Implemented the 'waiting' signal on the ChimaraGlk widget to let listeners know when...
[projects/chimara/chimara.git] / interpreters / glulxe / files.c
1 /* files.c: Glulxe file-handling code.
2     Designed by Andrew Plotkin <erkyrath@eblong.com>
3     http://eblong.com/zarf/glulx/index.html
4 */
5
6 #include "glk.h"
7 #include "gi_blorb.h"
8 #include "glulxe.h"
9
10 /* is_gamefile_valid():
11    Check guess what.
12 */
13 int is_gamefile_valid()
14 {
15   unsigned char buf[8];
16   int res;
17   glui32 version;
18
19   glk_stream_set_position(gamefile, gamefile_start, seekmode_Start);
20   res = glk_get_buffer_stream(gamefile, (char *)buf, 8);
21
22   if (res != 8) {
23     fatal_error("This is too short to be a valid Glulx file.");
24     return FALSE;
25   }
26
27   if (buf[0] != 'G' || buf[1] != 'l' || buf[2] != 'u' || buf[3] != 'l') {
28     fatal_error("This is not a valid Glulx file.");
29     return FALSE;
30   }
31
32   /* We support version 2.0 through 3.1.*. */
33
34   version = Read4(buf+4);
35   if (version < 0x20000) {
36     fatal_error("This Glulx file is too old a version to execute.");
37     return FALSE;
38   }
39   if (version >= 0x30200) {
40     fatal_error("This Glulx file is too new a version to execute.");
41     return FALSE;
42   }
43
44   return TRUE;
45 }
46
47 /* locate_gamefile: 
48    Given that gamefile contains a Glk stream, which may be a Glulx
49    file or a Blorb archive containing one, locate the beginning and
50    end of the Glulx data.
51 */
52 int locate_gamefile(int isblorb)
53 {
54   if (!isblorb) {
55     /* The simple case. A bare Glulx file was opened, so we don't use
56        Blorb at all. */
57     gamefile_start = 0;
58     glk_stream_set_position(gamefile, 0, seekmode_End);
59     gamefile_len = glk_stream_get_position(gamefile);
60     return TRUE;
61   }
62   else {
63     /* A Blorb file. We now have to open it and find the Glulx chunk. */
64     giblorb_err_t err;
65     giblorb_result_t blorbres;
66     giblorb_map_t *map;
67
68     err = giblorb_set_resource_map(gamefile);
69     if (err) {
70       init_err = "This Blorb file seems to be invalid.";
71       return FALSE;
72     }
73     map = giblorb_get_resource_map();
74     err = giblorb_load_resource(map, giblorb_method_FilePos, 
75       &blorbres, giblorb_ID_Exec, 0);
76     if (err) {
77       init_err = "This Blorb file does not contain an executable Glulx chunk.";
78       return FALSE;
79     }
80     if (blorbres.chunktype != giblorb_make_id('G', 'L', 'U', 'L')) {
81       init_err = "This Blorb file contains an executable chunk, but it is not a Glulx file.";
82       return FALSE;
83     }
84     gamefile_start = blorbres.data.startpos;
85     gamefile_len = blorbres.length;
86     return TRUE;
87   }
88 }
89