mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
patterns: More accurate variable declarations on nes.hexpat, add n64, gen, and gbx.hexpat (#477)
* Add n64, gen, and gbx.hexpat * Add n64, gbx, and gen.hexpat to README.md * Remove leftover string import from n64.hexpat * More accurate variable declarations on nes.hexpat * Add source to gbx.hexpat * Add accidentally missing curly brace in nes.hexpat
This commit is contained in:
61
patterns/gbx.hexpat
Normal file
61
patterns/gbx.hexpat
Normal file
@@ -0,0 +1,61 @@
|
||||
#pragma author gmestanley
|
||||
#pragma description GameBoy ROM file GBX footer
|
||||
#pragma source hhug.me/gbx/1.0
|
||||
|
||||
import gb;
|
||||
|
||||
bitfield SachenMMC2SolderPad {
|
||||
padding : 5;
|
||||
opt1 : 1;
|
||||
openBus512KiBOuterBanks : 1;
|
||||
openBus1MiBOuterBanks : 1;
|
||||
};
|
||||
|
||||
bitfield VastFameRunningValueType {
|
||||
TaiwanReleases : 1;
|
||||
MainlandChinaReleases : 1;
|
||||
};
|
||||
|
||||
enum VastFamePCBType : u8 {
|
||||
DSHGGB81,
|
||||
BCR1616T3P
|
||||
};
|
||||
|
||||
fn specialMapper(str value) { return value == "SAM2" || value == "VF01" || value == "GB81"; };
|
||||
|
||||
struct MapperVariables {
|
||||
match(parent.mapper) {
|
||||
("SAM2"): SachenMMC2SolderPad solderPadConfig;
|
||||
("VF01"): VastFameRunningValueType runningValue;
|
||||
("GB81"): VastFamePCBType pcb; }
|
||||
padding[3*specialMapper(parent.mapper)];
|
||||
u32 mapperVariables[8-specialMapper(parent.mapper)];
|
||||
};
|
||||
|
||||
struct CartridgeInformation {
|
||||
char mapper[4];
|
||||
bool battery;
|
||||
bool rumble;
|
||||
bool timer;
|
||||
padding[1];
|
||||
u32 romSize;
|
||||
u32 ramSize;
|
||||
if (specialMapper(mapper))
|
||||
MapperVariables mapperVariables;
|
||||
else
|
||||
MapperVariables mapperVariables [[inline]];
|
||||
};
|
||||
|
||||
struct GBXMetadata {
|
||||
u32 footerSize;
|
||||
u32 majorVersion;
|
||||
u32 minorVersion;
|
||||
char signature[4];
|
||||
};
|
||||
|
||||
struct GBXFooter {
|
||||
CartridgeInformation cartInfo;
|
||||
GBXMetadata metadata;
|
||||
};
|
||||
|
||||
be GBXFooter gbxFooter @ std::mem::size() - 0x40;
|
||||
137
patterns/gen.hexpat
Normal file
137
patterns/gen.hexpat
Normal file
@@ -0,0 +1,137 @@
|
||||
#pragma author gmestanley
|
||||
#pragma description Sega Genesis/MegaDrive header
|
||||
#pragma source plutiedev.com/rom-header wiki.neogeodev.org/index.php?title=68k_vector_table
|
||||
|
||||
#pragma endian big
|
||||
|
||||
import std.string;
|
||||
|
||||
struct M68000Vectors {
|
||||
u32 stackPointerReset;
|
||||
u32 programCounterReset [[comment("Entry Point")]];
|
||||
u32 busError;
|
||||
u32 addressError;
|
||||
u32 illegalInstruction;
|
||||
u32 divisionByZero;
|
||||
u32 chkInstruction;
|
||||
u32 trapVInstruction;
|
||||
u32 privilegeViolation;
|
||||
u32 trace;
|
||||
u32 lineAInstruction;
|
||||
u32 lineFInstruction;
|
||||
padding[12];
|
||||
u32 uninitializedInterruptVector;
|
||||
padding[32];
|
||||
u32 spuriousInterrupt;
|
||||
u32 interruptAutovectors[7];
|
||||
u32 traps[16];
|
||||
};
|
||||
|
||||
M68000Vectors vectors @ 0x00;
|
||||
|
||||
struct Info {
|
||||
char softwareType[2];
|
||||
char space;
|
||||
char serialNumber[8];
|
||||
char dash;
|
||||
char revision[2];
|
||||
};
|
||||
|
||||
enum DeviceType : char {
|
||||
NotFilled = ' ',
|
||||
Button3Controller = 'J',
|
||||
Button6Controller = '6',
|
||||
MasterSystemController = '0',
|
||||
AnalogJoystick = 'A',
|
||||
Multitap = '4',
|
||||
Lightgun = 'G',
|
||||
Activator = 'L',
|
||||
Mouse = 'M',
|
||||
Trackball = 'B',
|
||||
Mouse = 'T',
|
||||
Trackball = 'V',
|
||||
Keyboard = 'K',
|
||||
RS232 = 'R',
|
||||
Printer = 'P',
|
||||
CDROM = 'C',
|
||||
FloppyDrive = 'F',
|
||||
Download = 'D'
|
||||
};
|
||||
|
||||
bitfield RAMType {
|
||||
addresses : 1;
|
||||
padding : 3;
|
||||
bits : 2;
|
||||
saves : 1;
|
||||
sig : 1;
|
||||
};
|
||||
|
||||
enum MemoryType : char {
|
||||
RAM = ' ',
|
||||
EEPROM = '@'
|
||||
};
|
||||
|
||||
struct ExtraMemory {
|
||||
char signature[2];
|
||||
RAMType ramType;
|
||||
MemoryType memoryType;
|
||||
u32 startAddress;
|
||||
u32 endAddress;
|
||||
};
|
||||
|
||||
fn renderMicrophoneType(str value) {
|
||||
match(value) {
|
||||
("00"): value = "NoMicJapanOnly";
|
||||
("10"): value = "MicJapanOnly";
|
||||
("20"): value = "NoMicOverseasOnly";
|
||||
("30"): value = "MicOverseasOnly";
|
||||
("40"): value = "NoMic";
|
||||
("50"): value = "Mic";
|
||||
("60"): value = "NoMicJapan";
|
||||
("70"): value = "NoMicOverseas";
|
||||
}
|
||||
};
|
||||
|
||||
struct ModemSupport {
|
||||
char signature[2];
|
||||
char publisher[4];
|
||||
char gameNumber[2];
|
||||
char comma;
|
||||
char version;
|
||||
char microphone[2] [[format("renderMicrophoneType")]];
|
||||
};
|
||||
|
||||
enum RegionType : char {
|
||||
None = ' ',
|
||||
Japan = 'J',
|
||||
Americas = 'U',
|
||||
Europe = 'E'
|
||||
};
|
||||
|
||||
fn formatTerminatedString(str string) {
|
||||
u8 index;
|
||||
while (index < std::string::length(string)) {
|
||||
if (std::mem::read_string($+index, 2) == " ")
|
||||
break;
|
||||
index += 1;
|
||||
}
|
||||
return "\"" + std::string::substr(string, 0, index) + "\"";
|
||||
};
|
||||
|
||||
struct Header {
|
||||
char systemType[16] [[format("formatTerminatedString")]];
|
||||
char copyright[16] [[format("formatTerminatedString")]];
|
||||
char domesticTitle[48] [[format("formatTerminatedString")]];
|
||||
char overseasTitle[48] [[format("formatTerminatedString")]];
|
||||
Info info;
|
||||
u16 checksum;
|
||||
DeviceType deviceType[16];
|
||||
u32 romAddressRange[2];
|
||||
u32 ramAddressRange[2];
|
||||
if ($[$] == 'R') ExtraMemory extraMemory; else padding[12];
|
||||
if ($[$] == 'M') ModemSupport modemSupport; else padding[12];
|
||||
padding[40];
|
||||
RegionType regions[3];
|
||||
};
|
||||
|
||||
Header header @ 0x100;
|
||||
4
patterns/n64.hexpat
Normal file
4
patterns/n64.hexpat
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma author gmestanley
|
||||
#pragma description Nintendo 64 ROM header
|
||||
|
||||
char name[20] @ 0x20;
|
||||
@@ -124,7 +124,7 @@ enum ExtendedConsoleType : ConsoleType {
|
||||
VT03,
|
||||
VT09,
|
||||
VT32,
|
||||
VT3xx,
|
||||
VT36x,
|
||||
UM6578,
|
||||
FamicomNetworkSystem
|
||||
};
|
||||
@@ -143,9 +143,33 @@ bitfield MiscellaneousROMsHeaderByte {
|
||||
numberOfMiscellaneousROMs : 2;
|
||||
padding : 6;
|
||||
};
|
||||
|
||||
|
||||
enum DefaultExpansionDeviceType : u8 {
|
||||
Unspecified,
|
||||
StandardControllers,
|
||||
FourScoreorSatellite,
|
||||
FamicomFourPlayersAdapter,
|
||||
VsSystem1P4016h,
|
||||
VsSystem1P4017h,
|
||||
MAMEPinballJapan,
|
||||
VsZapper,
|
||||
Zapper,
|
||||
TwoZappers,
|
||||
BandaiHyperShotLightgun,
|
||||
PowerPadSideA,
|
||||
PowerPadSideB,
|
||||
FamilyTrainerSideA,
|
||||
FamilyTrainerSideB,
|
||||
Multicart = 0x2A
|
||||
};
|
||||
|
||||
fn formatDefaultExpansionDevice(u8 value) {
|
||||
DefaultExpansionDeviceType enumValue = value;
|
||||
return enumValue;
|
||||
};
|
||||
|
||||
bitfield DefaultExpansionDevice {
|
||||
defaultExpansionDevice : 6;
|
||||
defaultExpansionDevice : 6 [[format("formatDefaultExpansionDevice")]];
|
||||
};
|
||||
|
||||
struct NES2Attributes {
|
||||
@@ -171,16 +195,17 @@ fn renderEOF(str string) {
|
||||
return "\"NES<EOF>\"";
|
||||
};
|
||||
|
||||
u8 FILLED_NES2_FLAGS = 0b1100;
|
||||
struct Header {
|
||||
char identifier[4] [[format("renderEOF")]];
|
||||
u8 prgROMSizeBy16KiBs;
|
||||
u8 chrROMSizeBy8KiBs;
|
||||
Flags flags;
|
||||
if ($[0x07] & 12 != 4) {
|
||||
if ($[0x07] & FILLED_NES2_FLAGS != 0b100) {
|
||||
iNESFlags7 inesFlags7;
|
||||
if (inesFlags7.nes2Format)
|
||||
NES2Attributes nes2Attributes;
|
||||
else if ($[0x07] & 12 == 0 && !std::mem::read_unsigned(0x0C, 4)) {
|
||||
else if ($[0x07] & FILLED_NES2_FLAGS == 0 && !std::mem::read_unsigned(0x0C, 4)) {
|
||||
u8 prgRAMSizeBy8KiBs;
|
||||
iNESFlags9 inesFlags9;
|
||||
iNESFlags10 inesFlags10;
|
||||
@@ -191,10 +216,9 @@ struct Header {
|
||||
Header header @ 0x00;
|
||||
|
||||
u8 FILLED_HIGHER_NYBBLE = 0b1111;
|
||||
u8 FILLED_NES2_FLAGS = 0b1100;
|
||||
u8 SET_NES2_FLAGS = 0b1000;
|
||||
u16 mapperValue = (0x0100 * ($[0x08] & FILLED_HIGHER_NYBBLE)) * ($[7] & FILLED_NES2_FLAGS == SET_NES2_FLAGS)
|
||||
+ (0x10 * ($[0x07] >> 4)) * ($[7] & FILLED_NES2_FLAGS != 0b100)
|
||||
+ (0x10 * ($[0x07] >> 4)) * ($[0x07] & FILLED_NES2_FLAGS != 0b100)
|
||||
+ header.flags.lowerMapperNybble;
|
||||
fn identifyMapper(u16 mapperValue, u8 submapperValue) {
|
||||
str mapper;
|
||||
@@ -202,7 +226,7 @@ fn identifyMapper(u16 mapperValue, u8 submapperValue) {
|
||||
str designation;
|
||||
match (mapperValue) {
|
||||
(0): mapper = "No mapper";
|
||||
(1): mapper = "MMC1B";
|
||||
(1): mapper = "Nintendo MMC1B";
|
||||
(2): mapper = "UxROM";
|
||||
(3): mapper = "CNROM-32";
|
||||
(4): mapper = "MMC3";
|
||||
@@ -229,7 +253,7 @@ fn identifyMapper(u16 mapperValue, u8 submapperValue) {
|
||||
(25): mapper = "Konami VRC4d or VRC2c + VRC4b";
|
||||
(26): mapper = "Konami VRC6b";
|
||||
(27): mapper = "World Hero";
|
||||
(28): mapper = "Action 53, homebrew";
|
||||
(28): mapper = "InfiniteNESLives' Action 53";
|
||||
(29): mapper = "RET-CUFROM";
|
||||
(30): mapper = "UNROM 512";
|
||||
(31): mapper = "NSF";
|
||||
@@ -246,8 +270,8 @@ fn identifyMapper(u16 mapperValue, u8 submapperValue) {
|
||||
(42): mapper = "FDS -> NES Hacks";
|
||||
(43): mapper = "TONY-I/YS-612";
|
||||
(44): mapper = "Super Big 7-in-1";
|
||||
(45): mapper = "GA23C";
|
||||
(46): mapper = "Lite Star Rumble Station";
|
||||
(45): mapper = "GA23C"; //TC3294 according to NintendulatorNRS
|
||||
(46): mapper = "Lite Star's Rumble Station";
|
||||
(47): mapper = "Nintendo Super Spike V'Ball + NWC";
|
||||
(48): mapper = "Taito TC0690";
|
||||
(49): mapper = "Super HIK 4-in-1";
|
||||
@@ -294,18 +318,40 @@ fn identifyMapper(u16 mapperValue, u8 submapperValue) {
|
||||
(90): mapper = "J.Y. Company ASIC [ROM nametables & extended mirroring]";
|
||||
(91): mapper = "J.Y. Company clone boards";
|
||||
(92): mapper = "Jaleco JF-17 [16 KiB PRG ROM]";
|
||||
(124): mapper = "Super Game Mega Type III";
|
||||
(126): mapper = "TEC9719";
|
||||
(132): mapper = "TXC 05-00002-010";
|
||||
(173): mapper = "C&E 05-00002-010";
|
||||
(187): mapper = "Kǎ Shèng A98402";
|
||||
(256): mapper = "V.R. Technology OneBus";
|
||||
(269): mapper = "Nice Code Games Xplosion 121-in-1";
|
||||
(355): mapper = "Jùjīng 3D-BLOCK";
|
||||
(419): mapper = "Taikee TK-8007 MCU";
|
||||
(422): mapper = "ING-022";
|
||||
(423): mapper = "Lexibook Compact Cyber Arcade";
|
||||
(424): mapper = "Lexibook Retro TV Game Console";
|
||||
(425): mapper = "Cube Tech Handheld";
|
||||
(426): mapper = "V.R. Technology OneBus [Serial ROM in GPIO]";
|
||||
(534): mapper = "ING003C";
|
||||
(594): mapper = "Rinco FSG2";
|
||||
(595): mapper = "NES-4MROM-512";
|
||||
}
|
||||
match (mapperValue) {
|
||||
(0): designation = "NROM";
|
||||
(1): designation = "SxROM";
|
||||
(4): designation = "TxROM";
|
||||
(4): {
|
||||
if (header.prgROMSizeBy16KiBs >= 8 && header.chrROMSizeBy8KiBs >= 16) {
|
||||
if (($[0x08] != 1 && ($[0x07] & FILLED_NES2_FLAGS == 0 && !std::mem::read_unsigned(0x0C, 4))) ||
|
||||
($[0x0A]&FILLED_HIGHER_NYBBLE!=7 && ($[0x07] & FILLED_NES2_FLAGS == SET_NES2_FLAGS)))
|
||||
designation = "TLROM [128~512 KiBs PRG ROM]";
|
||||
else {
|
||||
if (header.flags.batterybackedPRGRAM) designation = "TKROM [128~512 KiBs PRG ROM, 8 KiB PRG RAM]";
|
||||
else designation = "TSROM [128~512 KiBs PRG ROM, 8 KiB PRG RAM, no battery]";
|
||||
}
|
||||
}
|
||||
else if (header.prgROMSizeBy16KiBs == 4) designation = "TBROM [64 KiBs PRG ROM]";
|
||||
else designation = "TxROM";
|
||||
}
|
||||
}
|
||||
if (mapperValue == 3) {
|
||||
match (submapperValue) {
|
||||
@@ -355,6 +401,22 @@ fn identifyMapper(u16 mapperValue, u8 submapperValue) {
|
||||
(1): submapper = "82-in-1";
|
||||
}
|
||||
}
|
||||
else if (mapperValue == 256 || mapperValue == 419) {
|
||||
match (submapperValue) {
|
||||
(0): submapper = "Normal";
|
||||
(1): submapper = "Waixing VT03";
|
||||
(2): submapper = "Nice Code VT02";
|
||||
(3): submapper = "Hummer Technology";
|
||||
(4): submapper = "Nice Code VT03";
|
||||
(5): submapper = "Waixing VT02";
|
||||
(11): submapper = "Vibes";
|
||||
(12): submapper = "Cheertone";
|
||||
(13): submapper = "Cube Tech";
|
||||
(14): submapper = "Unknown developer (Publisher: Karaoto)";
|
||||
(15): submapper = "JungleTac Fuzhou";
|
||||
}
|
||||
submapper += " wiring";
|
||||
}
|
||||
std::print("Mapper: " + mapper + " (" + std::string::to_string(mapperValue) + ")");
|
||||
if (submapper) std::print("Submapper: " + submapper + " (" + std::string::to_string(submapperValue) + ")");
|
||||
if (designation) std::print("Designation: " + designation);
|
||||
@@ -422,7 +484,7 @@ enum EncodingType : u8 {
|
||||
|
||||
fn titleLength(u8 value) { return value+1; };
|
||||
|
||||
struct OfficialHeader {
|
||||
struct Footer {
|
||||
char title[16] [[hex::spec_name("Title Registration Area")]];
|
||||
u16 programChecksum;
|
||||
u16 characterChecksum;
|
||||
@@ -431,7 +493,7 @@ struct OfficialHeader {
|
||||
EncodingType encodingType [[hex::spec_name("Registration Characters Type Distinction")]];
|
||||
u8 titleLength [[hex::spec_name("Registration Characters Count"), transform("titleLength")]];
|
||||
u8 licenseeID [[hex::spec_name("Maker Code")]];
|
||||
u8 complementaryChecksum [[hex::spec_name("Checksum for characterChecksum~makerID")]];
|
||||
u8 complementaryChecksum [[hex::spec_name("Checksum for Character Checksum~Maker Code")]];
|
||||
};
|
||||
|
||||
u16 PRGROM_MINIMUM_SIZE = 16384;
|
||||
@@ -439,7 +501,7 @@ u8 LOWER_TWO_DIGITS = 0b11;
|
||||
u32 calculatedPRGROMSize = (std::mem::size()-16-(4096*($[0x0E]&LOWER_TWO_DIGITS))) * ($[0x09]&FILLED_HIGHER_NYBBLE==0x0F)
|
||||
+ (PRGROM_MINIMUM_SIZE * ((0x0100 * ($[0x09] & FILLED_HIGHER_NYBBLE)) * ($[0x07] & FILLED_NES2_FLAGS == SET_NES2_FLAGS) + header.prgROMSizeBy16KiBs)) * ($[0x09]&FILLED_HIGHER_NYBBLE!=0x0F);
|
||||
|
||||
fn hasOfficialHeader() {
|
||||
fn hasFooter() {
|
||||
u8 sum;
|
||||
for (u8 i = 0, i < 8, i += 1) {
|
||||
sum += $[(calculatedPRGROMSize - 14) + i];
|
||||
@@ -447,13 +509,13 @@ fn hasOfficialHeader() {
|
||||
return !sum;
|
||||
};
|
||||
|
||||
u8 OFFICIAL_HEADER_SIZE = 26;
|
||||
u8 FOOTER_SIZE = 26;
|
||||
u8 VECTORS_SIZE = 6;
|
||||
|
||||
struct PRGROM {
|
||||
u8 data[calculatedPRGROMSize - OFFICIAL_HEADER_SIZE * hasOfficialHeader() - VECTORS_SIZE];
|
||||
if (hasOfficialHeader())
|
||||
OfficialHeader officialHeader;
|
||||
u8 data[calculatedPRGROMSize - FOOTER_SIZE * hasFooter() - VECTORS_SIZE];
|
||||
if (hasFooter())
|
||||
Footer footer;
|
||||
u16 nmi;
|
||||
u16 resetVector [[comment("Entry Point")]];
|
||||
u16 externalIRQ;
|
||||
@@ -470,8 +532,8 @@ struct MiscellaneousROMs {
|
||||
u8 decryptionDataPROM[16];
|
||||
u8 decryptionCounterOutPROM[16];
|
||||
}
|
||||
else if ($[0x0D] == ExtendedConsoleType::VT3xx) {
|
||||
u8 embeddedROM[4096];
|
||||
else if ($[0x0D] == ExtendedConsoleType::VT369) {
|
||||
u8 embeddedROM[std::mem::size()-calculatedCHRROMSize-calculatedPRGROMSize-sizeof(trainer)-0x10];
|
||||
}
|
||||
else if (mapperValue == 355) {
|
||||
u8 antiCloningROM[1024];
|
||||
|
||||
Reference in New Issue
Block a user