Mercurial > repos > blastem
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) { |