comparison dis.c @ 2085:1ff67ce37085

Add some Sega CD specific enhancements to disassembler
author Michael Pavone <pavone@retrodev.com>
date Sat, 05 Feb 2022 16:38:39 -0800
parents 460e14497120
children 36a9cf4db65f
comparison
equal deleted inserted replaced
2084:c9d3b8e1ea56 2085:1ff67ce37085
52 } 52 }
53 53
54 typedef struct { 54 typedef struct {
55 uint32_t num_labels; 55 uint32_t num_labels;
56 uint32_t storage; 56 uint32_t storage;
57 uint32_t full_address;
57 char *labels[]; 58 char *labels[];
58 } label_names; 59 } label_names;
59 60
60 tern_node * add_label(tern_node * head, char * name, uint32_t address) 61 tern_node * weak_label(tern_node * head, const char *name, uint32_t address)
61 { 62 {
62 char key[MAX_INT_KEY_SIZE]; 63 char key[MAX_INT_KEY_SIZE];
63 address &= 0xFFFFFF; 64 tern_int_key(address & 0xFFFFFF, key);
64 reference(address);
65 tern_int_key(address, key);
66 label_names * names = tern_find_ptr(head, key); 65 label_names * names = tern_find_ptr(head, key);
67 if (names) 66 if (names)
68 { 67 {
69 if (names->num_labels == names->storage) 68 if (names->num_labels == names->storage)
70 { 69 {
76 names->num_labels = 0; 75 names->num_labels = 0;
77 names->storage = 4; 76 names->storage = 4;
78 head = tern_insert_ptr(head, key, names); 77 head = tern_insert_ptr(head, key, names);
79 } 78 }
80 names->labels[names->num_labels++] = strdup(name); 79 names->labels[names->num_labels++] = strdup(name);
80 names->full_address = address;
81 return head; 81 return head;
82 }
83 tern_node *add_label(tern_node * head, const char *name, uint32_t address)
84 {
85 reference(address);
86 return weak_label(head, name, address);
82 } 87 }
83 88
84 typedef struct deferred { 89 typedef struct deferred {
85 uint32_t address; 90 uint32_t address;
86 struct deferred *next; 91 struct deferred *next;
152 157
153 uint8_t labels = 0, addr = 0, only = 0, vos = 0, reset = 0; 158 uint8_t labels = 0, addr = 0, only = 0, vos = 0, reset = 0;
154 tern_node * named_labels = NULL; 159 tern_node * named_labels = NULL;
155 160
156 uint32_t address_off = 0, address_end; 161 uint32_t address_off = 0, address_end;
162 uint8_t do_cd_labels = 0;
157 for(uint8_t opt = 2; opt < argc; ++opt) { 163 for(uint8_t opt = 2; opt < argc; ++opt) {
158 if (argv[opt][0] == '-') { 164 if (argv[opt][0] == '-') {
159 FILE * address_log; 165 FILE * address_log;
160 switch (argv[opt][1]) 166 switch (argv[opt][1])
161 { 167 {
171 case 'v': 177 case 'v':
172 vos = 1; 178 vos = 1;
173 break; 179 break;
174 case 'r': 180 case 'r':
175 reset = 1; 181 reset = 1;
182 break;
183 case 'c':
184 do_cd_labels = 1;
176 break; 185 break;
177 case 's': 186 case 's':
178 opt++; 187 opt++;
179 if (opt >= argc) { 188 if (opt >= argc) {
180 fputs("-s must be followed by an offset\n", stderr); 189 fputs("-s must be followed by an offset\n", stderr);
255 if (reset) 264 if (reset)
256 { 265 {
257 def = defer(filebuf[2] << 16 | filebuf[3], def); 266 def = defer(filebuf[2] << 16 | filebuf[3], def);
258 named_labels = add_label(named_labels, "reset", filebuf[2] << 16 | filebuf[3]); 267 named_labels = add_label(named_labels, "reset", filebuf[2] << 16 | filebuf[3]);
259 } 268 }
260 } else { 269 } else if (filesize > 0x1000) {
261 address_end = address_off + filesize; 270 long boot_size = filesize > (32*1024) ? 32*1024 : filesize;
262 filebuf = malloc(filesize); 271 filebuf = malloc(boot_size);
263 if (fread(filebuf, 2, filesize/2, f) != filesize/2) 272 if (fread(filebuf, 1, boot_size, f) != boot_size) {
264 {
265 fprintf(stderr, "Failure while reading file %s\n", argv[1]); 273 fprintf(stderr, "Failure while reading file %s\n", argv[1]);
266 } 274 return 1;
267 fclose(f); 275 }
268 for(cur = filebuf; cur - filebuf < (filesize/2); ++cur) 276 uint8_t is_scd_iso = !memcmp("SEGADISCSYSTEM ", filebuf, 0x10);
269 { 277 if (!is_scd_iso && !memcmp("SEGADISCSYSTEM ", filebuf + 0x8, 0x10)) {
270 *cur = (*cur >> 8) | (*cur << 8); 278 is_scd_iso = 1;
271 } 279 uint32_t end = 16 * 2352;
272 if (!address_off) { 280 if (end > filesize) {
273 uint32_t start = filebuf[2] << 16 | filebuf[3]; 281 end = (filesize / 2352) * 2352;
274 uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2]; 282 }
275 uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2]; 283 for(uint32_t offset = 0x10, dst_offset = 0; offset < end; offset += 2352, dst_offset += 2048)
276 uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2]; 284 {
277 named_labels = add_label(named_labels, "start", start); 285 memmove(filebuf + dst_offset/2, filebuf + offset/2, 2048);
278 named_labels = add_label(named_labels, "int_2", int_2); 286 }
279 named_labels = add_label(named_labels, "int_4", int_4); 287 boot_size = (end / 2352) * 2048;
280 named_labels = add_label(named_labels, "int_6", int_6); 288 }
281 if (!def || !only) { 289 if (is_scd_iso) {
282 def = defer(start, def); 290 for(cur = filebuf; cur - filebuf < (boot_size/2); ++cur)
283 def = defer(int_2, def); 291 {
284 def = defer(int_4, def); 292 *cur = (*cur >> 8) | (*cur << 8);
285 def = defer(int_6, def); 293 }
286 } 294 uint32_t sub_start =filebuf[0x40/2] << 16 | filebuf[0x42/2];
287 } 295 uint32_t sub_end =filebuf[0x44/2] << 16 | filebuf[0x46/2];
296 if (sub_start > (boot_size - 0x20)) {
297 fprintf(stderr, "System Program start offset is %X, but image is only %X bytes\n", sub_start, (uint32_t)boot_size);
298 return 1;
299 }
300 if (sub_end > boot_size) {
301 sub_end = boot_size;
302 }
303 uint32_t offset_start = (filebuf[(sub_start + 0x18)/2] << 16 | filebuf[(sub_start + 0x1A)/2]) + sub_start;
304 uint8_t has_manual_defs = !!def;
305 for(uint32_t cur = offset_start, index = 0; cur < sub_end && filebuf[cur/2]; cur+=2, ++index)
306 {
307 uint32_t offset = offset_start + filebuf[cur/2];
308 if (offset >= boot_size) {
309 break;
310 }
311 static const char* fixed_names[3] = {
312 "init",
313 "main",
314 "int_2"
315 };
316 char namebuf[32];
317 const char *name;
318 if (index < 3) {
319 name = fixed_names[index];
320 } else {
321 name = namebuf;
322 sprintf(namebuf, "usercall%u", index);
323 }
324 uint32_t address = 0x6000 + offset - sub_start;
325 named_labels = add_label(named_labels, name, address);
326 if (!has_manual_defs || !only) {
327 def = defer(address, def);
328 }
329 }
330 do_cd_labels = 1;
331 filebuf += sub_start / 2;
332 address_off = 0x6000;
333 address_end = sub_end-sub_start + address_off;
334 } else {
335 if (filesize > (32*1024)) {
336 filebuf = realloc(f, filesize);
337 fseek(f, 32*1024, SEEK_SET);
338 uint32_t to_read = filesize/2 - 16*1024;
339 if (fread(filebuf, 2, to_read, f) != to_read)
340 {
341 fprintf(stderr, "Failure while reading file %s\n", argv[1]);
342 }
343 }
344 address_end = address_off + filesize;
345 fclose(f);
346 for(cur = filebuf; cur - filebuf < (filesize/2); ++cur)
347 {
348 *cur = (*cur >> 8) | (*cur << 8);
349 }
350 if (!address_off) {
351 uint32_t start = filebuf[2] << 16 | filebuf[3];
352 uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2];
353 uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2];
354 uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2];
355 named_labels = add_label(named_labels, "start", start);
356 named_labels = add_label(named_labels, "int_2", int_2);
357 named_labels = add_label(named_labels, "int_4", int_4);
358 named_labels = add_label(named_labels, "int_6", int_6);
359 if (!def || !only) {
360 def = defer(start, def);
361 def = defer(int_2, def);
362 def = defer(int_4, def);
363 def = defer(int_6, def);
364 }
365 }
366 }
367 }
368 if (do_cd_labels) {
369 named_labels = weak_label(named_labels, "bios_common_work", 0x5E80);
370 named_labels = weak_label(named_labels, "_setjmptbl", 0x5F0A);
371 named_labels = weak_label(named_labels, "_waitvsync", 0x5F10);
372 named_labels = weak_label(named_labels, "_buram", 0x5F16);
373 named_labels = weak_label(named_labels, "_cdboot", 0x5F1C);
374 named_labels = weak_label(named_labels, "_cdbios", 0x5F22);
375 named_labels = weak_label(named_labels, "_usercall0", 0x5F28);
376 named_labels = weak_label(named_labels, "_usercall1", 0x5F2E);
377 named_labels = weak_label(named_labels, "_usercall2", 0x5F34);
378 named_labels = weak_label(named_labels, "_usercall2Address", 0x5F36);
379 named_labels = weak_label(named_labels, "_usercall3", 0x5F3A);
380 named_labels = weak_label(named_labels, "_slevel1", 0x5F76);
381 named_labels = weak_label(named_labels, "_slevel1Address", 0x5F78);
382 named_labels = weak_label(named_labels, "_slevel2", 0x5F7C);
383 named_labels = weak_label(named_labels, "_slevel2Address", 0x5F7E);
384 named_labels = weak_label(named_labels, "_slevel3", 0x5F82);
385 named_labels = weak_label(named_labels, "_slevel3Address", 0x5F84);
386 named_labels = weak_label(named_labels, "LED_CONTROL", 0xFFFF8000);
387 named_labels = weak_label(named_labels, "VERSION_RESET", 0xFFFF8001);
388 named_labels = weak_label(named_labels, "MEM_MODE_WORD", 0xFFFF8002);
389 named_labels = weak_label(named_labels, "MEM_MODE_BYTE", 0xFFFF8003);
390 named_labels = weak_label(named_labels, "CDC_CTRL", 0xFFFF8004);
391 named_labels = weak_label(named_labels, "CDC_AR", 0xFFFF8005);
392 named_labels = weak_label(named_labels, "CDC_REG_DATA_WORD", 0xFFFF8006);
393 named_labels = weak_label(named_labels, "CDC_REG_DATA", 0xFFFF8007);
394 named_labels = weak_label(named_labels, "CDC_HOST_DATA", 0xFFFF8008);
395 named_labels = weak_label(named_labels, "CDC_DMA_ADDR", 0xFFFF800A);
396 named_labels = weak_label(named_labels, "COMM_CMD0", 0xFFFF8010);
397 named_labels = weak_label(named_labels, "COMM_CMD1", 0xFFFF8012);
398 named_labels = weak_label(named_labels, "COMM_CMD2", 0xFFFF8014);
399 named_labels = weak_label(named_labels, "COMM_CMD3", 0xFFFF8016);
400 named_labels = weak_label(named_labels, "COMM_CMD4", 0xFFFF8018);
401 named_labels = weak_label(named_labels, "COMM_CMD5", 0xFFFF801A);
402 named_labels = weak_label(named_labels, "COMM_CMD6", 0xFFFF801C);
403 named_labels = weak_label(named_labels, "COMM_CMD7", 0xFFFF801E);
404 named_labels = weak_label(named_labels, "COMM_STATUS0", 0xFFFF8020);
405 named_labels = weak_label(named_labels, "COMM_STATUS1", 0xFFFF8022);
406 named_labels = weak_label(named_labels, "COMM_STATUS2", 0xFFFF8024);
407 named_labels = weak_label(named_labels, "COMM_STATUS3", 0xFFFF8026);
408 named_labels = weak_label(named_labels, "COMM_STATUS4", 0xFFFF8028);
409 named_labels = weak_label(named_labels, "COMM_STATUS5", 0xFFFF802A);
410 named_labels = weak_label(named_labels, "COMM_STATUS6", 0xFFFF802C);
411 named_labels = weak_label(named_labels, "COMM_STATUS7", 0xFFFF802E);
412 named_labels = weak_label(named_labels, "TIMER_WORD", 0xFFFF8030);
413 named_labels = weak_label(named_labels, "TIMER", 0xFFFF8031);
414 named_labels = weak_label(named_labels, "INT_MASK_WORD", 0xFFFF8032);
415 named_labels = weak_label(named_labels, "INT_MASK", 0xFFFF8033);
288 } 416 }
289 uint16_t *encoded, *next; 417 uint16_t *encoded, *next;
290 uint32_t size, tmp_addr; 418 uint32_t size, tmp_addr;
291 uint32_t address; 419 uint32_t address;
292 while(def) { 420 while(def) {
357 } 485 }
358 } 486 }
359 if (labels) { 487 if (labels) {
360 for (address = 0; address < address_off; address++) { 488 for (address = 0; address < address_off; address++) {
361 if (is_label(address)) { 489 if (is_label(address)) {
362 printf("ADR_%X equ $%X\n", address, address); 490 char key[MAX_INT_KEY_SIZE];
363 } 491 tern_int_key(address, key);
364 } 492 label_names *names = tern_find_ptr(named_labels, key);
365 for (address = filesize; address < (16*1024*1024); address++) { 493 if (names) {
366 char key[MAX_INT_KEY_SIZE]; 494 for (int i = 0; i < names->num_labels; i++)
367 tern_int_key(address, key); 495 {
368 label_names *names = tern_find_ptr(named_labels, key); 496 printf("%s equ $%X\n", names->labels[i], address);
369 if (names) { 497 }
370 for (int i = 0; i < names->num_labels; i++) 498 } else {
371 { 499 printf("ADR_%X equ $%X\n", address, address);
372 printf("%s equ $%X\n", names->labels[i], address); 500 }
373 } 501 }
374 } else if (is_label(address)) { 502 }
375 printf("ADR_%X equ $%X\n", address, address); 503 for (address = address_end; address < (16*1024*1024); address++) {
504 if (is_label(address)) {
505 char key[MAX_INT_KEY_SIZE];
506 tern_int_key(address, key);
507 label_names *names = tern_find_ptr(named_labels, key);
508 if (names) {
509 for (int i = 0; i < names->num_labels; i++)
510 {
511 printf("%s equ $%X\n", names->labels[i], names->full_address);
512 }
513 } else {
514 printf("ADR_%X equ $%X\n", address, address);
515 }
376 } 516 }
377 } 517 }
378 puts(""); 518 puts("");
379 } 519 }
380 for (address = address_off; address < address_end; address+=2) { 520 for (address = address_off; address < address_end; address+=2) {