8 void ADF_init(ADF
* a
, char* dir
) {
9 memset(a
, 0, sizeof(*a
));
14 void ADF_close(ADF
* a
) {
18 ASI
*ADF_get_global_script(ADF
* a
) {
19 return &a
->globalscript
;
22 ASI
*ADF_get_dialog_script(ADF
* a
) {
23 return &a
->dialogscript
;
26 ASI
*ADF_get_script(ADF
* a
, size_t index
) {
27 if(index
>= a
->scriptcount
) return 0;
28 return &a
->scripts
[index
];
31 size_t ADF_get_scriptcount(ADF
* a
) {
32 return a
->scriptcount
;
35 typedef enum interaction_type
{
41 static int ADF_read_interaction(ADF
*a
, interaction_type t
) {
42 /* deserialize_interaction_scripts */
43 static const size_t iter_start
[it_max
] = {
47 size_t *countmap
[it_max
] = {
48 [it_char
] = &a
->game
.charactercount
,
49 [it_inventory
] = &a
->game
.inventorycount
,
50 }, l
= *countmap
[t
], i
= iter_start
[t
];
53 size_t j
= 0, evcnt
= AF_read_uint(a
->f
);
54 for(; j
< evcnt
; j
++) {
55 if(!AF_read_string(a
->f
, buf
, 200)) return 0; /* function names of interaction scripts */
61 static int deserialize_command_list(ADF
*a
) {
62 size_t l
= AF_read_uint(a
->f
);
63 AF_read_uint(a
->f
); /*timesrun*/
66 assert(l
< sizeof(childs
));
67 for(i
= 0; i
< l
; i
++) {
68 AF_read_uint(a
->f
); // unused
69 AF_read_uint(a
->f
); // type
73 if(1 != AF_read(a
->f
, buf
, 1)) // valType
75 if(3 != AF_read(a
->f
, buf
, 3)) // padding
77 AF_read_uint(a
->f
); // val
78 AF_read_uint(a
->f
); // extra
80 childs
[i
] = !!AF_read_uint(a
->f
); // children
81 AF_read_uint(a
->f
); // parent
83 for(i
= 0; i
< l
; i
++) {
84 if(childs
[i
]) deserialize_command_list(a
);
89 static int ADF_read_interaction2x(ADF
*a
, interaction_type t
) {
90 /* deserialize_new_interaction */
91 size_t *countmap
[it_max
] = {
92 [it_char
] = &a
->game
.charactercount
,
93 [it_inventory
] = &a
->game
.inventorycount
,
94 }, l
= *countmap
[t
], i
= 0;
97 if(AF_read_uint(a
->f
) != 1) continue;
98 size_t evcnt
= AF_read_uint(a
->f
);
100 AF_read_junk(a
->f
, evcnt
* sizeof(int)); /*event types */
102 for(; j
< evcnt
; j
++)
103 response
[j
] = AF_read_int(a
->f
);
104 for(j
= 0; j
< evcnt
; j
++)
106 if(!deserialize_command_list(a
))
113 static int ADF_read_gamebase(ADF
*a
) {
114 /* acroom.h: 2881. void ReadFile() */
118 l
= 50 /* game name */ + 2 /*padding*/;
119 if(!AF_read(a
->f
, game_name
, l
)) return 0;
121 if(!AF_read_junk(a
->f
, 100*4)) return 0;
122 l
= 256; /* 256 "paluses", unsigned char*/
123 if(!AF_read_junk(a
->f
, l
)) return 0;
124 l
= 256 * 4; /*sizeof color, read into defpal*/
125 if(!AF_read_junk(a
->f
, l
)) return 0;
126 a
->game
.viewcount
= AF_read_uint(a
->f
);
127 a
->game
.charactercount
= AF_read_uint(a
->f
);
128 AF_read_uint(a
->f
); /* character of player*/
129 AF_read_uint(a
->f
); /* totalscore*/
130 a
->game
.inventorycount
= AF_read_ushort(a
->f
);
131 AF_read_ushort(a
->f
); /* padding */
132 a
->game
.dialogcount
= AF_read_uint(a
->f
);
133 AF_read_uint(a
->f
); /* numdlgmessage*/
134 a
->game
.fontcount
= AF_read_uint(a
->f
);
135 AF_read_uint(a
->f
); /* color depth*/
136 AF_read_uint(a
->f
); /* target_win */
137 AF_read_uint(a
->f
);/* dialog_bullet */
138 AF_read_ushort(a
->f
);/* hotdot */
139 AF_read_ushort(a
->f
);/* hotdotouter */
140 AF_read_uint(a
->f
);/* uniqueid */
141 AF_read_uint(a
->f
);/* numgui */
142 a
->game
.cursorcount
= AF_read_uint(a
->f
);
143 x
= AF_read_uint(a
->f
);/* default_resolution */
144 if(a
->version
>= 43 /* 3.3.0 */ && x
== 8 /* custom resolution */) {
145 /* 2 ints with the custom width and height */
146 if(!AF_read_junk(a
->f
, 8)) return 0;
148 AF_read_uint(a
->f
);/* default_lipsync_frame */
149 AF_read_uint(a
->f
);/* invhotdotsprite */
150 l
= 4 * 17; /* reserved */
151 if(!AF_read_junk(a
->f
, l
)) return 0;
152 l
= 500 * 4 /* 500 global message numbers */;
153 if(!AF_read_junk(a
->f
, l
)) return 0;
154 a
->game
.hasdict
= !!AF_read_int(a
->f
);/* dict */
155 AF_read_uint(a
->f
);/* globalscript */
156 AF_read_uint(a
->f
);/* chars */
157 AF_read_uint(a
->f
);/* compiled_script */
161 static int ADF_read_dictionary(ADF
*a
) {
163 size_t i
,l
= AF_read_uint(a
->f
);
164 for(i
= 0; i
< l
; i
++) {
165 /* length of encrypted string */
166 size_t e
= AF_read_uint(a
->f
);
167 if(!AF_read_junk(a
->f
, e
)) return 0;
168 AF_read_short(a
->f
); /* wordnum */
174 static int ADF_read_view(ADF
*a
) {
179 static int ADF_read_view2x(ADF
*a
) {
184 int ADF_open(ADF
* a
) {
186 size_t l
= strlen(a
->dir
), i
;
187 if(l
>= sizeof(fnbuf
) - 20) return 0;
188 memcpy(fnbuf
, a
->dir
, l
);
191 memcpy(p
, "game28.dta", sizeof("game28.dta"));
192 if(!AF_open(a
->f
, fnbuf
)) {
193 memcpy(p
, "ac2game.dta", sizeof("ac2game.dta"));
194 if(!AF_open(a
->f
, fnbuf
)) return 0;
197 if(30 != AF_read(a
->f
, fnbuf
, 30)) {
202 if(memcmp("Adventure Creator Game File v2", fnbuf
, 30)) goto err_close
;
203 a
->version
= AF_read_int(a
->f
);
204 /* here comes some version string with minor, major - we dont need it */
205 /* FIXME? newer ags does this only with version >= 12 */
206 /* 4 bytes containing the length of the string, followed by the string */
207 l
= AF_read_uint(a
->f
);
208 if(l
> 20) goto err_close
;
209 if(l
!= (size_t) AF_read(a
->f
, fnbuf
, l
)) goto err_close
;
211 /* main_game_file.cpp:OpenMainGameFileBase */
212 if(a
->version
>= 48 /* kGameVersion_341 */) {
213 /* latest ags now has placed an int here: number of required capabilities */
214 l
= AF_read_uint(a
->f
);
215 /* followed by l int/string pairs */
217 size_t len
= AF_read_uint(a
->f
);
218 if(!AF_read_junk(a
->f
, len
)) goto err_close
;
221 if(!ADF_read_gamebase(a
)) goto err_close
;
222 if(a
->version
> 32) {
223 l
= 40 /* guid */ + 20 /*savegame extension*/ + 50 /*savegame dir*/;
224 if(l
!= (size_t) AF_read(a
->f
, fnbuf
, l
)) goto err_close
;
226 if(a
->version
< 50 /* 3.5.0 */) {
227 l
= a
->game
.fontcount
* 2; /* fontflags and fontoutline arrays [each 1b/font] */
228 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
229 if(a
->version
>= 48) {
230 /* version == 3.4.1 have YOffset and versions >= 3.4.1.2 < 3.5.0 have YOffeset and LineSpacing ints */
231 l
= a
->game
.fontcount
* 4;
232 if(a
->version
== 49) l
*=2;
233 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
236 /* 3.5.0 has 5 ints per font, see gamesetupstruct.cpp */
237 l
= a
->game
.fontcount
* 4 * 5;
238 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
241 l
= (a
->version
< 24) ? 6000 : AF_read_uint(a
->f
);
242 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
243 l
= 68 * a
->game
.inventorycount
; /* sizeof(InventoryItemInfo) */
244 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
246 l
= 24 /* sizeof(MouseCursor) */ * a
->game
.cursorcount
;
247 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
248 if(a
->version
> 32) {
249 if(!ADF_read_interaction(a
, it_char
)) goto err_close
;
250 if(!ADF_read_interaction(a
, it_inventory
)) goto err_close
;
252 if(!ADF_read_interaction2x(a
, it_char
)) goto err_close
;
253 if(!ADF_read_interaction2x(a
, it_inventory
)) goto err_close
;
254 a
->globalvarcount
= AF_read_uint(a
->f
);
255 l
= 28 /* sizeof(InteractionVariable)*/ * a
->globalvarcount
;
256 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
259 if(!ADF_read_dictionary(a
)) goto err_close
;
260 a
->scriptstart
= AF_get_pos(a
->f
);
261 if(!ASI_read_script(a
->f
, &a
->globalscript
)) goto err_close
;
263 if(!ASI_read_script(a
->f
, &a
->dialogscript
)) goto err_close
;
264 if(a
->version
>= 31) {
265 a
->scriptcount
= AF_read_uint(a
->f
);
266 for(l
= 0; l
< a
->scriptcount
; l
++)
267 if(!ASI_read_script(a
->f
, &a
->scripts
[l
])) goto err_close
;
269 a
->scriptend
= AF_get_pos(a
->f
);
270 /* at this point we have everything we need */
273 if(a
->version
> 31) {
274 for(l
= 0; l
< a
->game
.viewcount
; l
++)
275 if(!ADF_read_view(a
)) goto err_close
;
277 for(l
= 0; l
< a
->game
.viewcount
; l
++)
278 if(!ADF_read_view2x(a
)) goto err_close
;
280 if(a
->version
<= 19) {
282 l
= AF_read_uint(a
->f
) * 0x204;
283 if(!AF_read_junk(a
->f
, l
)) goto err_close
;
285 /* ... we are around line 11977 in ac.cpp at this point*/