1 // $Id: git.c,v 1.21 2004/12/22 12:40:07 iain Exp $
8 // The four-char code 'FORM' as a big-endian value.
9 // This is the magic number at the start of Blorb files.
10 #define FORM 0x464f524d
12 static void gitMain (const git_uint8 * game, git_uint32 gameSize, git_uint32 cacheSize, git_uint32 undoSize)
15 enum IOMode ioMode = IO_NULL;
19 // Initialise the Glk dispatch layer.
22 // Set various globals.
26 // Load the gamefile into memory
27 // and initialise undo records.
28 initMemory (game, gameSize);
31 // Check that we're compatible with the
32 // glulx spec version that the game uses.
33 version = memRead32 (4);
34 if (version == 0x010000 && version <= 0x0100FF)
36 // We support version 1.0.0 even though it's
37 // officially obsolete. The only significant
38 // difference is the lack of I/O modes. In 1.0,
39 // all output goes directly to the Glk library.
42 else if (version == 0x020000 && version <= 0x0200FF)
44 // We support version 2.0, which most people currently use.
46 else if (version >= 0x030000 && version <= 0x0300FF)
48 // We support version 3.0, which adds Unicode functionality.
50 else if (version >= 0x030100 && version <= 0x0301FF)
52 // We support version 3.1, which adds some memory-management opcodes.
56 fatalError ("Can't run this game, because it uses a newer version "
57 "of the gamefile format than Git understands. You should check "
58 "whether a newer version of Git is available.");
61 // Call the top-level function.
62 startProgram (cacheSize, ioMode);
64 // Shut everything down cleanly.
69 static giblorb_result_t handleBlorb (strid_t stream)
72 giblorb_result_t blorbres;
75 err = giblorb_set_resource_map (stream);
78 case giblorb_err_None:
81 case giblorb_err_CompileTime:
82 fatalError ("Can't read the Blorb file because something is compiled wrong in the Blorb library.");
83 case giblorb_err_Alloc:
84 fatalError ("Can't read the Blorb file because there isn't enough memory available.");
85 case giblorb_err_Read:
86 fatalError ("Can't read data from the Blorb file.");
87 case giblorb_err_Format:
88 fatalError ("Can't read the Blorb file because it seems to be corrupted.");
90 fatalError ("Can't read the Blorb file because an unknown error occurred.");
93 map = giblorb_get_resource_map();
95 fatalError ("Can't find the Blorb file's resource map.");
97 err = giblorb_load_resource(map, giblorb_method_FilePos, &blorbres, giblorb_ID_Exec, 0);
99 fatalError ("This Blorb file does not contain an executable Glulx chunk.");
101 if (blorbres.chunktype != giblorb_make_id('G', 'L', 'U', 'L'))
102 fatalError ("This Blorb file contains an executable chunk, but it is not a Glulx file.");
107 void gitWithStream (strid_t str, git_uint32 cacheSize, git_uint32 undoSize)
113 git_uint32 remaining;
118 glk_stream_set_position (str, 0, seekmode_Start);
119 if (4 != glk_get_buffer_stream (str, buffer, 4))
120 fatalError ("can't read from game file stream");
122 if (read32 (buffer) == FORM)
124 giblorb_result_t result = handleBlorb (str);
125 gamePos = result.data.startpos;
126 gameSize = result.length;
131 glk_stream_set_position (str, 0, seekmode_End);
132 gameSize = glk_stream_get_position (str);
135 game = malloc (gameSize);
137 fatalError ("failed to allocate memory to store game file");
139 glk_stream_set_position (str, gamePos, seekmode_Start);
141 remaining = gameSize;
143 while (remaining > 0)
145 git_uint32 n = glk_get_buffer_stream (str, ptr, remaining);
147 fatalError ("failed to read entire game file");
152 gitMain ((git_uint8 *) game, gameSize, cacheSize, undoSize);
156 void git (const git_uint8 * game, git_uint32 gameSize, git_uint32 cacheSize, git_uint32 undoSize)
158 // If this is a blorb file, register it
159 // with glk and find the gamefile chunk.
161 if (read32 (game) == FORM)
164 giblorb_result_t result;
166 stream = glk_stream_open_memory ((char *) game, gameSize, filemode_Read, 0);
168 fatalError ("Can't open the Blorb file as a Glk memory stream.");
170 result = handleBlorb (stream);
171 game += result.data.startpos;
172 gameSize = result.length;
175 gitMain (game, gameSize, cacheSize, undoSize);