Skip to content

Instantly share code, notes, and snippets.

@Ced2911
Last active November 19, 2021 18:53
Show Gist options
  • Save Ced2911/1bba9b4893ec05268709a4a5b7917cfe to your computer and use it in GitHub Desktop.
Save Ced2911/1bba9b4893ec05268709a4a5b7917cfe to your computer and use it in GitHub Desktop.
SaturnBios.java
//TODO write a description for this script
//@author
//@category _NEW_
//@keybinding
//@menupath
//@toolbar
import ghidra.app.script.GhidraScript;
import ghidra.program.model.util.*;
import ghidra.program.model.reloc.*;
import ghidra.program.model.data.*;
import ghidra.program.model.block.*;
import ghidra.program.model.symbol.*;
import ghidra.program.model.scalar.*;
import ghidra.program.model.mem.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.pcode.*;
import ghidra.program.model.address.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.util.task.TaskMonitor;
import ghidra.feature.fid.hash.FidHashQuad;
import ghidra.feature.fid.service.FidService;
import ghidra.program.model.listing.BookmarkType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.AIFFDataType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class SaturnBios extends GhidraScript {
private MessageLog log;
public void createMemoryRegion(
//
String regionName, long startAddress, long endAddress,
// rwx
boolean read, boolean write, boolean execute, boolean _volatile,
// ...
Program program, TaskMonitor monitor, MessageLog log) {
// Direct
try {
Address addr;
MemoryBlock block;
long length = (endAddress - startAddress) + 1L;
addr = program.getAddressFactory().getDefaultAddressSpace().getAddress(startAddress);
if (program.getMemory().getBlock(addr) != null) {
block = program.getMemory().getBlock(addr);
block.setName(regionName);
} else {
block = program.getMemory().createInitializedBlock(regionName, addr, length, (byte) 0x00, monitor,
false);
}
block.setRead(read);
block.setWrite(write);
block.setExecute(execute);
// block.setVolatile(_volatile);
if ((startAddress & 0x20000000) == 0) {
// Mirror
Address cacheAddr;
cacheAddr = program.getAddressFactory().getDefaultAddressSpace().getAddress(startAddress | 0x20000000);
if (program.getMemory().getBlock(cacheAddr) != null) {
block = program.getMemory().getBlock(cacheAddr);
block.setName(regionName);
} else {
block = program.getMemory().createByteMappedBlock(regionName + "_mirror", cacheAddr, addr, length,
false);
}
block.setRead(read);
block.setWrite(write);
block.setExecute(execute);
// block.setVolatile(_volatile);
}
} catch (Exception e) {
log.appendException(e);
println("Failed to create region: " + regionName + e.getMessage());
}
}
//
// Memory-Mapped Registers
//
// label the SMPC registers
public long labelCDRegisters(Program program, MessageLog log) {
//
// CD registers taken from: https://wiki.yabause.org/index.php5?title=CDBlock
//
final Long CD_BASE = 0x25890000L;
String name = "CD_";
Address addr = program.getAddressFactory().getDefaultAddressSpace().getAddress(CD_BASE);
try {
addRegsU16(CD_BASE + 0x08, name + "HIRQ");
addRegsU16(CD_BASE + 0x0C, name + "HIRQ_MASK");
addRegsU16(CD_BASE + 0x18, name + "CR1");
addRegsU16(CD_BASE + 0x1C, name + "CR2");
addRegsU16(CD_BASE + 0x20, name + "CR3");
addRegsU16(CD_BASE + 0x24, name + "CR4");
addRegsU16(CD_BASE + 0x28, name + "MPEGRGB");
} catch (Exception e) {
log.appendException(e);
}
return 0;
}
//
public long labelArcade(Program program, MessageLog log) {
//
// CD registers taken from: https://wiki.yabause.org/index.php5?title=CDBlock
//
final Long IO_BASE = 0x20400000L;
String name = "ARC_IO_";
Address addr = program.getAddressFactory().getDefaultAddressSpace().getAddress(IO_BASE);
try {
addRegsU8(IO_BASE + 0x01, name + "A_P1");
addRegsU8(IO_BASE + 0x03, name + "B_P2");
addRegsU8(IO_BASE + 0x05, name + "C_SYS");
addRegsU8(IO_BASE + 0x07, name + "D_OUT");
addRegsU8(IO_BASE + 0x09, name + "E_P3");
addRegsU8(IO_BASE + 0x0b, name + "F_P4");
addRegsU8(IO_BASE + 0x0d, name + "G");
addRegsU8(IO_BASE + 0x0f, name + "unused");
addRegsU8(IO_BASE + 0x11, name + "DIR");
addRegsU8(IO_BASE + 0x13, name + "TX1");
addRegsU8(IO_BASE + 0x15, name + "TX2");
addRegsU8(IO_BASE + 0x17, name + "RX1");
addRegsU8(IO_BASE + 0x19, name + "RX2");
addRegsU8(IO_BASE + 0x1b, name + "FLAG");
addRegsU8(IO_BASE + 0x1d, name + "MODE");
addRegsU8(IO_BASE + 0x1f, name + "PORT_AD");
} catch (Exception e) {
log.appendException(e);
}
return 0;
}
// label the onchip registers 0xFFFFFE00 - 0xFFFFFFFF
public long labelOnchipRegisters(Program program, MessageLog log) {
//
// Onchip registers taken from:
// https://github.com/Yabause/yabause/blob/master/yabause/src/sh2core.c
//
String name = "Onchip_";
Address onChipAddr = program.getAddressFactory().getDefaultAddressSpace().getAddress(0xFFFFFE00);
Address addr;
final Long BASE = 0xFFFFFE00L;
try {
addRegsU8(BASE + 0x000, name + "SMR");
addRegsU8(BASE + 0x001, name + "BRR");
addRegsU8(BASE + 0x002, name + "SCR");
addRegsU8(BASE + 0x003, name + "TDR");
addRegsU8(BASE + 0x004, name + "SSR");
addRegsU8(BASE + 0x005, name + "RDR");
addRegsU8(BASE + 0x010, name + "TIER");
addRegsU8(BASE + 0x011, name + "FTCSR");
addRegsU8(BASE + 0x012, name + "FTCSR.part.h");
addRegsU8(BASE + 0x013, name + "FTCSR.part.L");
addRegsU8(BASE + 0x014, name + "OCRA_OCRB_high");
addRegsU8(BASE + 0x016, name + "TCR");
addRegsU8(BASE + 0x017, name + "TOCR");
addRegsU16(BASE + 0x018, name + "FICR");
addRegsU16(BASE + 0x060, name + "IPRB");
addRegsU16(BASE + 0x062, name + "VCRA");
addRegsU16(BASE + 0x064, name + "VCRB");
addRegsU16(BASE + 0x066, name + "VCRC");
addRegsU16(BASE + 0x068, name + "VCRD");
addRegsU8(BASE + 0x080, name + "WTCSR");
addRegsU8(BASE + 0x081, name + "WTCNT");
addRegsU16(BASE + 0x092, name + "CCR");
addRegsU8(BASE + 0x0E0, name + "ICR_high");
addRegsU8(BASE + 0x0E1, name + "ICR");
addRegsU8(BASE + 0x0E2, name + "IPRA_high");
addRegsU8(BASE + 0x0E3, name + "IPRA");
addRegsU8(BASE + 0x0E4, name + "VCRWDT_high");
addRegsU8(BASE + 0x0E5, name + "WCRWDT");
addRegsU16(BASE + 0x100, name + "DVSR");
addRegsU16(BASE + 0x120, name + "DVSR");
addRegsU16(BASE + 0x104, name + "DVDNTL");
addRegsU16(BASE + 0x124, name + "DVDNTL");
addRegsU16(BASE + 0x108, name + "DVCR");
addRegsU16(BASE + 0x128, name + "DVCR");
addRegsU16(BASE + 0x10C, name + "VCRDIV");
addRegsU16(BASE + 0x12C, name + "VCRDIV");
addRegsU16(BASE + 0X110, name + "DVDNTH");
addRegsU16(BASE + 0x130, name + "DVDNTH");
addRegsU16(BASE + 0x114, name + "DVDNTL");
addRegsU16(BASE + 0x134, name + "DVDNTL");
addRegsU16(BASE + 0x118, name + "DVDNTUH");
addRegsU16(BASE + 0x138, name + "DVDNTUH");
addRegsU16(BASE + 0x11C, name + "DVDNTUL");
addRegsU16(BASE + 0x13C, name + "DVDNTUL");
addRegsU16(BASE + 0x180, name + "SAR0");
addRegsU16(BASE + 0x184, name + "DAR0");
addRegsU16(BASE + 0x188, name + "TCR0");
addRegsU16(BASE + 0x18C, name + "CHCR0");
addRegsU16(BASE + 0x190, name + "SAR1");
addRegsU16(BASE + 0x194, name + "DAR1");
addRegsU16(BASE + 0x198, name + "TCR1");
addRegsU16(BASE + 0x19C, name + "CHCR1");
addRegsU16(BASE + 0x1A0, name + "VCRDMA0");
addRegsU16(BASE + 0x1A8, name + "VCRDMA1");
addRegsU16(BASE + 0x1B0, name + "DMA0R");
addRegsU16(BASE + 0x1E0, name + "BCR1");
addRegsU16(BASE + 0x1E4, name + "BCR2");
addRegsU16(BASE + 0x1E8, name + "WCR");
addRegsU16(BASE + 0x1EC, name + "MCR");
addRegsU16(BASE + 0x1F0, name + "RTCSR");
addRegsU16(BASE + 0x1F4, name + "RTCNT");
addRegsU16(BASE + 0x1F8, name + "RTCOR");
} catch (Exception e) {
log.appendException(e);
}
return 0;
}
// label the SCU registers
public long labelSCURegisters(Program program, MessageLog log) {
//
// SCU registers taken from:
// https://github.com/ijacquez/libyaul/blob/develop/libyaul/scu/scu/map.h
//
final Long SCU_BASE = 0x25FE0000L;
String name = "SCU_";
try {
addRegsU32(SCU_BASE + 0x0000, name + "D0R");
addRegsU32(SCU_BASE + 0x0004, name + "D0W");
addRegsU32(SCU_BASE + 0x0008, name + "D0C");
addRegsU32(SCU_BASE + 0x000C, name + "D0AD");
addRegsU32(SCU_BASE + 0x0010, name + "D0EN");
addRegsU32(SCU_BASE + 0x0014, name + "D0MD");
addRegsU32(SCU_BASE + 0x0020, name + "D1R");
addRegsU32(SCU_BASE + 0x0024, name + "D1W");
addRegsU32(SCU_BASE + 0x0028, name + "D1C");
addRegsU32(SCU_BASE + 0x002C, name + "D1AD");
addRegsU32(SCU_BASE + 0x0030, name + "D1EN");
addRegsU32(SCU_BASE + 0x0034, name + "D1MD");
addRegsU32(SCU_BASE + 0x0040, name + "D2R");
addRegsU32(SCU_BASE + 0x0044, name + "D2W");
addRegsU32(SCU_BASE + 0x0048, name + "D2C");
addRegsU32(SCU_BASE + 0x004C, name + "D2AD");
addRegsU32(SCU_BASE + 0x0050, name + "D2EN");
addRegsU32(SCU_BASE + 0x0054, name + "D2MD");
addRegsU32(SCU_BASE + 0x0060, name + "DSTP");
addRegsU32(SCU_BASE + 0x007C, name + "DSTA");
addRegsU32(SCU_BASE + 0x0080, name + "PPAF");
addRegsU32(SCU_BASE + 0x0084, name + "PPD");
addRegsU32(SCU_BASE + 0x0088, name + "PDA");
addRegsU32(SCU_BASE + 0x008C, name + "PDD");
addRegsU32(SCU_BASE + 0x0090, name + "T0C");
addRegsU32(SCU_BASE + 0x0094, name + "T1S");
addRegsU32(SCU_BASE + 0x0098, name + "T1MD");
addRegsU32(SCU_BASE + 0x00A0, name + "IMS");
addRegsU32(SCU_BASE + 0x00A4, name + "IST");
addRegsU32(SCU_BASE + 0x00A8, name + "AIACK");
addRegsU32(SCU_BASE + 0x00B0, name + "ASR0");
addRegsU32(SCU_BASE + 0x00B4, name + "ASR1");
addRegsU32(SCU_BASE + 0x00B8, name + "AREF");
addRegsU32(SCU_BASE + 0x00C4, name + "RSEL");
addRegsU32(SCU_BASE + 0x00C8, name + "VER");
} catch (Exception e) {
log.appendException(e);
}
return 0;
}
// label the SMPC registers
public long labelSMPCRegisters(Program program, MessageLog log) {
//
// SMPC registers taken from:
// https://github.com/ijacquez/libyaul/scu/bus/cpu/smpc/smpc/map.h
//
final Long SMPC_BASE = 0x20100000L;
String name = "SMPC_";
try {
addRegsU8(SMPC_BASE + 0x01F, name + "COMREG");
addRegsU8(SMPC_BASE + 0x061, name + "SR");
addRegsU8(SMPC_BASE + 0x063, name + "SF");
addRegsU8(SMPC_BASE + 0x075, name + "PDR1");
addRegsU8(SMPC_BASE + 0x077, name + "PDR2");
addRegsU8(SMPC_BASE + 0x079, name + "DDR1");
addRegsU8(SMPC_BASE + 0x07B, name + "DDR2");
addRegsU8(SMPC_BASE + 0x07D, name + "IOSEL1");
addRegsU8(SMPC_BASE + 0x07D, name + "IOSEL2");
addRegsU8(SMPC_BASE + 0x07F, name + "EXLE1");
addRegsU8(SMPC_BASE + 0x07F, name + "EXLE2");
} catch (Exception e) {
log.appendException(e);
}
return 0;
}
// label the VDP1 registers
public long labelVDP1Registers(Program program, MessageLog log) {
//
// VDP1 registers taken from:
// https://github.com/ijacquez/libyaulscu/bus/b/vdp/vdp1/map.h
//
final Long VDP1_BASE = 0x25D00000L;
String name = "VDP1_";
try {
addRegsU16(VDP1_BASE + 0x0000, name + "TVMR");
addRegsU16(VDP1_BASE + 0x0002, name + "FBCR");
addRegsU16(VDP1_BASE + 0x0004, name + "PTMR");
addRegsU16(VDP1_BASE + 0x0006, name + "EWDR");
addRegsU16(VDP1_BASE + 0x0008, name + "EWLR");
addRegsU16(VDP1_BASE + 0x000A, name + "EWRR");
addRegsU16(VDP1_BASE + 0x000C, name + "ENDR");
addRegsU16(VDP1_BASE + 0x0010, name + "EDSR");
addRegsU16(VDP1_BASE + 0x0012, name + "LOPR");
addRegsU16(VDP1_BASE + 0x0014, name + "COPR");
addRegsU16(VDP1_BASE + 0x0016, name + "MODR");
} catch (Exception e) {
log.appendException(e);
}
return 0;
}
// label the VDP2 registers
public long labelVDP2Registers(Program program, MessageLog log) {
//
// VDP2 registers taken from:
// https://github.com/ijacquez/libyaul/scu/bus/b/vdp/vdp2/map.h
//
final Long VDP_BASE = 0x25F80000L;
String name = "VDP2_";
try {
addRegsU16(VDP_BASE + 0x0000, name + "TVMD");
addRegsU16(VDP_BASE + 0x0002, name + "EXTEN");
addRegsU16(VDP_BASE + 0x0004, name + "TVSTAT");
addRegsU16(VDP_BASE + 0x0006, name + "VRSIZE");
addRegsU16(VDP_BASE + 0x0008, name + "HCNT");
addRegsU16(VDP_BASE + 0x000A, name + "VCNT");
addRegsU16(VDP_BASE + 0x000E, name + "RAMCTL");
addRegsU16(VDP_BASE + 0x0010, name + "CYCA0L");
addRegsU16(VDP_BASE + 0x0012, name + "CYCA0U");
addRegsU16(VDP_BASE + 0x0014, name + "CYCA1L");
addRegsU16(VDP_BASE + 0x0016, name + "CYCA1U");
addRegsU16(VDP_BASE + 0x0018, name + "CYCB0L");
addRegsU16(VDP_BASE + 0x001A, name + "CYCB0U");
addRegsU16(VDP_BASE + 0x001C, name + "CYCB1L");
addRegsU16(VDP_BASE + 0x001E, name + "CYCB1U");
addRegsU16(VDP_BASE + 0x0020, name + "BGON");
addRegsU16(VDP_BASE + 0x0022, name + "MZCTL");
addRegsU16(VDP_BASE + 0x0024, name + "SFSEL");
addRegsU16(VDP_BASE + 0x0026, name + "SFCODE");
addRegsU16(VDP_BASE + 0x0028, name + "CHCTLA");
addRegsU16(VDP_BASE + 0x002A, name + "CHCTLB");
addRegsU16(VDP_BASE + 0x002C, name + "BMPNA");
addRegsU16(VDP_BASE + 0x002E, name + "BMPNB");
addRegsU16(VDP_BASE + 0x0030, name + "PNCN0");
addRegsU16(VDP_BASE + 0x0032, name + "PNCN1");
addRegsU16(VDP_BASE + 0x0034, name + "PNCN2");
addRegsU16(VDP_BASE + 0x0036, name + "PNCN3");
addRegsU16(VDP_BASE + 0x0038, name + "PNCR");
addRegsU16(VDP_BASE + 0x003A, name + "PLSZ");
addRegsU16(VDP_BASE + 0x003C, name + "MPOFN");
addRegsU16(VDP_BASE + 0x003E, name + "MPOFR");
addRegsU16(VDP_BASE + 0x0040, name + "MPABN0");
addRegsU16(VDP_BASE + 0x0042, name + "MPCDN0");
addRegsU16(VDP_BASE + 0x0044, name + "MPABN1");
addRegsU16(VDP_BASE + 0x0046, name + "MPCDN1");
addRegsU16(VDP_BASE + 0x0048, name + "MPABN2");
addRegsU16(VDP_BASE + 0x004A, name + "MPCDN2");
addRegsU16(VDP_BASE + 0x004C, name + "MPABN3");
addRegsU16(VDP_BASE + 0x004E, name + "MPCDN3");
addRegsU16(VDP_BASE + 0x0050, name + "MPABRA");
addRegsU16(VDP_BASE + 0x0052, name + "MPCDRA");
addRegsU16(VDP_BASE + 0x0054, name + "MPEFRA");
addRegsU16(VDP_BASE + 0x0056, name + "MPGHRA");
addRegsU16(VDP_BASE + 0x0058, name + "MPIJRA");
addRegsU16(VDP_BASE + 0x005A, name + "MPKLRA");
addRegsU16(VDP_BASE + 0x005C, name + "MPMNRA");
addRegsU16(VDP_BASE + 0x005E, name + "MPOPRA");
addRegsU16(VDP_BASE + 0x0060, name + "MPABRB");
addRegsU16(VDP_BASE + 0x0062, name + "MPCDRB");
addRegsU16(VDP_BASE + 0x0064, name + "MPEFRB");
addRegsU16(VDP_BASE + 0x0066, name + "MPGHRB");
addRegsU16(VDP_BASE + 0x0068, name + "MPIJRB");
addRegsU16(VDP_BASE + 0x006A, name + "MPKLRB");
addRegsU16(VDP_BASE + 0x006C, name + "MPMNRB");
addRegsU16(VDP_BASE + 0x006E, name + "MPOPRB");
addRegsU16(VDP_BASE + 0x0070, name + "SCXIN0");
addRegsU16(VDP_BASE + 0x0072, name + "SCXDN0");
addRegsU16(VDP_BASE + 0x0074, name + "SCYIN0");
addRegsU16(VDP_BASE + 0x0076, name + "SCYDN0");
addRegsU16(VDP_BASE + 0x0078, name + "ZMXIN0");
addRegsU16(VDP_BASE + 0x007A, name + "ZMXDN0");
addRegsU16(VDP_BASE + 0x007C, name + "ZMYIN0");
addRegsU16(VDP_BASE + 0x007E, name + "ZMYDN0");
addRegsU16(VDP_BASE + 0x0080, name + "SCXIN1");
addRegsU16(VDP_BASE + 0x0082, name + "SCXDN1");
addRegsU16(VDP_BASE + 0x0084, name + "SCYIN1");
addRegsU16(VDP_BASE + 0x0086, name + "SCYDN1");
addRegsU16(VDP_BASE + 0x0088, name + "ZMXIN1");
addRegsU16(VDP_BASE + 0x008A, name + "ZMXDN1");
addRegsU16(VDP_BASE + 0x008C, name + "ZMYIN1");
addRegsU16(VDP_BASE + 0x008E, name + "ZMYDN1");
addRegsU16(VDP_BASE + 0x0090, name + "SCXN2");
addRegsU16(VDP_BASE + 0x0092, name + "SCYN2");
addRegsU16(VDP_BASE + 0x0094, name + "SCXN3");
addRegsU16(VDP_BASE + 0x0096, name + "SCYN3");
addRegsU16(VDP_BASE + 0x0098, name + "ZMCTL");
addRegsU16(VDP_BASE + 0x009A, name + "SCRCTL");
addRegsU16(VDP_BASE + 0x009C, name + "VCSTAU");
addRegsU16(VDP_BASE + 0x009E, name + "VCSTAL");
addRegsU16(VDP_BASE + 0x00A0, name + "LSTA0U");
addRegsU16(VDP_BASE + 0x00A2, name + "LSTA0L");
addRegsU16(VDP_BASE + 0x00A4, name + "LSTA1U");
addRegsU16(VDP_BASE + 0x00A6, name + "LSTA1L");
addRegsU16(VDP_BASE + 0x00A8, name + "LCTAU");
addRegsU16(VDP_BASE + 0x00AA, name + "LCTAL");
addRegsU16(VDP_BASE + 0x00AC, name + "BKTAU");
addRegsU16(VDP_BASE + 0x00AE, name + "BKTAL");
addRegsU16(VDP_BASE + 0x00B0, name + "RPMD");
addRegsU16(VDP_BASE + 0x00B2, name + "RPRCTL");
addRegsU16(VDP_BASE + 0x00B4, name + "KTCTL");
addRegsU16(VDP_BASE + 0x00B6, name + "KTAOF");
addRegsU16(VDP_BASE + 0x00B8, name + "OVPNRA");
addRegsU16(VDP_BASE + 0x00BA, name + "OVPNRB");
addRegsU16(VDP_BASE + 0x00BC, name + "RPTAU");
addRegsU16(VDP_BASE + 0x00BE, name + "RPTAL");
addRegsU16(VDP_BASE + 0x00C0, name + "WPSX0");
addRegsU16(VDP_BASE + 0x00C2, name + "WPSY0");
addRegsU16(VDP_BASE + 0x00C4, name + "WPEX0");
addRegsU16(VDP_BASE + 0x00C6, name + "WPEY0");
addRegsU16(VDP_BASE + 0x00C8, name + "WPSX1");
addRegsU16(VDP_BASE + 0x00CA, name + "WPSY1");
addRegsU16(VDP_BASE + 0x00CC, name + "WPEX1");
addRegsU16(VDP_BASE + 0x00CE, name + "WPEY1");
addRegsU16(VDP_BASE + 0x00D0, name + "WCTLA");
addRegsU16(VDP_BASE + 0x00D2, name + "WCTLB");
addRegsU16(VDP_BASE + 0x00D4, name + "WCTLC");
addRegsU16(VDP_BASE + 0x00D6, name + "WCTLD");
addRegsU16(VDP_BASE + 0x00D8, name + "LWTA0U");
addRegsU16(VDP_BASE + 0x00DA, name + "LWTA0L");
addRegsU16(VDP_BASE + 0x00DC, name + "LWTA1U");
addRegsU16(VDP_BASE + 0x00DE, name + "LWTA1L");
addRegsU16(VDP_BASE + 0x00E0, name + "SPCTL");
addRegsU16(VDP_BASE + 0x00E2, name + "SDCTL");
addRegsU16(VDP_BASE + 0x00E4, name + "CRAOFA");
addRegsU16(VDP_BASE + 0x00E6, name + "CRAOFB");
addRegsU16(VDP_BASE + 0x00E8, name + "LNCLEN");
addRegsU16(VDP_BASE + 0x00EA, name + "SFPRMD");
addRegsU16(VDP_BASE + 0x00EC, name + "CCCTL");
addRegsU16(VDP_BASE + 0x00EE, name + "SFCCMD");
addRegsU16(VDP_BASE + 0x00F0, name + "PRISA");
addRegsU16(VDP_BASE + 0x00F2, name + "PRISB");
addRegsU16(VDP_BASE + 0x00F4, name + "PRISC");
addRegsU16(VDP_BASE + 0x00F6, name + "PRISD");
addRegsU16(VDP_BASE + 0x00F8, name + "PRINA");
addRegsU16(VDP_BASE + 0x00FA, name + "PRINB");
addRegsU16(VDP_BASE + 0x00FC, name + "PRIR");
addRegsU16(VDP_BASE + 0x0100, name + "CCRSA");
addRegsU16(VDP_BASE + 0x0102, name + "CCRSB");
addRegsU16(VDP_BASE + 0x0104, name + "CCRSC");
addRegsU16(VDP_BASE + 0x0106, name + "CCRSD");
addRegsU16(VDP_BASE + 0x0108, name + "CCRNA");
addRegsU16(VDP_BASE + 0x010A, name + "CCRNB");
addRegsU16(VDP_BASE + 0x010C, name + "CCRR");
addRegsU16(VDP_BASE + 0x010E, name + "CCRLB");
addRegsU16(VDP_BASE + 0x0110, name + "CLOFEN");
addRegsU16(VDP_BASE + 0x0112, name + "CLOFSL");
addRegsU16(VDP_BASE + 0x0114, name + "COAR");
addRegsU16(VDP_BASE + 0x0116, name + "COAG");
addRegsU16(VDP_BASE + 0x0118, name + "COAB");
addRegsU16(VDP_BASE + 0x011A, name + "COBR");
addRegsU16(VDP_BASE + 0x011C, name + "COBG");
addRegsU16(VDP_BASE + 0x011E, name + "COBB");
} catch (Exception e) {
log.appendException(e);
}
return 0;
}
private void findBootSound() {
AIFFDataType aiffdt = new AIFFDataType();
Memory memory = currentProgram.getMemory();
MemoryBlock[] blocks = memory.getBlocks();
ArrayList<Address> foundAdresses = new ArrayList<Address>();
for (int i = 0; i < blocks.length; i++) {
if (blocks[i].isInitialized()) {
Address start = blocks[i].getStart();
Address found = null;
while (true) {
found = memory.findBytes(start, blocks[i].getEnd(), AIFFDataType.MAGIC, AIFFDataType.MAGIC_MASK,
true, monitor);
if (found != null) {
foundAdresses.add(found);
start = found.add(1);
} else
break;
}
}
}
for (int i = 0; i < foundAdresses.size(); i++) {
try {
Data data = getDataAt(foundAdresses.get(i));
if (data == null) {
Data newData = createData(foundAdresses.get(i), aiffdt);
currentProgram.getBookmarkManager().setBookmark(foundAdresses.get(i), BookmarkType.ANALYSIS,
"Embedded Media", "BootSound");
}
} catch (Exception e) {
println("Invalid at " + foundAdresses.get(i).toString());
}
}
}
private void addRegsU8(Long address, String name) {
try {
createByte(toAddr(address));
createLabel(toAddr(address), name, true);
} catch (Exception e) {
println("Invalid reg at " + name.toString());
}
}
private void addRegsU16(Long address, String name) {
try {
createWord(toAddr(address));
createLabel(toAddr(address), name, true);
} catch (Exception e) {
println("Invalid reg at " + name.toString() + e.getMessage());
}
}
private void addRegsU32(Long address, String name) {
try {
createDWord(toAddr(address));
createLabel(toAddr(address), name, true);
} catch (Exception e) {
println("Invalid reg at " + name.toString());
}
}
// TODO: split this into separate script file so raw binaries can use this same
// code
// TODO: add missing memory sections
public void createSegaSaturnMemoryMap(Program program, TaskMonitor monitor, MessageLog log) {
try {
// 0x00000000 - 0x000FFFFF: Boot ROM
createMemoryRegion("BootROM", 0x00000000, 0x000FFFFF, true, false, true, false, program, monitor, log);
// 0x00100000 0x0017FFFF SMPC Registers
createMemoryRegion("SMPCRegisters", 0x00100000, 0x0017FFFF, true, true, false, true, program, monitor, log);
// 0x00180000 0x001FFFFF Backup RAM
createMemoryRegion("BackRam", 0x00180000, 0x001FFFFF, true, true, false, false, program, monitor, log);
// 0x00200000 - 0x002FFFFF: Work RAM Low
createMemoryRegion("LRam", 0x00200000, 0x002FFFFF + 1, true, true, true, false, program, monitor, log);
// 0x00300000 0x003FFFFF Random Data On Every Read (mostly $00)
createMemoryRegion("Random", 0x00300000, 0x003FFFFF, true, true, false, false, program, monitor, log);
// 0x00400000 0x007FFFFF Always Returns $0000
createMemoryRegion("$0000", 0x00400000, 0x007FFFFF, true, true, false, false, program, monitor, log);
// 0x00800000 0x00FFFFFF Always Returns $00000001000200030004000500060007
createMemoryRegion("$1234567", 0x00800000, 0x00FFFFFF, true, true, false, false, program, monitor, log);
// 0x01000000 0x01FFFFFF Always Returns $FFFF.
createMemoryRegion("$FFFF", 0x01000000, 0x01FFFFFF, true, true, true, false, program, monitor, log);
// 0x02000000 0x03FFFFFF A-Bus CS0
createMemoryRegion("CS0", 0x02000000, 0x03FFFFFF, true, true, true, false, program, monitor, log);
// 0x04000000 0x04FFFFFF A-Bus CS1
createMemoryRegion("CS1", 0x04000000, 0x04FFFFFF, true, true, true, false, program, monitor, log);
// 0x05000000 0x057FFFFF A-Bus Dummy
createMemoryRegion("CS1Dummy", 0x05000000, 0x057FFFFF, true, true, true, false, program, monitor, log);
// 0x05800000 0x058FFFFF A-Bus CS2
createMemoryRegion("CS2", 0x05800000, 0x058FFFFF, true, true, true, false, program, monitor, log);
// 0x05900000 0x059FFFFF Lockup When Read
createMemoryRegion("LockupWhenRead", 0x05900000, 0x059FFFFF, true, true, false, false, program, monitor,
log);
// 0x05A00000 0x05AFFFFF 68000 Work RAM
createMemoryRegion("68000Ram", 0x05A00000, 0x05AFFFFF, true, true, false, false, program, monitor, log);
// 0x05B00000 0x05BFFFFF SCSP Registers
createMemoryRegion("SCSPRegisters", 0x05B00000, 0x05BFFFFF, true, true, false, true, program, monitor, log);
// 0x05C00000 0x05C7FFFF VDP1 VRAM
createMemoryRegion("VDP1Vram", 0x05C00000, 0x05C7FFFF, true, true, false, false, program, monitor, log);
// 0x05C80000 0x05CFFFFF VDP1 Framebuffer
createMemoryRegion("VDP1Framebuffer", 0x05C80000, 0x05CFFFFF, true, true, false, false, program, monitor,
log);
// 0x05D00000 0x05D7FFFF VDP1 Registers
createMemoryRegion("VDP1Registers", 0x05D00000, 0x05D7FFFF, true, true, false, true, program, monitor, log);
// 0x05D80000 0x05DFFFFF Lockup When Read2
createMemoryRegion("LockupR2", 0x05D80000, 0x05DFFFFF, true, true, false, false, program, monitor, log);
// 0x05E00000 0x05EFFFFF VDP2 VRAM
createMemoryRegion("VDP2Vram", 0x05E00000, 0x05EFFFFF, true, true, false, false, program, monitor, log);
// 0x05F00000 0x05F7FFFF VDP2 CRAM
createMemoryRegion("VDP2Cram", 0x05F00000, 0x05F7FFFF, true, true, false, false, program, monitor, log);
// 0x05F80000 0x05FBFFFF VDP2 Registers
createMemoryRegion("VDP2Registers", 0x05F80000, 0x05FBFFFF, true, true, false, true, program, monitor, log);
// 0x05FC0000 0x05FDFFFF Always Returns $000E0000
createMemoryRegion("AlwaysReturns$E0000", 0x05FC0000, 0x05FDFFFF, true, true, false, false, program,
monitor, log);
// 0x05FE0000 0x05FEFFFF SCU Registers
createMemoryRegion("SCURegisters", 0x05FE0000, 0x05FEFFFF, true, true, false, true, program, monitor, log);
// 0x05FF0000 0x05FFFFFF Unknown Registers
createMemoryRegion("UnknownRegisters", 0x05FF0000, 0x05FFFFFF, true, true, false, true, program, monitor,
log);
// 0x06000000 - 0x07FFFFFF: Work RAM High
createMemoryRegion("HRam", 0x06000000, 0x07FFFFFF, true, true, true, false, program, monitor, log);
// sh2regs
createMemoryRegion("SHRegs", 0xFFFFFE00, 0xFFFFFFFF, true, true, true, true, program, monitor, log);
labelCDRegisters(program, log);
labelOnchipRegisters(program, log);
labelSCURegisters(program, log);
labelSMPCRegisters(program, log);
labelVDP1Registers(program, log);
labelVDP2Registers(program, log);
labelArcade(program, log);
} catch (Exception e) {
log.appendException(e);
}
}
public void addBiosFunc(int addr, String name) {
try {
int ptrJump = getInt(toAddr(addr));
Data ptrData = createDWord(toAddr(addr));
createLabel(toAddr(addr), String.format("jmp_%s", name), true);
createMemoryReference(ptrData, toAddr(ptrJump), ghidra.program.model.symbol.RefType.DATA);
disassemble(toAddr(ptrJump));
createLabel(toAddr(ptrJump), String.format("call_%s", name), true);
createFunction(toAddr(ptrJump), String.format("%s", name));
} catch (Exception e) {
log.appendException(e);
}
}
private void setInt(int addr, int v) throws Exception {
setInt(toAddr(addr), v);
}
private void memcpy(int destAddr, int startAddr, int len) throws Exception {
for (int i = 0; i < len; i++) {
try {
int dw = getInt(toAddr(startAddr + i));
setInt(destAddr + i, dw);
} catch (Exception e) {
log.appendException(e);
}
}
}
private void memoryMap() throws Exception {
createSegaSaturnMemoryMap(currentProgram, monitor, log);
// Copy
// memcpy(0x06000150, 0x750, 0x344);
// Copy ...
// memcpy(0x6001100, 0x0001100, 0x80000 - 0x1100);
// Bios version
clearListing(toAddr(0x0800));
clearListing(toAddr(0x06000200));
createAsciiString​(toAddr(0x0800));
try {
createAsciiString​(toAddr(0x06000200));
} catch (Exception e) {
log.appendException(e);
}
}
private void diss() throws Exception {
/*
* // Init bios.. setInt(0x06000210, 0x00000210); setInt(0x0600026C,
* 0x0000026C); setInt(0x06000274, 0x00000274); setInt(0x06000280, 0x00000280);
* setInt(0x0600029C, 0x0000029C); setInt(0x060002DC, 0x000002DC);
* setInt(0x06000300, 0x00000300); setInt(0x06000304, 0x00000304);
* setInt(0x06000310, 0x00000310); setInt(0x06000314, 0x00000314);
* setInt(0x06000320, 0x00000320); setInt(0x06000324, 0x00000000);
* setInt(0x06000330, 0x00000330); setInt(0x06000334, 0x00000334);
* setInt(0x06000340, 0x00000340); setInt(0x06000344, 0x00000344);
* setInt(0x06000348, 0xFFFFFFFF); setInt(0x06000354, 0x00000000);
* setInt(0x06000358, 0x00000358);
*/
// 0x00000226
// createDWord(toAddr(0x00000226));
// createLabel(toAddr(0x00000226), "ReturnFromException", true);
// Interrupt handler
for (Integer i = 0x400; i < 0x480; i += 4) {
Data ptrData = createDWord(toAddr(0x06000000 + i));
createLabel(toAddr(0x06000000 + i), String.format("BiosHandleScuInterrupt_%d", i), true);
}
// Some tables ?...
// createDwords(toAddr(0x2d4), (0x380 - 0x2d4) / 4);
// entry point ?
int entryPoint = getInt(toAddr(0x0000000)) & 0x1FFFFFFF;
Data entryPointData = createDWord(toAddr(0x0000000));
createDWord(toAddr(0x0000000));
createLabel(toAddr(entryPoint), "_ENTRY_POINT", true);
createFunction(toAddr(entryPoint), "_start");
createMemoryReference(entryPointData, toAddr(entryPoint), ghidra.program.model.symbol.RefType.DATA);
// GBR
for (Integer i = 0; i < 0x200; i += 4) {
int ptrJump = getInt(toAddr(0x0000000 + i)) & 0x1FFFFFFF;
Data ptrData = createDWord(toAddr(0x00000000 + i));
createMemoryReference(ptrData, toAddr(ptrJump), ghidra.program.model.symbol.RefType.DATA);
disassemble(toAddr(ptrJump));
}
for (Integer i = 0; i < 0x200; i += 4) {
Data ptrData = createDWord(toAddr(0x06000000 + i));
createLabel(toAddr(0x06000000 + i), String.format("itr_%d", i), true);
}
try {
int returnFromExceptionAddr = getInt(toAddr(0x0000020));
createDWord(toAddr(returnFromExceptionAddr));
createLabel(toAddr(returnFromExceptionAddr), "ReturnFromException", true);
} catch (Exception e) {
log.appendException(e);
}
try {
int stackPointerAddr = getInt(toAddr(0x04));
createDWord(toAddr(stackPointerAddr));
createLabel(toAddr(stackPointerAddr), "ResetStackPointer", true);
} catch (Exception e) {
log.appendException(e);
}
try {
int illegalInstAddr = getInt(toAddr(0x10));
createDWord(toAddr(illegalInstAddr));
createLabel(toAddr(illegalInstAddr), "IllegalInstrInterupt", true);
} catch (Exception e) {
log.appendException(e);
}
try {
int nmiAddr = getInt(toAddr(0x2C));
createDWord(toAddr(nmiAddr));
createLabel(toAddr(nmiAddr), "NMI", true);
} catch (Exception e) {
log.appendException(e);
}
createFunction(toAddr(0x50ea), "decompress_logo_font");
createLabel(toAddr(0x25a00000), "SOUND_RAM", true);
createLabel(toAddr(0x24FFFFFF), "Cart_id", true);
// Bios call...
addBiosFunc(0x06000210, "BiosPowerOnMemoryClear");
addBiosFunc(0x06000268, "BiosLoadSomething_at_06004000");
addBiosFunc(0x0600026C, "BiosExecuteCDPlayer");
addBiosFunc(0x06000270, "bios_check_cd_auth");
addBiosFunc(0x06000274, "BiosCheckMPEGCard");
addBiosFunc(0x06000280, "BiosChangeScuInterruptPriority");
addBiosFunc(0x06000288, "bios_loadcd_boot");
addBiosFunc(0x0600028C, "bios_loadcd_parse_validate_ip"); // BiosCDINIT2
addBiosFunc(0x06000298, "bios_loadcd_xxx");
addBiosFunc(0x060002A0, "scu_reset");
addBiosFunc(0x060002C4, "bios_HRAM_entrypoint");
addBiosFunc(0x060002CC, "bios_loadcd_read");
addBiosFunc(0x060002DC, "bios_play_disc");
addBiosFunc(0x060002DC, "BiosCDINIT1");
addBiosFunc(0x06000300, "BiosSetScuInterrupt");
addBiosFunc(0x06000304, "BiosGetScuInterrupt");
addBiosFunc(0x06000310, "BiosSetSh2Interrupt");
addBiosFunc(0x06000314, "BiosGetSh2Interrupt");
addBiosFunc(0x06000320, "BiosChangeSystemClock");
addBiosFunc(0x06000328, "BiosChangeSystemClock2");
addBiosFunc(0x06000330, "BiosGetSemaphore");
addBiosFunc(0x06000334, "BiosClearSemaphore");
addBiosFunc(0x06000340, "BiosSetScuInterruptMask");
addBiosFunc(0x06000344, "BiosChangeScuInterruptMask");
addBiosFunc(0x06000334, "BiosMemSet");
addBiosFunc(0x06000338, "BiosMemCpy");
addRegsU32(0x06000248L, "region_flag");
addBiosFunc(0x060002C8, "bios_1a3C");
// bup...
addBiosFunc(0x06000358, "bios_bup_init");
Data pubVectAddr = createDWord(toAddr(0x6000354));
createLabel(toAddr(0x6000354), String.format("bios_bup_vect_addr"), true);
// only works with correct memory setup
if (false) {
int pubVectInt = getInt(toAddr(0x6000354));
addBiosFunc(pubVectInt + 4, "bios_bup_sel_part");
addBiosFunc(pubVectInt + 8, "bios_bup_format");
addBiosFunc(pubVectInt + 12, "bios_bup_stat");
addBiosFunc(pubVectInt + 16, "bios_bup_write");
addBiosFunc(pubVectInt + 20, "bios_bup_read");
addBiosFunc(pubVectInt + 24, "bios_bup_delete");
addBiosFunc(pubVectInt + 28, "bios_bup_dir");
addBiosFunc(pubVectInt + 32, "bios_bup_verify");
addBiosFunc(pubVectInt + 36, "bios_bup_get_date");
addBiosFunc(pubVectInt + 40, "bios_bup_set_date");
addBiosFunc(pubVectInt + 86, "bios_unknown_func");
}
}
private void copy2bl() throws Exception {
// bios copy somestuff to main ram
memcpy(0x6020000, 0x40000, 0x400);
memcpy(0x6001100, 0x01100, 0x800);
}
public void run() throws Exception {
log = new MessageLog();
memoryMap();
copy2bl();
diss();
// Ressources
findBootSound();
Map<Long, String> fid_hash = new HashMap<Long, String>() {
{
// known hash - from Sega Saturn BIOS v1.00 (1994)(Sega)(JP)(M6)
// decompression
put(-4957357294425986193L, "compr_memset");
put(8267093030358976781L, "compr_memcpy");
put(8170632217599045526L, "uncompress_fmt1");
put(7002974656940721789L, "uncompress_fmt2");
put(-880055033493905191L, "uncompress");
// common
put(-3215063894234191610L, "memset_000002ac");
put(-1917158710479188708L, "memcpy_000002bc");
// cd rom
put(-3960013885942437404L, "cd_write_command");
put(440706581677110490L, "cd_read_return_status");
put(1753148846564467649L, "cd_is_data_ready");
put(9038101781666711820L, "cd_get_then_delete_sector_data");
put(-2951319010860686687L, "cd_abort_file");
put(252523138794864959L, "cd_wait_hirq");
put(3921644145217220886L, "cd_connect_cd_to_filter");
put(6652641698586143213L, "cd_reset_selector");
put(7118378219280806410L, "cd_end_transfer");
put(-7247300660382144158L, "cd_get_toc");
put(-5748168935487761878L, "scu_reset");
// scsp
put(-366585507627112407L, "scsp_reset");
// vdp2
put(-7281369988693427340L, "vdp2_reset");
put(-617029235865965458L, "vdp2_reset_old");
// arcade
put(-2899734622558521840L, "stv_save_input");
put(8929775529747857369L, "SET_PDR1");
put(-5695376958713899753L, "INIT_SOUND_uuuu");
// bup
put(-934179304925463990L, "set_backup_header");
put(8214877273008696814L, "check_cd_ip_bin");// 1a3c
// compare ipbin cd et bios à 00001b08
// cleanup
put(-6136425346699106145L, "clean_vdp_regs_ram");
}
};
// currentProgram, monitor, log
FidService service = new FidService();
FunctionManager functionManager = currentProgram.getFunctionManager();
FunctionIterator functions = functionManager.getFunctions(true);
for (Function function : functions) {
if (monitor.isCancelled()) {
return;
}
FidHashQuad hashQuad = service.hashFunction(function);
if (hashQuad == null) {
continue;
}
if (fid_hash.containsKey(hashQuad.getFullHash())) {
println("full hash:" + String.valueOf(hashQuad.getFullHash()) + " fname"+function.getName());
function.setName(fid_hash.get(hashQuad.getFullHash()), SourceType.USER_DEFINED);
}
}
}
}
// FUN_00001a18(void)
// 2bl (0x400)
// 0x40000 => 0x6020000
// memcpy(0x6020000, 0x40000, 0x400)
// (*0x6020000)();
// resources
// 00001744
// 0x7000 decompresser vers hram+0x10000 (0x2b0) => 0x1fe4 => 0x2362 = us
// 0x2b0 => 0x4410 = jap
// - header: 10 01 09 E6 FF 7F
// FUN_00002c5c
// (decmpr ?) 0x438c / 0x455c
// decr a 51d0 (logo sega ?)
// FUN_000050ea => decompress sega logo
/*
* FUN_00002c5c(0x51d0, dst, 0x1000) uint FUN_00002c5c(int param_1,int
* *param_2,int param_3)
*
*
*
*
*/
/**
* stv notes (stv110.bin) 00000220 => check reset ? 00003478 => check test btn
* 00004f96 => wait ioport or eprom ? 0000b1c0 => check cartridge
**/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment