├── GenesisChecksum.java ├── GenesisVectorTable.java └── README.md /GenesisChecksum.java: -------------------------------------------------------------------------------- 1 | //Fix SEGA Genesis ROM Checksum 2 | //@author zznop 3 | //@category Patching 4 | //@keybinding 5 | //@menupath 6 | //@toolbar 7 | 8 | import ghidra.app.script.GhidraScript; 9 | import ghidra.program.model.mem.*; 10 | import ghidra.program.model.address.*; 11 | 12 | public class GenesisChecksum extends GhidraScript { 13 | static final int START_OFFSET = 0x200; 14 | static final int CHECKSUM_OFFSET = 0x18e; 15 | static final int WORD_SIZE = 0x2; 16 | 17 | public void run() throws Exception { 18 | Memory memory = currentProgram.getMemory(); 19 | Address currAddr = currentProgram.getMinAddress().add(START_OFFSET); 20 | Address checksumAddr = currentProgram.getMinAddress().add(CHECKSUM_OFFSET); 21 | long maxSize = currentProgram.getMaxAddress().getOffset() + 1; // EOF 22 | short checksum = 0; 23 | long currIndex = currAddr.getOffset(); 24 | 25 | for (; currIndex <= maxSize-WORD_SIZE; currIndex += WORD_SIZE) { 26 | checksum = (short)((checksum + memory.getShort(currAddr)) & 0x0000ffff); 27 | currAddr = currAddr.add(WORD_SIZE); 28 | } 29 | 30 | memory.setShort(checksumAddr, checksum); 31 | println("ROM checksum calculated (and fixed): 0x" + Integer.toHexString(checksum & 0x0000ffff)); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /GenesisVectorTable.java: -------------------------------------------------------------------------------- 1 | //Given a raw binary SEGA Genesis ROM, construct the vector table and ROM header and kickoff disassembly 2 | //@author zznop 3 | //@category Binary 4 | //@keybinding 5 | //@menupath 6 | //@toolbar 7 | 8 | import ghidra.app.script.GhidraScript; 9 | import ghidra.program.model.util.*; 10 | import ghidra.program.model.reloc.*; 11 | import ghidra.program.model.data.*; 12 | import ghidra.program.model.block.*; 13 | import ghidra.program.model.symbol.*; 14 | import ghidra.program.model.scalar.*; 15 | import ghidra.program.model.mem.*; 16 | import ghidra.program.model.listing.*; 17 | import ghidra.program.model.lang.*; 18 | import ghidra.program.model.pcode.*; 19 | import ghidra.program.model.address.*; 20 | 21 | public class GenesisVectorTable extends GhidraScript { 22 | // Constants 23 | private static final long VECTOR_TABLE_START = 0x4; 24 | private static final long VECTOR_TABLE_END = 0x100; 25 | private static final long DWORD_SIZE = 0x4; 26 | private static final long PTR_PROGRAM_START = 0x4; 27 | private static final long PTR_HBLANK = 0x70; 28 | private static final long PTR_VBLANK = 0x78; 29 | // Address blocks 30 | private static final int CART_ADDRESS_SPACE = 0x00000000; 31 | private static final int SCD_ADDRESS_SPACE = 0x00400000; 32 | private static final int S32X_ADDRESS_SPACE = 0x00800000; 33 | private static final int Z80_ADDRESS_SPACE = 0x00A00000; 34 | private static final int IO_ADDRESS_SPACE = 0x00A10000; 35 | private static final int VDP_ADDRESS_SPACE = 0x00C00000; 36 | private static final int M68K_ADDRESS_SPACE = 0x00FF0000; 37 | // Labels 38 | private static final int REG_HWVERSION = 0x00A10001; 39 | private static final int CTRL_1_DATA = 0x00A10003; 40 | private static final int CTRL_1_CONTROL = 0x00A10009; 41 | private static final int CTRL_2_DATA = 0x00A10005; 42 | private static final int CTRL_2_CONTROL = 0x00A1000B; 43 | private static final int EXT_DATA = 0x00A10007; 44 | private static final int EXT_CONTROL = 0x00A1000D; 45 | private static final int CTRL_1_SERIAL_SEND = 0x00A1000F; 46 | private static final int CTRL_1_SERIAL_RECV = 0x00A10011; 47 | private static final int CTRL_1_SERIAL_CTRL = 0x00A10013; 48 | private static final int CTRL_2_SERIAL_SEND = 0x00A10015; 49 | private static final int CTRL_2_SERIAL_RECV = 0x00A10017; 50 | private static final int CTRL_2_SERIAL_CTRL = 0x00A10019; 51 | private static final int EXT_SERIAL_SEND = 0x00A1001B; 52 | private static final int EXT_SERIAL_RECV = 0x00A1001D; 53 | private static final int EXT_SERIAL_CTRL = 0x00A1001F; 54 | 55 | private static final int Z80_BUS = 0x00A11100; 56 | private static final int Z80_RESET = 0x00A11200; 57 | 58 | private static final int REG_TMS = 0x00A14000; 59 | 60 | private static final int VDP_DATA = 0x00C00000; 61 | private static final int VDP_CONTROL = 0x00C00004; 62 | private static final int VDP_COUNTER = 0x00C00008; 63 | private static final int PSG_INPUT = 0x00C00011; 64 | 65 | // Members 66 | private Address currAddr = null; 67 | 68 | /** 69 | * Creates an ASCII string at the current address, applys a label, and 70 | * increments the cursor past the string 71 | */ 72 | private void createLabeledStringAndIncrement(String label, int length) throws Exception { 73 | createAsciiString(currAddr, length); 74 | createLabel(currAddr, label, true); 75 | currAddr = currAddr.add(length); 76 | } 77 | 78 | /** 79 | * Creates an numerical data field at the current address and increments the 80 | * cursor past the field. 81 | */ 82 | private void createLabeledIntegerAndIncrement(String label, DataType dataType, long length) throws Exception { 83 | createData(currAddr, dataType); 84 | createLabel(currAddr, label, true); 85 | currAddr = currAddr.add(length); 86 | } 87 | 88 | /** 89 | * Applies types and labels fields of the vector table 90 | */ 91 | private void createVectorTable() throws Exception { 92 | createLabeledIntegerAndIncrement("PtrInitialStack", 93 | UnsignedIntegerDataType.dataType, 4); 94 | createLabeledIntegerAndIncrement("PtrProgramStart", 95 | UnsignedIntegerDataType.dataType, 4); 96 | createLabeledIntegerAndIncrement("VectPtrBusError", 97 | UnsignedIntegerDataType.dataType, 4); 98 | createLabeledIntegerAndIncrement("VectPtrAddressError", 99 | UnsignedIntegerDataType.dataType, 4); 100 | createLabeledIntegerAndIncrement("VectPtrIllegalInstruction", 101 | UnsignedIntegerDataType.dataType, 4); 102 | createLabeledIntegerAndIncrement("VectPtrDivisionByZero", 103 | UnsignedIntegerDataType.dataType, 4); 104 | createLabeledIntegerAndIncrement("VectPtrChkException", 105 | UnsignedIntegerDataType.dataType, 4); 106 | createLabeledIntegerAndIncrement("VectPtrTrapVException", 107 | UnsignedIntegerDataType.dataType, 4); 108 | createLabeledIntegerAndIncrement("VectPtrPrivilegeViolation", 109 | UnsignedIntegerDataType.dataType, 4); 110 | createLabeledIntegerAndIncrement("VectPtrTraceException", 111 | UnsignedIntegerDataType.dataType, 4); 112 | createLabeledIntegerAndIncrement("VectPtrLineAEmulator", 113 | UnsignedIntegerDataType.dataType, 4); 114 | createLabeledIntegerAndIncrement("VectPtrLineFEmulator", 115 | UnsignedIntegerDataType.dataType, 4); 116 | createLabeledIntegerAndIncrement("VectUnused00", 117 | UnsignedIntegerDataType.dataType, 4); 118 | createLabeledIntegerAndIncrement("VectUnused01", 119 | UnsignedIntegerDataType.dataType, 4); 120 | createLabeledIntegerAndIncrement("VectUnused02", 121 | UnsignedIntegerDataType.dataType, 4); 122 | createLabeledIntegerAndIncrement("VectUnused03", 123 | UnsignedIntegerDataType.dataType, 4); 124 | createLabeledIntegerAndIncrement("VectUnused04", 125 | UnsignedIntegerDataType.dataType, 4); 126 | createLabeledIntegerAndIncrement("VectUnused05", 127 | UnsignedIntegerDataType.dataType, 4); 128 | createLabeledIntegerAndIncrement("VectUnused06", 129 | UnsignedIntegerDataType.dataType, 4); 130 | createLabeledIntegerAndIncrement("VectUnused07", 131 | UnsignedIntegerDataType.dataType, 4); 132 | createLabeledIntegerAndIncrement("VectUnused08", 133 | UnsignedIntegerDataType.dataType, 4); 134 | createLabeledIntegerAndIncrement("VectUnused09", 135 | UnsignedIntegerDataType.dataType, 4); 136 | createLabeledIntegerAndIncrement("VectUnused10", 137 | UnsignedIntegerDataType.dataType, 4); 138 | createLabeledIntegerAndIncrement("VectUnused11", 139 | UnsignedIntegerDataType.dataType, 4); 140 | createLabeledIntegerAndIncrement("VectPtrSpuriousException", 141 | UnsignedIntegerDataType.dataType, 4); 142 | createLabeledIntegerAndIncrement("VectPtrIrqL1", 143 | UnsignedIntegerDataType.dataType, 4); 144 | createLabeledIntegerAndIncrement("VectPtrIrqL2", 145 | UnsignedIntegerDataType.dataType, 4); 146 | createLabeledIntegerAndIncrement("VectPtrIrqL3", 147 | UnsignedIntegerDataType.dataType, 4); 148 | createLabeledIntegerAndIncrement("VectPtrIrqL4", 149 | UnsignedIntegerDataType.dataType, 4); 150 | createLabeledIntegerAndIncrement("VectPtrIrqL5", 151 | UnsignedIntegerDataType.dataType, 4); 152 | createLabeledIntegerAndIncrement("VectPtrIrqL6", 153 | UnsignedIntegerDataType.dataType, 4); 154 | createLabeledIntegerAndIncrement("VectPtrIrqL7", 155 | UnsignedIntegerDataType.dataType, 4); 156 | createLabeledIntegerAndIncrement("VectPtrTrap00", 157 | UnsignedIntegerDataType.dataType, 4); 158 | createLabeledIntegerAndIncrement("VectPtrTrap01", 159 | UnsignedIntegerDataType.dataType, 4); 160 | createLabeledIntegerAndIncrement("VectPtrTrap02", 161 | UnsignedIntegerDataType.dataType, 4); 162 | createLabeledIntegerAndIncrement("VectPtrTrap03", 163 | UnsignedIntegerDataType.dataType, 4); 164 | createLabeledIntegerAndIncrement("VectPtrTrap04", 165 | UnsignedIntegerDataType.dataType, 4); 166 | createLabeledIntegerAndIncrement("VectPtrTrap05", 167 | UnsignedIntegerDataType.dataType, 4); 168 | createLabeledIntegerAndIncrement("VectPtrTrap06", 169 | UnsignedIntegerDataType.dataType, 4); 170 | createLabeledIntegerAndIncrement("VectPtrTrap07", 171 | UnsignedIntegerDataType.dataType, 4); 172 | createLabeledIntegerAndIncrement("VectPtrTrap08", 173 | UnsignedIntegerDataType.dataType, 4); 174 | createLabeledIntegerAndIncrement("VectPtrTrap09", 175 | UnsignedIntegerDataType.dataType, 4); 176 | createLabeledIntegerAndIncrement("VectPtrTrap10", 177 | UnsignedIntegerDataType.dataType, 4); 178 | createLabeledIntegerAndIncrement("VectPtrTrap11", 179 | UnsignedIntegerDataType.dataType, 4); 180 | createLabeledIntegerAndIncrement("VectPtrTrap12", 181 | UnsignedIntegerDataType.dataType, 4); 182 | createLabeledIntegerAndIncrement("VectPtrTrap13", 183 | UnsignedIntegerDataType.dataType, 4); 184 | createLabeledIntegerAndIncrement("VectPtrTrap14", 185 | UnsignedIntegerDataType.dataType, 4); 186 | createLabeledIntegerAndIncrement("VectPtrTrap15", 187 | UnsignedIntegerDataType.dataType, 4); 188 | createLabeledIntegerAndIncrement("VectUnused12", 189 | UnsignedIntegerDataType.dataType, 4); 190 | createLabeledIntegerAndIncrement("VectUnused13", 191 | UnsignedIntegerDataType.dataType, 4); 192 | createLabeledIntegerAndIncrement("VectUnused14", 193 | UnsignedIntegerDataType.dataType, 4); 194 | createLabeledIntegerAndIncrement("VectUnused15", 195 | UnsignedIntegerDataType.dataType, 4); 196 | createLabeledIntegerAndIncrement("VectUnused16", 197 | UnsignedIntegerDataType.dataType, 4); 198 | createLabeledIntegerAndIncrement("VectUnused17", 199 | UnsignedIntegerDataType.dataType, 4); 200 | createLabeledIntegerAndIncrement("VectUnused18", 201 | UnsignedIntegerDataType.dataType, 4); 202 | createLabeledIntegerAndIncrement("VectUnused19", 203 | UnsignedIntegerDataType.dataType, 4); 204 | createLabeledIntegerAndIncrement("VectUnused20", 205 | UnsignedIntegerDataType.dataType, 4); 206 | createLabeledIntegerAndIncrement("VectUnused21", 207 | UnsignedIntegerDataType.dataType, 4); 208 | createLabeledIntegerAndIncrement("VectUnused22", 209 | UnsignedIntegerDataType.dataType, 4); 210 | createLabeledIntegerAndIncrement("VectUnused23", 211 | UnsignedIntegerDataType.dataType, 4); 212 | createLabeledIntegerAndIncrement("VectUnused24", 213 | UnsignedIntegerDataType.dataType, 4); 214 | createLabeledIntegerAndIncrement("VectUnused25", 215 | UnsignedIntegerDataType.dataType, 4); 216 | createLabeledIntegerAndIncrement("VectUnused26", 217 | UnsignedIntegerDataType.dataType, 4); 218 | createLabeledIntegerAndIncrement("VectUnused27", 219 | UnsignedIntegerDataType.dataType, 4); 220 | } 221 | 222 | /** 223 | * Applies types and labels to the ROM header 224 | */ 225 | private void createRomHeader() throws Exception { 226 | createLabeledStringAndIncrement("ConsoleName", 16); 227 | createLabeledStringAndIncrement("Copyright", 16); 228 | createLabeledStringAndIncrement("DomesticName", 48); 229 | createLabeledStringAndIncrement("InternationalName", 48); 230 | createLabeledStringAndIncrement("SerialRevision", 14); 231 | createLabeledIntegerAndIncrement("Checksum", UnsignedShortDataType.dataType, 2); 232 | createLabeledStringAndIncrement("IoSupport", 16); 233 | createLabeledIntegerAndIncrement("RomStartAddress", UnsignedIntegerDataType.dataType, 4); 234 | createLabeledIntegerAndIncrement("RomEndAddress", UnsignedIntegerDataType.dataType, 4); 235 | createLabeledIntegerAndIncrement("RamStartAddress", UnsignedIntegerDataType.dataType, 4); 236 | createLabeledIntegerAndIncrement("RamEndAddress", UnsignedIntegerDataType.dataType, 4); 237 | createLabeledStringAndIncrement("SramInfo", 12); 238 | createLabeledStringAndIncrement("Notes", 52); 239 | createLabeledStringAndIncrement("Region", 16); 240 | } 241 | 242 | /** 243 | * Iterate the function pointers in the vector table and disassemble 244 | */ 245 | private void disassembleExceptionHandlers() throws Exception { 246 | long handlerPtr = 0; 247 | Memory memory = currentProgram.getMemory(); 248 | currAddr = currentProgram.getMinAddress().add(VECTOR_TABLE_START); 249 | for (long i = currAddr.getOffset(); i <= VECTOR_TABLE_END; i += DWORD_SIZE) { 250 | handlerPtr = memory.getInt(currAddr); 251 | disassemble(toAddr(handlerPtr)); 252 | currAddr = currAddr.add(DWORD_SIZE); 253 | } 254 | } 255 | 256 | /** 257 | * Apply labels to important code and data addresses 258 | */ 259 | private void labelImportantFields() throws Exception { 260 | Memory memory = currentProgram.getMemory(); 261 | int ptr = memory.getInt(toAddr(PTR_PROGRAM_START)); 262 | createLabel(toAddr(ptr), "ProgramStart", true); 263 | ptr = memory.getInt(toAddr(PTR_HBLANK)); 264 | createLabel(toAddr(ptr), "HBlank", true); 265 | ptr = memory.getInt(toAddr(PTR_VBLANK)); 266 | createLabel(toAddr(ptr), "VBlank", true); 267 | createLabel(toAddr(VDP_CONTROL), "VDP_CONTROL", true); 268 | createLabel(toAddr(VDP_COUNTER), "VDP_COUNTER", true); 269 | createLabel(toAddr(VDP_DATA), "VDP_DATA", true); 270 | createLabel(toAddr(IO_ADDRESS_SPACE), "IO_ADDRESS_SPACE", true); 271 | createLabel(toAddr(CTRL_1_CONTROL), "CTRL_1_CONTROL", true); 272 | createLabel(toAddr(CTRL_1_DATA), "CTRL_1_DATA", true); 273 | createLabel(toAddr(CTRL_2_CONTROL), "CTRL_2_CONTROL", true); 274 | createLabel(toAddr(CTRL_2_DATA), "CTRL_2_DATA", true); 275 | createLabel(toAddr(EXT_CONTROL), "EXT_CONTROL", true); 276 | createLabel(toAddr(EXT_DATA), "EXT_DATA", true); 277 | createLabel(toAddr(CTRL_1_SERIAL_SEND), "CTRL_1_SERIAL_SEND", true); 278 | createLabel(toAddr(CTRL_1_SERIAL_RECV), "CTRL_1_SERIAL_RECV", true); 279 | createLabel(toAddr(CTRL_1_SERIAL_CTRL), "CTRL_1_SERIAL_CTRL", true); 280 | createLabel(toAddr(CTRL_2_SERIAL_SEND), "CTRL_2_SERIAL_SEND", true); 281 | createLabel(toAddr(CTRL_2_SERIAL_RECV), "CTRL_2_SERIAL_RECV", true); 282 | createLabel(toAddr(CTRL_2_SERIAL_CTRL), "CTRL_2_SERIAL_CTRL", true); 283 | createLabel(toAddr(EXT_SERIAL_SEND), "EXT_SERIAL_SEND", true); 284 | createLabel(toAddr(EXT_SERIAL_RECV), "EXT_SERIAL_RECV", true); 285 | createLabel(toAddr(EXT_SERIAL_CTRL), "EXT_SERIAL_CTRL", true); 286 | createLabel(toAddr(REG_HWVERSION), "REG_HWVERSION", true); 287 | createLabel(toAddr(REG_TMS), "REG_TMS", true); 288 | createLabel(toAddr(PSG_INPUT), "PSG_INPUT", true); 289 | createLabel(toAddr(Z80_ADDRESS_SPACE), "Z80_ADDRESS_SPACE", true); 290 | createLabel(toAddr(Z80_BUS), "Z80_BUS", true); 291 | createLabel(toAddr(Z80_RESET), "Z80_RESET", true); 292 | createLabel(toAddr(M68K_ADDRESS_SPACE), "M68K_ADDRESS_SPACE", true); 293 | } 294 | 295 | /** 296 | * Main 297 | */ 298 | public void run() throws Exception { 299 | currAddr = currentProgram.getMinAddress(); 300 | createVectorTable(); 301 | createRomHeader(); 302 | disassembleExceptionHandlers(); 303 | labelImportantFields(); 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ghidra_scripts 2 | 3 | ## Description 4 | 5 | My (zznop) open source Ghidra scripts --------------------------------------------------------------------------------