[NES] add 6502 BRK instruction and some mapper=2 games (incl. castlevania and megaman)
This commit is contained in:
parent
c4e47c60d4
commit
ee336bec15
BizHawk.Emulation
BizHawk.MultiClient/output
CpuCoreGenerator/MOS 6502
|
@ -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" />
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
static string ClassifyTable = @"
|
||||
NROM 0 1 1
|
||||
NROM 0 2 1
|
||||
UXROM 2 8 0
|
||||
";
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
|
|
|
@ -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--)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue