diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index 2a8a78c439..e390549732 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -3,7 +3,7 @@
Debug
AnyCPU
- 9.0.21022
+ 9.0.30729
2.0
{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}
Library
@@ -23,6 +23,7 @@
4
x86
true
+ false
pdbonly
@@ -56,6 +57,7 @@
+
diff --git a/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs b/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs
index d2ca288a82..9a8cfe6fe0 100644
--- a/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs
+++ b/BizHawk.Emulation/CPUs/MOS 6502/Execute.cs
@@ -17,28 +17,20 @@ namespace BizHawk.Emulation.CPUs.M6502
PendingCycles += cycles;
while (PendingCycles > 0)
{
- if (NMI)
- {
- WriteMemory((ushort)(S-- + 0x100), (byte)(PC >> 8));
- WriteMemory((ushort)(S-- + 0x100), (byte)PC);
- byte oldP = P;
- FlagB = false;
- FlagT = true;
- WriteMemory((ushort)(S-- + 0x100), P);
- P = oldP;
- FlagI = true;
- PC = ReadWord(NMIVector);
- PendingCycles -= 7;
- NMI = false;
- }
+ if (NMI)
+ {
+ TriggerException(ExceptionType.NMI);
+ NMI = false;
+ }
+
+ if(debug) Console.WriteLine(State());
-if(debug) Console.WriteLine(State());
ushort this_pc = PC;
byte opcode = ReadMemory(PC++);
switch (opcode)
{
case 0x00: // BRK
-throw new Exception("break");
+TriggerException(ExceptionType.BRK);
break;
case 0x01: // ORA (addr,X)
value8 = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X)));
diff --git a/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs b/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs
index a5eaf6e0c9..b69231c4aa 100644
--- a/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs
+++ b/BizHawk.Emulation/CPUs/MOS 6502/MOS6502.cs
@@ -70,12 +70,34 @@ namespace BizHawk.Emulation.CPUs.M6502
// TODO IRQ, NMI functions
public bool Interrupt;
- public bool NMI;//
+ public bool NMI;
private const ushort NMIVector = 0xFFFA;
private const ushort ResetVector = 0xFFFC;
private const ushort BRKVector = 0xFFFE;
+ enum ExceptionType
+ {
+ BRK, NMI
+ }
+
+ void TriggerException(ExceptionType type)
+ {
+ WriteMemory((ushort)(S-- + 0x100), (byte)(PC >> 8));
+ WriteMemory((ushort)(S-- + 0x100), (byte)PC);
+ byte oldP = P;
+ FlagB = false;
+ FlagT = true;
+ WriteMemory((ushort)(S-- + 0x100), P);
+ P = oldP;
+ FlagI = true;
+ if(type == ExceptionType.NMI)
+ PC = ReadWord(NMIVector);
+ else
+ PC = ReadWord(BRKVector);
+ PendingCycles -= 7;
+ }
+
// ==== End State ====
/// Carry Flag
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs
index aaae7bf8a1..2ed85ee0d8 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/BoardDetector.cs
@@ -40,6 +40,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
static string ClassifyTable = @"
NROM 0 1 1
NROM 0 2 1
+UXROM 2 8 0
";
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs
index 2b54b87aec..57e5760a9d 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NROM.cs
@@ -9,11 +9,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo.Boards
{
base.Initialize(romInfo, nes);
Debug.Assert(romInfo.PRG_Size < 3);
+ mask = (RomInfo.PRG_Size << 14) - 1;
}
public override byte ReadPRG(int addr)
{
- addr &= (RomInfo.PRG_Size << 14) - 1;
+ addr &= mask;
return RomInfo.ROM[addr];
}
+
+ int mask;
}
}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs
new file mode 100644
index 0000000000..9f0edd4eca
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/UxROM.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Diagnostics;
+
+namespace BizHawk.Emulation.Consoles.Nintendo.Boards
+{
+ public class UxROM : NES.NESBoardBase
+ {
+ string type;
+ public UxROM(string type)
+ {
+ this.type = type;
+ }
+ public override void Initialize(NES.RomInfo romInfo, NES nes)
+ {
+ base.Initialize(romInfo, nes);
+ Debug.Assert(Util.IsPowerOfTwo(RomInfo.PRG_Size));
+
+ if (type == "UNROM") pagemask = 7;
+ else if (type == "UOROM") pagemask = 15;
+ else throw new InvalidOperationException("Invalid UXROM type");
+
+ //guess CRAM size (this is a very confident guess!)
+ if (RomInfo.CRAM_Size == -1) RomInfo.CRAM_Size = 8;
+
+ cram = new byte[RomInfo.CRAM_Size * 1024];
+ cram_mask = cram.Length - 1;
+ }
+ public override byte ReadPRG(int addr)
+ {
+ int block = addr >> 14;
+ int page = block == 1 ? pagemask : prg;
+ page &= pagemask;
+ int ofs = addr & 0x3FFF;
+ return RomInfo.ROM[(page << 14) | ofs];
+ }
+ public override void WritePRG(int addr, byte value)
+ {
+ prg = value;
+ }
+
+ public override byte ReadPPU(int addr)
+ {
+ if (addr < 0x2000)
+ {
+ return cram[addr & cram_mask];
+ }
+ else return base.ReadPPU(addr);
+ }
+
+ public override void WritePPU(int addr, byte value)
+ {
+ if (addr < 0x2000)
+ {
+ cram[addr & cram_mask] = value;
+ }
+ else base.WritePPU(addr,value);
+ }
+
+ int pagemask;
+ int prg;
+ byte[] cram;
+ int cram_mask;
+ }
+}
\ No newline at end of file
diff --git a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs
index 3c08a50b64..18311b1970 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/NES/NES.cs
@@ -22,7 +22,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
public EHeaderType HeaderType;
- public int PRG_Size = -1, CHR_Size = -1, PRAM_Size = -1;
+ public int PRG_Size = -1, CHR_Size = -1;
+ public int CRAM_Size = -1, NVWRAM_Size = -1, WRAM_Size = -1;
public string BoardName;
public EMirrorType MirrorType;
public bool Battery;
@@ -38,10 +39,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
byte ReadPRG(int addr);
byte ReadPPU(int addr);
- byte ReadPRAM(int addr);
+ byte ReadWRAM(int addr);
void WritePRG(int addr, byte value);
void WritePPU(int addr, byte value);
- void WritePRAM(int addr, byte value);
+ void WriteWRAM(int addr, byte value);
void Initialize(RomInfo romInfo, NES nes);
};
@@ -82,8 +83,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public virtual byte ReadPRG(int addr) { return RomInfo.ROM[addr];}
public virtual void WritePRG(int addr, byte value) { }
- public virtual void WritePRAM(int addr, byte value) { }
- public virtual byte ReadPRAM(int addr) { return 0xFF; }
+ public virtual void WriteWRAM(int addr, byte value) { }
+ public virtual byte ReadWRAM(int addr) { return 0xFF; }
public virtual void WritePPU(int addr, byte value)
@@ -533,11 +534,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
ret.CHR_Size = VROM_size;
ret.Battery = (ROM_type & 2) != 0;
- fixed (iNES_HEADER* self = &this) ret.PRAM_Size = self->reserve[0];
+ fixed (iNES_HEADER* self = &this) ret.WRAM_Size = self->reserve[0] * 8;
//0 is supposed to mean 1 (for compatibility, as this is an extension to original iNES format)
- //but we're not worrying about that for now)
+ if (ret.WRAM_Size == 0) ret.WRAM_Size = 8;
- Console.WriteLine("iNES header: map:{0}, mirror:{1}, PRG:{2}, CHR:{3}, PRAM:{4}, bat:{5}", ret.MapperNumber, ret.MirrorType, ret.PRG_Size, ret.CHR_Size, ret.PRAM_Size, ret.Battery ? 1 : 0);
+ Console.WriteLine("iNES header: map:{0}, mirror:{1}, PRG:{2}, CHR:{3}, CRAM:{4}, WRAM:{5}, NVWRAM:{6}, bat:{7}", ret.MapperNumber, ret.MirrorType, ret.PRG_Size, ret.CHR_Size, ret.CRAM_Size, ret.WRAM_Size, ret.NVWRAM_Size, ret.Battery ? 1 : 0);
//fceux calls uppow2(PRG_Banks) here, and also ups the chr size as well
//then it does something complicated that i don't understand with making sure it doesnt read too much data
@@ -598,12 +599,17 @@ namespace BizHawk.Emulation.Consoles.Nintendo
romInfo.PRG_Size = int.Parse(dict["PRG"]);
if (dict.ContainsKey("CHR"))
romInfo.CHR_Size = int.Parse(dict["CHR"]);
+ if (dict.ContainsKey("CRAM"))
+ romInfo.CRAM_Size = int.Parse(dict["CRAM"]);
+ if (dict.ContainsKey("bug"))
+ Console.WriteLine("game is known to be BUGGED!!!");
}
//construct board (todo)
switch (romInfo.BoardName)
{
case "NROM": board = new Boards.NROM(); break;
+ case "UNROM": board = new Boards.UxROM("UNROM"); break;
}
if (board == null) throw new InvalidOperationException("Couldn't classify NES rom");
diff --git a/BizHawk.Emulation/Util.cs b/BizHawk.Emulation/Util.cs
index 7f11d5575a..89be102a48 100644
--- a/BizHawk.Emulation/Util.cs
+++ b/BizHawk.Emulation/Util.cs
@@ -282,6 +282,13 @@ namespace BizHawk
public static class Util
{
+ public static bool IsPowerOfTwo(int x)
+ {
+ if (x == 0) return true;
+ if (x == 1) return true;
+ return (x & (x - 1)) == 0;
+ }
+
public static int SaveRamBytesUsed(byte[] SaveRAM)
{
for (int j = SaveRAM.Length - 1; j >= 0; j--)
diff --git a/BizHawk.MultiClient/output/gamedb.txt b/BizHawk.MultiClient/output/gamedb.txt
index b464a2342a..2a10df42dc 100644
--- a/BizHawk.MultiClient/output/gamedb.txt
+++ b/BizHawk.MultiClient/output/gamedb.txt
@@ -2258,6 +2258,7 @@ B486A8ED Dai Makai Mura SGX
D4448D09BBFDE687C04F9E3310E023AB ti83_1.rom TI83 initPC=6ce
+;NROM 1,1
1457475741846A01399DC663135A60C1 Balloon Fight (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
576AB245B4F04C670AC312AB0D441697 Baseball (UE) NES board=NROM;mirror=H;PRG=1;CHR=1
0F9C8D3D3099C70368411F6DF9EF49C1 Bomberman (U) NES board=NROM;mirror=V;PRG=1;CHR=1
@@ -2289,6 +2290,7 @@ B0F0B0CC14958D30E89D06AF182E7CD5 Raid on Bungeling Bay (U) NES board=NROM;mirr
CB7F1463C90CDCDF5EF315C125F12FE2 Urban Champion (JU) NES board=NROM;mirror=V;PRG=1;CHR=1
4635D8D82A86E8B99390A0586C96D536 Wild Gunman (JUE) NES board=NROM;mirror=V;PRG=1;CHR=1
+;NROM 2,1
BD2C15391B0641D43A35E83F5FCE073A 10-Yard Fight (U) NES board=NROM;mirror=H;PRG=2;CHR=1
0B66FDF88964235C434DAFF62837AF60 1942 (JU) NES board=NROM;mirror=H;PRG=2;CHR=1
4B3B120FA98DCAE25FA88B29818572F8 Chubby Cherub (U) NES board=NROM;mirror=V;PRG=2;CHR=1
@@ -2320,4 +2322,15 @@ E7D7225DAD044B624FBAD9C9CA96E835 Wrecking Crew (JUE) NES board=NROM;mirror=H;P
7A528FA727623BA7704FDBB519F3419F Xevious (U) NES board=NROM;mirror=H;PRG=2;CHR=1
;todo videomation(mapper13)
-;starting at arkanoid we have mappers
\ No newline at end of file
+;starting at arkanoid we have mappers
+;http://tuxnes.sourceforge.net/nesmapper.txt a mappers list
+
+;UNROM
+4DE82CFCEADBF1A5E693B669B1221107 Mega Man (U) NES board=UNROM;mirror=V;PRG=8;CHR=0;CRAM=8
+756170BA1E06FA26C60D10114DC6A5AE Castlevania (Rev 0) (U) NES board=UNROM;mirror=V;PRG=8;CHR=0;CRAM=8
+728E05F245AB8B7FE61083F6919DC485 Castlevania (Rev 1) (U) NES board=UNROM;mirror=V;PRG=8;CHR=0;CRAM=8
+5A5C2F4F1CAFB1F55A8DC0D5AD4550E5 Contra (U) NES board=UNROM;mirror=V;PRG=8;CHR=0;CRAM=8
+B480855FFF883B20BA403A2009A7F13C Duck Tales (U) NES board=UNROM;mirror=V;PRG=8;CHR=0;CRAM=8
+
+;mapper66? mhrom? wtf??
+;27100B746D50E6AE6FBAE2C794173240 Metal Gear (U) NES board=UXROM;mirror=H;PRG=8;CHR=0;CRAM=8;bug=1
diff --git a/CpuCoreGenerator/MOS 6502/CoreGenerator.cs b/CpuCoreGenerator/MOS 6502/CoreGenerator.cs
index 0e7f280728..58990fe568 100644
--- a/CpuCoreGenerator/MOS 6502/CoreGenerator.cs
+++ b/CpuCoreGenerator/MOS 6502/CoreGenerator.cs
@@ -329,25 +329,17 @@ namespace M6502
w.WriteLine(" while (PendingCycles > 0)");
w.WriteLine(" {");
- w.WriteLine(" if (NMI)");
- w.WriteLine(" {");
- w.WriteLine(" WriteMemory((ushort)(S-- + 0x100), (byte)(PC >> 8));");
- w.WriteLine(" WriteMemory((ushort)(S-- + 0x100), (byte)PC);");
- w.WriteLine(" byte oldP = P;");
- w.WriteLine(" FlagB = false;");
- w.WriteLine(" FlagT = true;");
- w.WriteLine(" WriteMemory((ushort)(S-- + 0x100), P);");
- w.WriteLine(" P = oldP;");
- w.WriteLine(" FlagI = true;");
- w.WriteLine(" PC = ReadWord(NMIVector);");
- w.WriteLine(" PendingCycles -= 7;");
- w.WriteLine(" NMI = false;");
- w.WriteLine(" }");
- w.WriteLine("");
+ w.WriteLine(" if (NMI)");
+ w.WriteLine(" {");
+ w.WriteLine(" TriggerException(ExceptionType.NMI);");
+ w.WriteLine(" NMI = false;");
+ w.WriteLine(" }");
+ w.WriteLine("");
- w.WriteLine("if(debug) Console.WriteLine(State());");
-
- w.WriteLine(" ushort this_pc = PC;");
+ w.WriteLine(" if(debug) Console.WriteLine(State());");
+ w.WriteLine("");
+
+ w.WriteLine(" ushort this_pc = PC;");
w.WriteLine(" byte opcode = ReadMemory(PC++);");
w.WriteLine(" switch (opcode)");
w.WriteLine(" {");
@@ -386,7 +378,7 @@ namespace M6502
case "BMI": Branch(op, w, "N", true); break;
case "BNE": Branch(op, w, "Z", false); break;
case "BPL": Branch(op, w, "N", false); break;
- case "BRK": w.WriteLine("throw new Exception(\"break\");"); break;
+ case "BRK": w.WriteLine("TriggerException(ExceptionType.BRK);"); break;
case "BVC": Branch(op, w, "V", false); break;
case "BVS": Branch(op, w, "V", true); break;
case "CLC": CLC(op, w); break;