Skip to content

Commit

Permalink
patterns: Added GBA ROM pattern (#323)
Browse files Browse the repository at this point in the history
* add support for cartridge size type $54

Added support for cartridge size type $54, corresponding to 1.5 MiB (96 banks).

* add missing license

* Add GBA Cartridge Header

* Update README.md

Added GBA information to README.md and corrected a typo.
  • Loading branch information
GekySan authored Nov 28, 2024
1 parent 5ffc583 commit 500a3fe
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| File System | | [`patterns/fs.hexpat`](patterns/fs.hexpat) | Drive File System |
| FLAC | `audio/flac` | [`patterns/flac.hexpat`](patterns/flac.hexpat) | Free Lossless Audio Codec, FLAC Audio Format |
| Flipper Zero Settings | | [`patterns/flipper_settings.hexpat`](patterns/flipper_settings.hexpat) | Flipper Zero Settings Files |
| GB | `application/x-gameboy-rom` | [`patterns/gb.hexpat`](patterns/gb.hexpat) | Gameboy ROM |
| GB | `application/x-gameboy-rom` | [`patterns/gb.hexpat`](patterns/gb.hexpat) | Game Boy ROM |
| GBA | `application/x-gameboy-advance-rom` | [`patterns/gba.hexpat`](patterns/gba.hexpat) | Game Boy Advance ROM header |
| GGUF | | [`patterns/gguf.hexpat`](patterns/gguf.hexpat) | GGML Inference Models |
| GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files |
| GLTF | `model/gltf-binary` | [`patterns/gltf.hexpat`](patterns/gltf.hexpat) | GL Transmission Format binary 3D model file |
Expand Down
175 changes: 175 additions & 0 deletions patterns/gba.hexpat
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#pragma author GekySan
#pragma description Game Boy Advance ROM Header

#pragma MIME application/x-gameboy-advance-rom
#pragma MIME application/x-agb-rom
#pragma MIME application/x-gba-rom

import std.string;
import std.mem;
import std.sys;

// In gb.hexpat
namespace format {
fn licensee_code(str code) {
match(code) {
("00"): return "None";
("01" | "31"): return "Nintendo";
("08" | "38"): return "Capcom";
("09"): return "Hot-B";
("0A" | "E0"): return "Jaleco";
("0B"): return "Coconuts Japan";
("0C" | "6E"): return "Elite Systems";
("13" | "69"): return "EA (Electronic Arts)";
("18"): return "Hudsonsoft";
("19"): return "ITC Entertainment";
("1A"): return "Yanoman";
("1D"): return "Japan Clary";
("1F" | "4A" | "61"): return "Virgin Interactive";
("24"): return "PCM Complete";
("25"): return "San-X";
("28"): return "Kotobuki Systems";
("29"): return "Seta";
("30" | "70"): return "Infogrames";
("32" | "A2" | "B2" | "C4"): return "Bandai";
("33"): return "See new licensee code";
("34" | "A4"): return "Konami";
("35"): return "HectorSoft";
("39" | "9D"): return "Banpresto";
("3C"): return ".Entertainment i";
("3E"): return "Gremlin";
("41"): return "Ubisoft";
("42" | "EB"): return "Atlus";
("44" | "4D"): return "Malibu";
("46" | "CF"): return "Angel";
("47"): return "Spectrum Holoby";
("49"): return "Irem";
("4F"): return "U.S. Gold";
("50"): return "Absolute";
("51" | "B0"): return "Acclaim";
("52"): return "Activision";
("53"): return "American Sammy";
("54"): return "GameTek";
("55"): return "Park Place";
("56" | "DB" | "FF"): return "LJN";
("57"): return "Matchbox";
("59"): return "Milton Bradley";
("5A"): return "Mindscape";
("5B"): return "Romstar";
("5C" | "D6"): return "Naxat Soft";
("5D"): return "Tradewest";
("60"): return "Titus";
("67"): return "Ocean Interactive";
("6F"): return "Electro Brain";
("71"): return "Interplay";
("72" | "AA"): return "Broderbund";
("73"): return "Sculptered Soft";
("75"): return "The Sales Curve";
("78"): return "t.hq";
("79"): return "Accolade";
("7A"): return "Triffix Entertainment";
("7C"): return "Microprose";
("7F" | "C2"): return "Kemco";
("80"): return "Misawa Entertainment";
("83"): return "Lozc";
("86" | "C4"): return "Tokuma Shoten Intermedia";
("8B"): return "Bullet-Proof Software";
("8C"): return "Vic Tokai";
("8E"): return "Ape";
("8F"): return "I'Max";
("91"): return "Chunksoft Co.";
("92"): return "Video System";
("93"): return "Tsubaraya Productions Co.";
("95"): return "Varie Corporation";
("96"): return "Yonezawa/S’Pal";
("97"): return "Kaneko";
("99"): return "Arc";
("9A"): return "Nihon Bussan";
("9B"): return "Tecmo";
("9C"): return "Imagineer";
("9F"): return "Nova";
("A1"): return "Hori Electric";
("A6"): return "Kawada";
("A7"): return "Takara";
("A9"): return "Technos Japan";
("AC"): return "Toei Animation";
("AD"): return "Toho";
("AF"): return "Namco";
("B1"): return "ASCII or Nexsoft";
("B4"): return "Square Enix";
("B6"): return "HAL Laboratory";
("B7"): return "SNK";
("B9" | "CE"): return "Pony Canyon";
("BA"): return "Culture Brain";
("BB"): return "Sunsoft";
("BD"): return "Sony Imagesoft";
("BF"): return "Sammy";
("C0" | "D0"): return "Taito";
("C3"): return "Squaresoft";
("C5"): return "Data East";
("C6"): return "Tonkinhouse";
("C8"): return "Koei";
("C9"): return "UFL";
("CA"): return "Ultra";
("CB"): return "Vap";
("CC"): return "Use Corporation";
("CD"): return "Meldac";
("D1"): return "Sofel";
("D2"): return "Quest";
("D3"): return "Sigma Enterprises";
("D4"): return "ASK Kodansha Co.";
("D7"): return "Copya System";
("DA"): return "Tomy";
("DD"): return "NCS";
("DE"): return "Human";
("DF"): return "Altron";
("E1"): return "Towa Chiki";
("E2"): return "Yutaka";
("E3"): return "Varie";
("E5"): return "Epoch";
("E7"): return "Athena";
("E8"): return "Asmik";
("E9"): return "Natsume";
("EA"): return "King Records";
("EC"): return "Epic/Sony Records";
("EE"): return "IGS";
("F0"): return "A Wave";
("F3"): return "Extreme Entertainment";
}
return "Unknown Licensee";
};
}

fn calcChecksum() {
u8 sum = 0;
u8 offset = 0xA0;

while (offset <= 0xBC) {
sum += std::mem::read_unsigned(offset, 1);
offset += 1;
}

return ((-((0x19 + sum) & 0xFF)) & 0xFF) == std::mem::read_unsigned(0xBD, 1);
};

struct GBAHeader {
u8 entryPoint[4] [[comment("ARM entry point code, typically a 'B rom_start' instruction")]];
u8 nintendoLogo[156] [[comment("Nintendo logo")]];
char gameTitle[12] [[comment("Game title, uppercase ASCII, max 12 characters")]];
char gameCode[4] [[comment("Game code, uppercase ASCII, 4 characters")]];
char makerCode[2] [[format("format::licensee_code"), comment("Maker code, uppercase ASCII, 2 characters")]];
u8 fixedValue [[comment("Fixed value, must be 0x96")]];
u8 unitCode [[comment("Main unit code, identifies required hardware (00h for GBA)")]];
u8 deviceType [[comment("Device type, usually 00h. Bit 7 relates to DACS/debug features")]];
u8 reserved1[7] [[comment("Reserved area, must be zero-filled")]];
u8 softwareVersion [[comment("Software version number, usually 00h")]];
u8 complementCheck [[comment("Header checksum, required for validation")]];
u8 reserved2[2] [[comment("Reserved area, must be zero-filled")]];
};


if (!calcChecksum()) {
std::error("Checksum validation failed: Calculated value does not match the expected checksum in the header.");
}

GBAHeader gbaHeader @ 0x0000;

0 comments on commit 500a3fe

Please sign in to comment.