agssim: fix bugs emitting strings with a size divisible by 4
[rofl0r-agsutils.git] / RoomFile.c
blob84f72fa699800bc743c2042c77498c3beb4cbed7
1 #include "RoomFile.h"
2 #include <stdlib.h>
4 ssize_t ARF_find_code_start(AF* f, size_t start) {
5 if(!AF_set_pos(f, start)) return -1;
6 char buf[4];
7 unsigned match = 0;
8 while(1) {
9 if(AF_read(f, buf, 1) != 1) break;;
10 switch(match) {
11 case 0:
12 if(*buf == 'S') match++;
13 else match = 0;
14 break;
15 case 1:
16 if(*buf == 'C') match++;
17 else match = 0;
18 break;
19 case 2:
20 if(*buf == 'O') match++;
21 else match = 0;
22 break;
23 case 3:
24 if(*buf == 'M') return AF_get_pos(f) - 4;
25 else match = 0;
26 break;
27 default:
28 assert(0);
31 return -1;
34 static void roomfile_decrypt_text(char *s, int len) {
35 unsigned i = 0;
36 while (i < len) {
37 *s += "Avis Durgan"[i % 11];
38 if (!*s) break;
39 ++i; ++s;
43 char *RoomFile_extract_source(AF *f, struct RoomFile *r, size_t *sizep) {
44 *sizep = 0;
45 off_t pos = r->blockpos[BLOCKTYPE_SCRIPT];
46 if(!pos || !AF_set_pos(f, pos)) return 0;
47 int scriptlen = AF_read_int(f);
48 assert(r->blocklen[BLOCKTYPE_SCRIPT] == scriptlen + 4);
49 char* out = malloc(scriptlen+1);
50 if(!out) return out;
51 if((size_t) -1 == AF_read(f, out, scriptlen)) {
52 free(out);
53 return 0;
55 *sizep = scriptlen;
56 roomfile_decrypt_text(out, scriptlen);
57 out[scriptlen] = 0;
58 return out;
62 int RoomFile_read(AF *f, struct RoomFile *r) {
63 if(!AF_set_pos(f, 0)) return 0;
64 r->version = AF_read_short(f);
65 while(1) {
66 unsigned char blocktype;
67 if((size_t) -1 == AF_read(f, &blocktype, 1)) return 0;
68 if(blocktype == BLOCKTYPE_EOF) break;
69 if(blocktype < BLOCKTYPE_MIN || blocktype > BLOCKTYPE_MAX) return 0;
70 int blocklen = AF_read_int(f);
71 off_t curr_pos = AF_get_pos(f), next_block = curr_pos + blocklen;
72 r->blockpos[blocktype] = curr_pos;
73 r->blocklen[blocktype] = blocklen;
74 switch(blocktype) {
75 case BLOCKTYPE_COMPSCRIPT3:
77 char sig[4];
78 AF_read(f, sig, 4);
79 assert(!memcmp(sig, "SCOM", 4));
81 break;
82 /* the older script types weren't supported by the released AGS sources ever */
83 default:
84 break;
86 if(!AF_set_pos(f, next_block)) return 0;
88 return 1;