Repository navigation
Expand file tree
/
Copy pathdisassembler.c
More file actions
153 lines (130 loc) · 4.74 KB
/
Copy pathdisassembler.c
File metadata and controls
153 lines (130 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* disassemler.c
* disassembler main loop
* Created 230900 by James Churchill
* Updated 190924 by Tim Böttiger
* Last Modified 081025
*/
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include "config.h"
#include "dispel.h"
unsigned long openFiles(const char *infile, const char *outfile, FILE **fin, FILE **fout) {
*fin = fopen(infile, "rb");
if (!*fin) {
if (!flagged(SILENT))
printf("Cannot open %s for reading.\n", infile);
exit(1);
}
if (strcmp(outfile, "stdout") == 0) {
*fout = stdout;
} else {
*fout = fopen(outfile, "w");
if (!*fout) {
if (!flagged(SILENT))
printf("Cannot open %s for writing.\n", outfile);
exit(1);
}
}
return getFileLength(fin);
}
void load_data(FILE **fin, unsigned long len, unsigned char **data) {
fread(*data, len, 1, *fin);
fclose(*fin);
}
int close_files(FILE **fout, unsigned char **data) {
fclose(*fout);
free(*data);
return 0;
}
int process_file(void)
{
unsigned long pos = 0, origin = 0x1000000, start = 0, end = 0;
unsigned char hirom = 2, shadow = 2, tsrc = 0;
unsigned int dwidth = 0, bank = 0x100;
unsigned char cpuflag = 0;
FILE *fin, *fout;
unsigned long len = openFiles(option(INPUT_FILE), option(OUTPUT_FILE), &fin, &fout);
if (len <= 392) {
if (flagged(VERBOSE) && !flagged(SILENT)) {
printf("File size <= 392 bytes. Activating 'Action Replay Patch Mode'.\n");
}
flag(AR_PATCH_MODE);
if(flagged(AR_AUTO_8BIT)) {
flag(A8BIT);
flag(XY8BIT);
if (flagged(VERBOSE) && !flagged(SILENT)) {
printf("Ensure CPU M and X flags are in 8-bit mode.\n");
}
}
}
else if (len < 0x8000 || (flagged(SKIP_HEADER) && len < 0x8200)) {
if (!flagged(SILENT))
printf("This file looks too small to be a legitimate ROM image.\n");
}
unsigned char *data = allocateMemory(len);
load_data(&fin, len, &data);
if(flagged(A8BIT)) cpuflag |= 0x20;
if(flagged(XY8BIT)) cpuflag |= 0x10;
autoDetectHiLoROM(&data, &hirom);
calculateAddressOptions(&data, &start, &end, &pos, origin, &hirom, &shadow, &bank, len);
dwidth = strtol(option(HEXDUMP_WIDTH), NULL, 10);
disassemble(&fout, &cpuflag, &data, len, start, end, pos, hirom, shadow, dwidth, tsrc);
return 0; //close_files(&fout, &data);
}
void disassemble(FILE **fout, unsigned char *flag, unsigned char **data, unsigned long len, unsigned long start, unsigned long end, unsigned long pos, unsigned char hirom, unsigned char shadow, unsigned int dwidth, unsigned char tsrc) {
unsigned char dmem[4];
unsigned long rpos = start;
char inst[521];
int output_hexdump = (strcmp(option(FORMAT), "hexdump") == 0);
while (rpos < len && rpos <= end) {
// Handle DEADC0DE patch if applicable
if (pos == 0 && !output_hexdump && flagged(AR_PATCH_MODE) && handleDeadCodePatch(fout, data, len, &rpos, &pos)) {
continue; // Skip to next iteration if a patch was handled
}
// Copy the next 4 bytes into the staging area
memcpy(dmem, *data + rpos, 4);
// Disassemble or generate a hexdump
unsigned int offset;
if (output_hexdump) {
offset = hexdump(data, pos, rpos, len, inst, dwidth);
} else {
offset = disasm(dmem, pos, flag, inst, tsrc);
}
// Check for file/block overruns
if ((rpos + offset) > len || (rpos + offset) > (end + 1)) {
fprintf(*fout, "%02lX/%04lX:\t", (pos >> 16) & 0xFF, pos & 0xFFFF);
for (unsigned long i = rpos; i < len && i <= end; i++) {
fprintf(*fout, "%02X", (*data)[i]);
}
fprintf(*fout, "\n");
break;
}
// Check for bank overruns
if (((pos & 0xFFFF) + offset) > 0x10000) {
unsigned int tmp = 0x10000 - (pos & 0xFFFF);
fprintf(*fout, "%02lX/%04lX:\t", (pos >> 16) & 0xFF, pos & 0xFFFF);
for (unsigned int i = 0; i < tmp; i++) {
fprintf(*fout, "%02X", (*data)[rpos + i]);
}
fprintf(*fout, "\n");
// Move to the next bank
if (!hirom) {
pos = (pos & 0xFF0000) + 0x18000;
} else {
pos += tmp;
}
rpos += tmp;
continue;
}
// Print the disassembled instruction or hexdump
fprintf(*fout, "%s\n", inst);
// Move to the next instruction
if (!hirom && ((pos & 0xFFFF) + offset) > 0xFFFF) {
pos = (pos & 0xFF0000) + 0x18000;
} else {
pos += offset;
}
rpos += offset;
}
}