Skip to content

Commit 6248c93

Browse files
Fix NES 2.0 exponent-multiplier ROM size parsing
1 parent 14c84e6 commit 6248c93

File tree

1 file changed

+14
-6
lines changed
  • src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES

1 file changed

+14
-6
lines changed

src/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/NES.iNES.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,21 @@ public static bool DetectFromINES(ReadOnlySpan<byte> data, out CartInfo Cart, ou
2727
static int ReadEMFormAreaSize(int msn, int lsb, int nonEMFormBlockSizeKiB)
2828
{
2929
if (msn is not 0xF) return ((msn << 8) | lsb) * nonEMFormBlockSizeKiB;
30-
// else exponent-multiplier form: `2^E * (2*M + 1)` bytes, where M is the least significant 2 bits, and E is the next 6 bits
31-
var prgSize = (2 * (lsb & 0xFC) + 1) << (1 + (lsb & 0x03));
32-
// convert to KiB, rounding up
33-
var frac = prgSize & 0x3FF;
34-
prgSize >>= 10;
35-
return frac is 0 ? prgSize : prgSize + 1;
30+
// else exponent-multiplier form: 2^E * (M * 2 + 1) bytes, where M is the least significant 2 bits, and E is the next 6 bits
31+
32+
// exponent needs to be at least 10 in order to have KiB granularity
33+
// we also can't handle >= 2GiB files, so any exponent too large can't be handled
34+
var exponent = (lsb >> 2) & 0x3F;
35+
if (exponent is < 10 or > 30) throw new InvalidOperationException();
36+
37+
var multiplier = (lsb & 0x03) * 2 + 1;
38+
var prgSize = (1UL << exponent) * (ulong)multiplier;
39+
if (prgSize > int.MaxValue) throw new InvalidOperationException();
40+
41+
// convert to KiB
42+
return (int)(prgSize >> 10);
3643
}
44+
3745
CartV2 = new CartInfo
3846
{
3947
PrgSize = ReadEMFormAreaSize(msn: data[9] & 0x0F, lsb: data[4], nonEMFormBlockSizeKiB: 16),

0 commit comments

Comments
 (0)