[NES] add 6502 BRK instruction and some mapper=2 games (incl. castlevania and megaman)

This commit is contained in:
zeromus 2011-02-28 07:53:19 +00:00
parent c4e47c60d4
commit ee336bec15
10 changed files with 149 additions and 47 deletions
BizHawk.Emulation
BizHawk.MultiClient/output
CpuCoreGenerator/MOS 6502

View File

@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{197D4314-8A9F-49BA-977D-54ACEFAEB6BA}</ProjectGuid>
<OutputType>Library</OutputType>
@ -23,6 +23,7 @@
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -56,6 +57,7 @@
<Compile Include="Consoles\Calculator\TI83.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\NROM.cs" />
<Compile Include="Consoles\Nintendo\NES\BoardDetector.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\UxROM.cs" />
<Compile Include="Consoles\Nintendo\NES\NES.cs" />
<Compile Include="Consoles\Nintendo\NES\Palettes.cs" />
<Compile Include="Consoles\Nintendo\NES\PPU.cs" />

View File

@ -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)));

View File

@ -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 ====
/// <summary>Carry Flag</summary>

View File

@ -40,6 +40,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
static string ClassifyTable = @"
NROM 0 1 1
NROM 0 2 1
UXROM 2 8 0
";
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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");

View File

@ -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--)

View File

@ -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
;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

View File

@ -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;