nes-add vrc7 and fix irq bugs in vrc2,4,6

This commit is contained in:
zeromus 2011-09-25 00:23:47 +00:00
parent afbd3e0ee3
commit a5d31cc488
5 changed files with 238 additions and 3 deletions

View File

@ -139,6 +139,7 @@
</Compile> </Compile>
<Compile Include="Consoles\Nintendo\NES\Boards\VRC2_4.cs" /> <Compile Include="Consoles\Nintendo\NES\Boards\VRC2_4.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\VRC6.cs" /> <Compile Include="Consoles\Nintendo\NES\Boards\VRC6.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\VRC7.cs" />
<Compile Include="Consoles\Nintendo\NES\Core.cs" /> <Compile Include="Consoles\Nintendo\NES\Core.cs" />
<Compile Include="Consoles\Nintendo\NES\iNES.cs" /> <Compile Include="Consoles\Nintendo\NES\iNES.cs" />
<Compile Include="Consoles\Nintendo\NES\NES.cs" /> <Compile Include="Consoles\Nintendo\NES\NES.cs" />

View File

@ -69,7 +69,7 @@ Open bus and bus conflict emulation is not considered complete or thorough in an
079 NINA-06 Complete 079 NINA-06 Complete
080 Misc (J) Nothing 080 Misc (J) Nothing
082 Misc (J) Nothing 082 Misc (J) Nothing
085 VRC7 Needed (lagrange point) 085 VRC7 Decent (no OPL sound)
086 Misc (J) Started (One game I tried didn't work but also didn't match the sha1 (but worked in FCEUX) 086 Misc (J) Started (One game I tried didn't work but also didn't match the sha1 (but worked in FCEUX)
087 Misc (J) Complete 087 Misc (J) Complete
088 Misc (J) Nothing 088 Misc (J) Nothing

View File

@ -5,7 +5,7 @@ using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo namespace BizHawk.Emulation.Consoles.Nintendo
{ {
//mapper 21 + 22 + 23 + 25 (docs largely in 021.txt for VRC4 and 22.txt for VRC2) //mapper 21 + 22 + 23 + 25 (docs largely in 021.txt for VRC4 and 22.txt for VRC2)
//If you change any of the IRQ logic here, be sure to change it in VRC4 as well. //If you change any of the IRQ logic here, be sure to change it in VRC 6/7 as well.
public class VRC2_4 : NES.NESBoardBase public class VRC2_4 : NES.NESBoardBase
{ {
//configuration //configuration
@ -266,6 +266,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//disabled //disabled
irq_enabled = false; irq_enabled = false;
} }
//acknowledge
irq_pending = false;
SyncIRQ(); SyncIRQ();
break; break;
@ -299,6 +303,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
if (irq_mode) if (irq_mode)
{ {
throw new InvalidOperationException("needed a test case for this; you found one!");
ClockIRQ(); ClockIRQ();
} }
else else

View File

@ -5,7 +5,7 @@ using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo namespace BizHawk.Emulation.Consoles.Nintendo
{ {
//mapper 24 + 26 //mapper 24 + 26
//If you change any of the IRQ logic here, be sure to change it in VRC4 as well. //If you change any of the IRQ logic here, be sure to change it in VRC 2/4/7 as well.
public class VRC6 : NES.NESBoardBase public class VRC6 : NES.NESBoardBase
{ {
//configuration //configuration
@ -198,6 +198,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//disabled //disabled
irq_enabled = false; irq_enabled = false;
} }
//acknowledge
irq_pending = false;
SyncIRQ(); SyncIRQ();
break; break;
@ -228,6 +232,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
if (irq_mode) if (irq_mode)
{ {
throw new InvalidOperationException("needed a test case for this; you found one!");
ClockIRQ(); ClockIRQ();
} }
else else

View File

@ -0,0 +1,224 @@
using System;
using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo
{
//mapper 85
//If you change any of the IRQ logic here, be sure to change it in VRC 2/4/6 as well.
public class VRC7 : NES.NESBoardBase
{
//configuration
int prg_bank_mask_8k, chr_bank_mask_1k;
Func<int, int> remap;
//state
ByteBuffer prg_banks_8k = new ByteBuffer(4);
ByteBuffer chr_banks_1k = new ByteBuffer(8);
bool irq_mode;
bool irq_enabled, irq_pending, irq_autoen;
byte irq_reload;
byte irq_counter;
int irq_prescaler;
public override void Dispose()
{
base.Dispose();
prg_banks_8k.Dispose();
chr_banks_1k.Dispose();
}
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("prg_banks_8k", ref prg_banks_8k);
ser.Sync("chr_banks_1k", ref chr_banks_1k);
ser.Sync("irq_mode", ref irq_mode);
ser.Sync("irq_enabled", ref irq_enabled);
ser.Sync("irq_pending", ref irq_pending);
ser.Sync("irq_autoen", ref irq_autoen);
ser.Sync("irq_reload", ref irq_reload);
ser.Sync("irq_counter", ref irq_counter);
ser.Sync("irq_prescaler", ref irq_prescaler);
}
void SyncIRQ()
{
NES.irq_cart = (irq_pending && irq_enabled);
}
public override bool Configure(NES.EDetectionOrigin origin)
{
switch (Cart.board_type)
{
case "KONAMI-VRC-7":
AssertPrg(128,512); AssertChr(0,128); AssertVram(0,8); AssertWram(0,8);
break;
default:
return false;
}
if (Cart.pcb == "353429")
//tiny toons 2
remap = (addr) => ((addr & 0xF000) | ((addr & 0x8) >> 3));
else if(Cart.pcb == "352402")
//lagrange point
remap = (addr) => ((addr & 0xF000) | ((addr & 0x10) >> 4));
else throw new Exception("Unknown PCB type for VRC7");
prg_bank_mask_8k = Cart.prg_size / 8 - 1;
chr_bank_mask_1k = Cart.chr_size - 1;
SetMirrorType(EMirrorType.Vertical);
prg_banks_8k[3] = (byte)(0xFF & prg_bank_mask_8k);
return true;
}
public override byte ReadPRG(int addr)
{
int bank_8k = addr >> 13;
int ofs = addr & ((1 << 13) - 1);
bank_8k = prg_banks_8k[bank_8k];
addr = (bank_8k << 13) | ofs;
return ROM[addr];
}
int Map_PPU(int addr)
{
int bank_1k = addr >> 10;
int ofs = addr & ((1 << 10) - 1);
bank_1k = chr_banks_1k[bank_1k];
addr = (bank_1k << 10) | ofs;
return addr;
}
public override byte ReadPPU(int addr)
{
if (addr < 0x2000)
{
addr = Map_PPU(addr);
if (Cart.vram_size != 0)
return base.ReadPPU(addr);
else return VROM[addr];
}
else return base.ReadPPU(addr);
}
public override void WritePPU(int addr, byte value)
{
if (addr < 0x2000)
{
base.WritePPU(Map_PPU(addr),value);
}
else base.WritePPU(addr, value);
}
public override void WritePRG(int addr, byte value)
{
//Console.WriteLine(" mapping {0:X4} = {1:X2}", addr, value);
addr = remap(addr);
//Console.WriteLine("- remapping {0:X4} = {1:X2}", addr, value);
switch (addr)
{
case 0x0000: prg_banks_8k[0] = (byte)(value & prg_bank_mask_8k); break;
case 0x0001: prg_banks_8k[1] = (byte)(value & prg_bank_mask_8k); break;
case 0x1000: prg_banks_8k[2] = (byte)(value & prg_bank_mask_8k); break;
case 0x1001:
//sound address port
break;
case 0x1003:
//sound data port
//TODO - remap will break this
break;
//a bit creepy to mask this for lagrange point which has no VROM, but the mask will be 0xFFFFFFFF so its OK
case 0x2000: chr_banks_1k[0] = (byte)(value & chr_bank_mask_1k); break;
case 0x2001: chr_banks_1k[1] = (byte)(value & chr_bank_mask_1k); break;
case 0x3000: chr_banks_1k[2] = (byte)(value & chr_bank_mask_1k); break;
case 0x3001: chr_banks_1k[3] = (byte)(value & chr_bank_mask_1k); break;
case 0x4000: chr_banks_1k[4] = (byte)(value & chr_bank_mask_1k); break;
case 0x4001: chr_banks_1k[5] = (byte)(value & chr_bank_mask_1k); break;
case 0x5000: chr_banks_1k[6] = (byte)(value & chr_bank_mask_1k); break;
case 0x5001: chr_banks_1k[7] = (byte)(value & chr_bank_mask_1k); break;
case 0x6000:
switch (value & 3)
{
case 0: SetMirrorType(NES.NESBoardBase.EMirrorType.Vertical); break;
case 1: SetMirrorType(NES.NESBoardBase.EMirrorType.Horizontal); break;
case 2: SetMirrorType(NES.NESBoardBase.EMirrorType.OneScreenA); break;
case 3: SetMirrorType(NES.NESBoardBase.EMirrorType.OneScreenB); break;
}
break;
case 0x6001: //(reload)
irq_reload = value;
break;
case 0x7000: //(control)
irq_mode = value.Bit(2);
irq_autoen = value.Bit(0);
if (value.Bit(1))
{
//enabled
irq_enabled = true;
irq_counter = irq_reload;
irq_prescaler = 341;
}
else
{
//disabled
irq_enabled = false;
}
//acknowledge
irq_pending = false;
SyncIRQ();
break;
case 0x7001: //(ack)
irq_pending = false;
irq_enabled = irq_autoen;
SyncIRQ();
break;
}
}
void ClockIRQ()
{
if (irq_counter == 0xFF)
{
irq_pending = true;
irq_counter = irq_reload;
SyncIRQ();
}
else
irq_counter++;
}
public override void ClockPPU()
{
if (!irq_enabled) return;
if (irq_mode)
{
throw new InvalidOperationException("needed a test case for this; you found one!");
ClockIRQ();
}
else
{
irq_prescaler--;
if (irq_prescaler == 0)
{
irq_prescaler += 341;
ClockIRQ();
}
}
}
}
}