8 void ADF_close(ADF
* a
) {
12 ASI
*ADF_get_global_script(ADF
* a
) {
13 return &a
->globalscript
;
16 ASI
*ADF_get_dialog_script(ADF
* a
) {
17 return &a
->dialogscript
;
20 ASI
*ADF_get_script(ADF
* a
, size_t index
) {
21 if(index
>= a
->scriptcount
) return 0;
22 return &a
->scripts
[index
];
25 size_t ADF_get_scriptcount(ADF
* a
) {
26 return a
->scriptcount
;
29 typedef enum interaction_type
{
35 static int ADF_read_interaction(ADF
*a
, interaction_type t
) {
36 /* deserialize_interaction_scripts */
37 static const size_t iter_start
[it_max
] = {
41 size_t *countmap
[it_max
] = {
42 [it_char
] = &a
->game
.charactercount
,
43 [it_inventory
] = &a
->game
.inventorycount
,
44 }, l
= *countmap
[t
], i
= iter_start
[t
];
47 size_t j
= 0, evcnt
= AF_read_uint(a
->f
);
48 for(; j
< evcnt
; j
++) {
49 if(!AF_read_string(a
->f
, buf
, 200)) return 0; /* function names of interaction scripts */
55 static int deserialize_command_list(ADF
*a
) {
56 size_t l
= AF_read_uint(a
->f
);
57 AF_read_uint(a
->f
); /*timesrun*/
60 assert(l
< sizeof(childs
));
61 for(i
= 0; i
< l
; i
++) {
62 AF_read_uint(a
->f
); // unused
63 AF_read_uint(a
->f
); // type
67 if(1 != AF_read(a
->f
, buf
, 1)) // valType
69 if(3 != AF_read(a
->f
, buf
, 3)) // padding
71 AF_read_uint(a
->f
); // val
72 AF_read_uint(a
->f
); // extra
74 childs
[i
] = !!AF_read_uint(a
->f
); // children
75 AF_read_uint(a
->f
); // parent
77 for(i
= 0; i
< l
; i
++) {
78 if(childs
[i
]) deserialize_command_list(a
);
83 static int ADF_read_interaction2x(ADF
*a
, interaction_type t
) {
84 /* deserialize_new_interaction */
85 size_t *countmap
[it_max
] = {
86 [it_char
] = &a
->game
.charactercount
,
87 [it_inventory
] = &a
->game
.inventorycount
,
88 }, l
= *countmap
[t
], i
= 0;
91 if(AF_read_uint(a
->f
) != 1) continue;
92 size_t evcnt
= AF_read_uint(a
->f
);
94 AF_read_junk(a
->f
, evcnt
* sizeof(int)); /*event types */
97 response
[j
] = AF_read_int(a
->f
);
98 for(j
= 0; j
< evcnt
; j
++)
100 if(!deserialize_command_list(a
))
107 static int ADF_read_gamebase(ADF
*a
) {
108 /* acroom.h: 2881. void ReadFile() */
112 l
= 50 /* game name */ + 2 /*padding*/;
113 if(!AF_read(a
->f
, game_name
, l
)) return 0;
115 if(!AF_read_junk(a
->f
, 100*4)) return 0;
116 l
= 256; /* 256 "paluses", unsigned char*/
117 if(!AF_read_junk(a
->f
, l
)) return 0;
118 l
= 256 * 4; /*sizeof color, read into defpal*/
119 if(!AF_read_junk(a
->f
, l
)) return 0;
120 a
->game
.viewcount
= AF_read_uint(a
->f
);
121 a
->game
.charactercount
= AF_read_uint(a
->f
);
122 AF_read_uint(a
->f
); /* character of player*/
123 AF_read_uint(a
->f
); /* totalscore*/
124 a
->game
.inventorycount
= AF_read_ushort(a
->f
);
125 AF_read_ushort(a
->f
); /* padding */
126 a
->game
.dialogcount
= AF_read_uint(a
->f
);
127 AF_read_uint(a
->f
); /* numdlgmessage*/
128 a
->game
.fontcount
= AF_read_uint(a
->f
);
129 AF_read_uint(a
->f
); /* color depth*/
130 AF_read_uint(a
->f
); /* target_win */
131 AF_read_uint(a
->f
);/* dialog_bullet */
132 AF_read_ushort(a
->f
);/* hotdot */
133 AF_read_ushort(a
->f
);/* hotdotouter */
134 AF_read_uint(a
->f
);/* uniqueid */
135 AF_read_uint(a
->f
);/* numgui */
136 a
->game
.cursorcount
= AF_read_uint(a
->f
);
137 x
= AF_read_uint(a
->f
);/* default_resolution */
138 if(a
->version
>= 43 /* 3.3.0 */ && x
== 8 /* custom resolution */) {
139 /* 2 ints with the custom width and height */
140 if(!AF_read_junk(a
->f
, 8)) return 0;
142 AF_read_uint(a
->f
);/* default_lipsync_frame */
143 AF_read_uint(a
->f
);/* invhotdotsprite */
144 l
= 4 * 17; /* reserved */
145 if(!AF_read_junk(a
->f
, l
)) return 0;
146 l
= 500 * 4 /* 500 global message numbers */;
147 if(!AF_read_junk(a
->f
, l
)) return 0;
148 a
->game
.hasdict
= !!AF_read_int(a
->f
);/* dict */
149 AF_read_uint(a
->f
);/* globalscript */
150 AF_read_uint(a
->f
);/* chars */
151 AF_read_uint(a
->f
);/* compiled_script */
155 static int ADF_read_dictionary(ADF
*a
) {
157 size_t i
,l
= AF_read_uint(a
->f
);
158 for(i
= 0; i
< l
; i
++) {
159 /* length of encrypted string */
160 size_t e
= AF_read_uint(a
->f
);
161 if(!AF_read_junk(a
->f
, e
)) return 0;
162 AF_read_short(a
->f
); /* wordnum */
168 static int ADF_read_view(ADF
*a
) {
173 static int ADF_read_view2x(ADF
*a
) {
178 int ADF_find_datafile(const char *dir
, char *fnbuf
, size_t flen
)
180 size_t l
= strlen(dir
);
181 if(l
>= flen
- 20) return 0;
182 memcpy(fnbuf
, dir
, l
);
185 memcpy(p
, "game28.dta", sizeof("game28.dta"));
187 if(!AF_open(&f
, fnbuf
)) {
188 memcpy(p
, "ac2game.dta", sizeof("ac2game.dta"));
189 if(!AF_open(&f
, fnbuf
)) return 0;
195 int ADF_open(ADF
* a
, const char *filename
) {
199 memset(a
, 0, sizeof(*a
));
202 if(!AF_open(a
->f
, filename
)) return 0;
204 if(30 != AF_read(a
->f
, fnbuf
, 30)) {
209 if(memcmp("Adventure Creator Game File v2", fnbuf
, 30)) goto err_close
;
210 a
->version
= AF_read_int(a
->f
);
211 /* here comes some version string with minor, major - we dont need it */
212 /* FIXME? newer ags does this only with version >= 12 */
213 /* 4 bytes containing the length of the string, followed by the string */
214 l
= AF_read_uint(a
->f
);
215 if(l
> 20) goto err_close
;
216 if(l
!= (size_t) AF_read(a
->f
, fnbuf
, l
)) goto err_close
;
218 /* main_game_file.cpp:OpenMainGameFileBase */
219 if(a
->version
>= 48 /* kGameVersion_341 */) {
220 /* latest ags now has placed an int here: number of required capabilities */
221 l
= AF_read_uint(a
->f
);
222 /* followed by l int/string pairs */
224 size_t len
= AF_read_uint(a
->f
);
225 if(!AF_read_junk(a
->f
, len
)) goto err_close
;
228 if(!ADF_read_gamebase(a
)) goto err_close
;
229 if(a
->version
> 32) {
230 l
= 40 /* guid */ + 20 /*savegame extension*/ + 50 /*savegame dir*/;
231 if(l
!= (size_t) AF_read(a
->f
, fnbuf
, l
)) goto err_close
;
233 if(a
->version
< 50 /* 3.5.0 */) {
234 l
= a
->game
.fontcount
* 2; /* fontflags and fontoutline arrays [each 1b/font] */
235 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
236 if(a
->version
>= 48) {
237 /* version == 3.4.1 have YOffset and versions >= 3.4.1.2 < 3.5.0 have YOffeset and LineSpacing ints */
238 l
= a
->game
.fontcount
* 4;
239 if(a
->version
== 49) l
*=2;
240 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
243 /* 3.5.0 has 5 ints per font, see gamesetupstruct.cpp */
244 l
= a
->game
.fontcount
* 4 * 5;
245 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
248 l
= a
->numsprites
= (a
->version
< 24) ? 6000 : AF_read_uint(a
->f
);
249 a
->spriteflagsstart
= AF_get_pos(a
->f
);
250 // array of spriteflags (1 char each, max: MAX_SPRITES==30000)
251 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
252 l
= 68 * a
->game
.inventorycount
; /* sizeof(InventoryItemInfo) */
253 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
255 l
= 24 /* sizeof(MouseCursor) */ * a
->game
.cursorcount
;
256 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
257 if(a
->version
> 32) {
258 if(!ADF_read_interaction(a
, it_char
)) goto err_close
;
259 if(!ADF_read_interaction(a
, it_inventory
)) goto err_close
;
261 if(!ADF_read_interaction2x(a
, it_char
)) goto err_close
;
262 if(!ADF_read_interaction2x(a
, it_inventory
)) goto err_close
;
263 a
->globalvarcount
= AF_read_uint(a
->f
);
264 l
= 28 /* sizeof(InteractionVariable)*/ * a
->globalvarcount
;
265 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
268 if(!ADF_read_dictionary(a
)) goto err_close
;
269 a
->scriptstart
= AF_get_pos(a
->f
);
270 if(!ASI_read_script(a
->f
, &a
->globalscript
)) goto err_close
;
272 if(!ASI_read_script(a
->f
, &a
->dialogscript
)) goto err_close
;
273 if(a
->version
>= 31) {
274 a
->scriptcount
= AF_read_uint(a
->f
);
275 for(l
= 0; l
< a
->scriptcount
; l
++)
276 if(!ASI_read_script(a
->f
, &a
->scripts
[l
])) goto err_close
;
278 a
->scriptend
= AF_get_pos(a
->f
);
279 /* at this point we have everything we need */
282 if(a
->version
> 31) {
283 for(l
= 0; l
< a
->game
.viewcount
; l
++)
284 if(!ADF_read_view(a
)) goto err_close
;
286 for(l
= 0; l
< a
->game
.viewcount
; l
++)
287 if(!ADF_read_view2x(a
)) goto err_close
;
289 if(a
->version
<= 19) {
291 l
= AF_read_uint(a
->f
) * 0x204;
292 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
294 /* ... we are around line 11977 in ac.cpp at this point*/