diff --git a/README.md b/README.md index 171a156..ead1a41 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | NACP | | [`patterns/nacp.hexpat`](patterns/nacp.hexpat) | Nintendo Switch NACP files | | NBT | | [`patterns/nbt.hexpat`](patterns/nbt.hexpat) | Minecraft NBT format | | NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields | +| nes | | [`patterns/nes.hexpat`](patterns/nes.hexpat) | .nes file format | | NRO | | [`patterns/nro.hexpat`](patterns/nro.hexpat) | Nintendo Switch NRO files | | NTAG | | [`patterns/ntag.hexpat`](patterns/ntag.hexpat) | NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC | | OGG | `audio/ogg` | [`patterns/ogg.hexpat`](patterns/ogg.hexpat) | OGG Audio format | diff --git a/patterns/nes.hexpat b/patterns/nes.hexpat new file mode 100644 index 0000000..b5c68c3 --- /dev/null +++ b/patterns/nes.hexpat @@ -0,0 +1,87 @@ +#pragma author gmestanley +#pragma description .nes file format + +#include +#include + +bitfield iNES07Flags { + mirroringIsVertical : 1; + batterybackedPRGRAM : 1; + trainerOf512Bytes : 1; + ignoreMirroring : 1; + mapperLowerNybble : 4; + vsUnisystem : 1; + playchoice10 : 1; + nes2Format : 2 [[name("nes2.0Format")]]; + mapperHigherNybble : 4; +} [[name("iNES0.7Flags")]]; + +bitfield Flags9 { + isPAL : 1; + padding : 7; +}; + +bitfield Flags10 { + tvSystem : 2; + padding : 2; + prgRAM : 1; + busConflicts : 1; + padding : 2; +}; + +struct iNESFlags { + iNES07Flags ines07Flags [[name("ines0.7Flags")]]; + if (!ines07Flags.nes2Format) { + u8 prgRAM8KBMultiplier; + Flags9 flags9; + Flags10 flags10; + restLength = 5; + } + else { + restLength = 9; + } +}; + +u8 restLength; + +struct Header { + char identifier[4]; + u8 prgROM16KBMultiplier; + u8 chrROM8KBMultiplier; + iNESFlags inesFlags; + char rest[restLength]; +}; + +Header header @ 0x00; + +enum EncodingType : u8 { + ASCII = 1 +}; + +struct OfficialHeader { + char title[16] [[hex::spec_name("Title Registration Area")]]; + u16 programChecksum; + u16 characterChecksum; + u8 memorySize [[hex::spec_name("Cartridge Memory Size")]]; + u8 cartridgeType; + EncodingType encodingType [[hex::spec_name("Registration Character Type Distinction")]]; + u8 titleLength [[hex::spec_name("Registration Characters Count")]]; + u8 makerID [[hex::spec_name("Maker Code")]]; + u8 complementaryChecksum; +}; + +union OfficialHeaderUnion { + u8 miscellaneousData[26]; + OfficialHeader officialHeader; +}; + +struct PRGROM { + u8 data[16384*header.prgROM16KBMultiplier-32]; + OfficialHeaderUnion officialHeaderUnion; + u16 nmi; + u16 entryPoint; + u16 externalIRQ; +}; + +PRGROM prgROM @ sizeof(header); +u8 chrROM[8192*header.chrROM8KBMultiplier] @ sizeof(header)+sizeof(prgROM); \ No newline at end of file