9 #define ADS ":::AGSinject " VERSION " by rofl0r:::"
11 __attribute__((noreturn
))
12 void usage(char *argv0
) {
14 ADS
"\nusage:\n%s index input.o inject_to.crm\n"
15 "index is the number of script to replace, i.e. 0 for first script\n"
16 "only relevant if the output file is a gamefile which contains multiple scripts\n"
17 "for example gamescript is 0, dialogscript is 1 (if existing), etc\n"
18 "a room file (.crm) only has one script so you must pass 0.\n", argv0
);
22 /* inj = filename of file to inject in */
23 static int inject(char *o
, char *inj
, unsigned which
) {
27 int isroom
= !strcmp(".crm", inj
+ strlen(inj
) - 4);
28 if(isroom
&& which
!= 0) return -1;
29 if(!AF_open(f
, inj
)) return 0;
31 for(index
= found
= 0; 1 ; found
++, index
= start
+ 4) {
32 if(!isroom
&& (start
= ARF_find_code_start(f
, index
)) == -1) {
33 dprintf(2, "error, only %zu scripts found\n", found
);
36 /* use roomfile specific script lookup, as it's faster */
37 struct RoomFile rinfo
= {0};
38 if(!RoomFile_read(f
, &rinfo
)) return 0;
39 start
= rinfo
.blockpos
[BLOCKTYPE_COMPSCRIPT3
];
41 if(found
!= which
) continue;
42 char *tmp
= tempnam(".", "agsinject.tmp");
43 FILE *out
= fopen(tmp
, "w");
47 AF_dump_chunk_stream(f
, 0, isroom
? start
-4 : start
, out
);
50 /* open replacement object file */
53 ByteArray_open_file(&b
, o
);
56 /* 2a) if room, write length */
57 /* room files, unlike game files, have a length field of size 4 before
58 * the compiled script starts. */
59 unsigned l
= ByteArray_get_length(&b
);
62 ByteArray_open_mem(&c
, 0, 0);
63 ByteArray_set_flags(&c
, BAF_CANGROW
);
64 ByteArray_set_endian(&c
, BAE_LITTLE
);
65 ByteArray_writeInt(&c
, l
);
66 ByteArray_dump_to_stream(&c
, out
);
69 /* 2b) dump object file */
70 ByteArray_dump_to_stream(&b
, out
);
71 ByteArray_close_file(&b
);
74 if(!ASI_read_script(f
, &s
)) {
75 dprintf(2, "trouble finding script in %s\n", inj
);
78 /* 3) dump rest of file */
79 AF_dump_chunk_stream(f
, start
+ s
.len
, ByteArray_get_length(f
->b
) - (start
+ s
.len
), out
);
82 return !rename(tmp
, inj
);
87 int main(int argc
, char**argv
) {
88 if(argc
!= 4) usage(argv
[0]);
89 char *o
= argv
[2], *inj
= argv
[3], *p
;
90 if(!(p
= strrchr(o
, '.')) || strcmp(p
, ".o")) {
91 dprintf(2, "error: object file has no .o extension\n");
94 int which
= atoi(argv
[1]);
95 dprintf(1, "injecting %s into %s as %d'th script ...", o
, inj
, which
);
96 int ret
= inject(o
, inj
, which
);
97 if(ret
>= 0) dprintf(1, "OK\n");
101 dprintf(2, "invalid index %d for roomfile, only 0 possible\n", which
);
103 } else perror("error:");