11 * Another World script disassembler
12 * Only DOS version are supported
15 #define MSG_USAGE "usage: disasm [-a | -i | -u] [-p] OBJECT OUTFILE\n"
16 #define MSG_OPENERR "can't open file %s.\n"
17 #define MSG_WRITEERR "can't create file %s.\n"
18 #define MSG_INVALIDOP "invalid opcode 0x%X\n"
19 #define MSG_INVALIDJMP "invalid jump opcode %u\n"
29 struct labelinfo label
[MAX_LABEL
];
34 void (*printlabel
)(int);
35 void (*printopcode
)(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, int);
37 static uint8_t ubyte() {
41 static uint16_t uword() {
42 return (ubyte() << 8) | ubyte();
45 static int addlabel(uint16_t adr
, int type
) {
46 for(int i
= 0; i
< labelnum
; i
++) {
47 if(label
[i
].adr
== adr
)
51 label
[labelnum
].adr
= adr
;
52 label
[labelnum
].type
= type
;
57 static void fndlabel() {
58 for(int i
= 0; i
< labelnum
; i
++) {
59 if(label
[i
].adr
== pc
) {
75 uint16_t x
= -1, y
= -1, z
= -1, w
= -1;
78 if(op
& 0x80) { /* spr */
79 w
= (((op
<< 8) | ubyte()) << 1) & 0x7FFF;
82 } else if(op
& 0x40) { /* spr */
83 w
= (uword() << 1) & 0x7FFF;
87 x
= (x
<< 8) | ubyte();
88 else if((op
& 48) == 48)
93 y
= (y
<< 8) | ubyte();
95 if((op
& 3) == 1 || (op
& 3) == 2)
119 label
= addlabel(x
, LT_CALL
);
121 case 0x5: /* return */
123 case 0x6: /* break */
127 label
= addlabel(x
, LT_JUMP
);
129 case 0x8: /* setvec */
132 label
= addlabel(y
, LT_VEC
);
137 label
= addlabel(y
, LT_JUMP
);
151 printf(MSG_INVALIDJMP
, w
& 0x7);
156 label
= addlabel(z
, LT_JUMP
);
166 case 0xD: /* setws */
177 case 0x10: /* show */
180 case 0x11: /* bigend */
182 case 0x12: /* text */
192 case 0x14: /* andi */
208 case 0x18: /* play */
214 case 0x19: /* load */
217 case 0x1A: /* song */
223 printf(MSG_INVALIDOP
, op
);
229 printopcode(op
, x
, y
, z
, w
, label
);
232 static void readarg(int argc
, char **argv
) {
237 printlabel
= aw_printlabel
;
238 printopcode
= aw_printopcode
;
241 while((i
< argc
) && (argv
[i
][0] == '-')) {
242 if(strcmp("-a", argv
[i
]) == 0) {
243 printlabel
= aw_printlabel
;
244 printopcode
= aw_printopcode
;
245 } else if(strcmp("-i", argv
[i
]) == 0) {
246 printlabel
= intel_printlabel
;
247 printopcode
= intel_printopcode
;
248 } else if(strcmp("-u", argv
[i
]) == 0) {
249 printlabel
= att_printlabel
;
250 printopcode
= att_printopcode
;
251 } else if(strcmp("-p", argv
[i
]) == 0) {
264 output
= argv
[i
+ 1];
272 int main(int argc
, char **argv
) {
275 if((fp
= fopen(input
, "r")) == NULL
) {
276 printf(MSG_OPENERR
, input
);
280 fseek(fp
, 0, SEEK_END
);
281 codesize
= ftell(fp
);
282 fseek(fp
, 0, SEEK_SET
);
284 code
= malloc(codesize
);
285 fread(code
, codesize
, 1, fp
);
288 if((fp
= fopen(output
, "w")) == NULL
) {
289 printf(MSG_WRITEERR
, output
);
298 step(); /* read labels */
303 step(); /* print code */