add NES 2.0 cartridge header parsing support
This commit is contained in:
@@ -53,19 +53,33 @@ pub fn init(
|
||||
const flags6 = rom[6];
|
||||
const flags7 = rom[7];
|
||||
|
||||
// NES 2.0 signature.
|
||||
if ((flags7 & 0x0c) == 0x08)
|
||||
return error.UnsupportedNes2;
|
||||
const is_nes2 = (flags7 & 0x0c) == 0x08;
|
||||
|
||||
const mapper_id: u8 =
|
||||
(flags6 >> 4) |
|
||||
(flags7 & 0xf0);
|
||||
var mapper_id: u16 = (flags6 >> 4) | (flags7 & 0xf0);
|
||||
var prg_size: usize = @as(usize, prg_banks) * 0x4000;
|
||||
var chr_size: usize = @as(usize, chr_banks) * 0x2000;
|
||||
|
||||
const prg_size =
|
||||
@as(usize, prg_banks) * 0x4000;
|
||||
if (is_nes2) {
|
||||
mapper_id |= @as(u16, rom[8] & 0x0f) << 8;
|
||||
|
||||
const chr_size =
|
||||
@as(usize, chr_banks) * 0x2000;
|
||||
const prg_msb = rom[9] & 0x0f;
|
||||
if (prg_msb < 0x0f) {
|
||||
prg_size = ((@as(usize, prg_msb) << 8) | prg_banks) * 0x4000;
|
||||
} else {
|
||||
const exponent = (prg_banks >> 2) & 0x3f;
|
||||
const multiplier = prg_banks & 0x03;
|
||||
prg_size = (@as(usize, 1) << @intCast(exponent)) * (multiplier * 2 + 1);
|
||||
}
|
||||
|
||||
const chr_msb = (rom[9] >> 4) & 0x0f;
|
||||
if (chr_msb < 0x0f) {
|
||||
chr_size = ((@as(usize, chr_msb) << 8) | chr_banks) * 0x2000;
|
||||
} else {
|
||||
const exponent = (chr_banks >> 2) & 0x3f;
|
||||
const multiplier = chr_banks & 0x03;
|
||||
chr_size = (@as(usize, 1) << @intCast(exponent)) * (multiplier * 2 + 1);
|
||||
}
|
||||
}
|
||||
|
||||
switch (mapper_id) {
|
||||
0, 3 => {
|
||||
@@ -177,21 +191,21 @@ pub fn init(
|
||||
.vrc4 = _mapper.Vrc4.init(
|
||||
prg_size,
|
||||
chr_size,
|
||||
mapper_id,
|
||||
@truncate(mapper_id),
|
||||
),
|
||||
},
|
||||
22, 23 => .{
|
||||
.vrc2 = _mapper.Vrc2.init(
|
||||
prg_size,
|
||||
chr_size,
|
||||
mapper_id,
|
||||
@truncate(mapper_id),
|
||||
),
|
||||
},
|
||||
24, 26 => .{
|
||||
.vrc6 = _mapper.Vrc6.init(
|
||||
prg_size,
|
||||
chr_size,
|
||||
mapper_id,
|
||||
@truncate(mapper_id),
|
||||
),
|
||||
},
|
||||
34 => .{
|
||||
@@ -1103,3 +1117,15 @@ test "NES Cartridge - Nintendo MMC5 Mapper 5 PRG, CHR Banking & Multiplier" {
|
||||
try std.testing.expectEqual(@as(?u8, 0xd2), mmc5.readRegister(0x5205));
|
||||
try std.testing.expectEqual(@as(?u8, 0x00), mmc5.readRegister(0x5206));
|
||||
}
|
||||
|
||||
test "NES Cartridge - NES 2.0 Header Parsing" {
|
||||
// Header for 128KB PRG, 128KB CHR, Mapper 1 (MMC1), NES 2.0 signature (flags7 0x08)
|
||||
const nes2_header = [_]u8{
|
||||
'N', 'E', 'S', 0x1A, 0x08, 0x10, 0x13, 0x08,
|
||||
0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
} ++ ([_]u8{0} ** (128 * 1024 + 128 * 1024));
|
||||
|
||||
const cart = try Cartridge.init(&nes2_header);
|
||||
try std.testing.expectEqual(@as(usize, 128 * 1024), cart.prg_rom.len);
|
||||
try std.testing.expectEqual(@as(usize, 128 * 1024), cart.chr_rom.len);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user