nes-mapper 67

This commit is contained in:
zeromus 2012-06-11 06:32:44 +00:00
parent 34dd2812f6
commit 3a336b9ef4
5 changed files with 144 additions and 10 deletions

View File

@ -344,7 +344,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Consoles\Nintendo\Docs\compatibility.txt" />
<Content Include="Consoles\Nintendo\Docs\notes_for_disch.txt" />
<Content Include="Consoles\Nintendo\Docs\sunsoft.txt" />
<Content Include="Consoles\Nintendo\Docs\test_status.txt" />
<Content Include="Consoles\PC Engine\Compat.txt" />
<Content Include="Consoles\Sega\Genesis\Compat.txt" />

View File

@ -54,7 +54,7 @@ Open bus and bus conflict emulation is not considered complete or thorough in an
064 Tengen Good
065 Misc (J) Nothing
066 GxROM Complete
067 Sunsoft-3 Nothing
067 Sunsoft-3 Complete
068 Sunsoft-4 Complete
069 FME7 Minimal
070 Misc Complete

View File

@ -62,6 +62,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
this.NES = nes;
}
public abstract bool Configure(NES.EDetectionOrigin origin);
public virtual void ClockPPU() { }
@ -188,13 +189,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public virtual void AddressPPU(int addr) { }
public virtual byte PeekPPU(int addr) { return ReadPPU(addr); }
/// <summary>
/// reads PPU from a pattern table address. asserts addr lt 0x2000
/// This is just so that we can accelerate things a tiny bit by not checking against 0x2000 excessively
/// </summary>
protected virtual byte ReadPPUChr(int addr)
{
Debug.Assert(addr < 0x2000);
if (VROM != null)
return VROM[addr];
else return VRAM[addr];

View File

@ -8,10 +8,148 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//this may be confusing due to general chaos with the early sunsoft mappers. see docs/sunsoft.txt
class Sunsoft3 : NES.NESBoardBase
{
//configuration
int prg_bank_mask_16k, chr_bank_mask_2k;
//state
bool toggle;
ByteBuffer prg_banks_16k = new ByteBuffer(2);
ByteBuffer chr_banks_2k = new ByteBuffer(4);
int irq_counter;
bool irq_enable;
bool irq_asserted;
int clock_counter;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("toggle", ref toggle);
ser.Sync("prg_banks_16k", ref prg_banks_16k);
ser.Sync("chr_banks_2k", ref chr_banks_2k);
ser.Sync("irq_counter", ref irq_counter);
ser.Sync("irq_enable", ref irq_enable);
ser.Sync("irq_asserted", ref irq_asserted);
ser.Sync("clock_counter", ref clock_counter);
}
public override bool Configure(NES.EDetectionOrigin origin)
{
//TBD
return false;
switch (Cart.board_type)
{
case "MAPPER067":
break;
case "SUNSOFT-3":
AssertPrg(128); AssertChr(128);
break;
default:
return false;
}
prg_bank_mask_16k = (Cart.prg_size / 16) - 1;
chr_bank_mask_2k = (Cart.chr_size / 2) - 1;
prg_banks_16k[0] = 0;
prg_banks_16k[1] = 0xFF;
ApplyMemoryMapMask(prg_bank_mask_16k, prg_banks_16k);
return true;
}
void SetCHR(int block, byte value)
{
chr_banks_2k[block] = value;
ApplyMemoryMapMask(chr_bank_mask_2k, chr_banks_2k);
}
void SyncIRQ()
{
NES.irq_cart = irq_asserted;
}
public override void WritePRG(int addr, byte value)
{
//Console.WriteLine("{0:X4} = {1:X2}", addr, value);
switch (addr & 0xF800)
{
case 0x0800: //0x8800
SetCHR(0, value);
break;
case 0x1800: //0x9800
SetCHR(1, value);
break;
case 0x2800: //0xA800
SetCHR(2, value);
break;
case 0x3800: //0xB800
SetCHR(3, value);
break;
case 0x4800: //0xC800
if (!toggle)
irq_counter = (irq_counter & 0xFF) | (value << 8);
else irq_counter = (irq_counter & 0xFF00) | (value);
toggle ^= true;
break;
case 0x5800: //0xD800
irq_enable = value.Bit(4);
toggle = false;
irq_asserted = false;
SyncIRQ();
break;
case 0x6800: //0xE800:
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 0x7800: //0xF800:
prg_banks_16k[0] = value;
ApplyMemoryMapMask(prg_bank_mask_16k, prg_banks_16k);
break;
}
}
void ClockClock()
{
if (!irq_enable) return;
if (irq_counter == 0)
{
irq_counter = 0xFFFF;
//Console.WriteLine("IRQ!!!");
irq_asserted = true;
SyncIRQ();
irq_enable = false;
}
else irq_counter--;
}
public override byte ReadPRG(int addr)
{
addr = ApplyMemoryMap(14, prg_banks_16k, addr);
return ROM[addr];
}
public override byte ReadPPU(int addr)
{
if (addr < 0x2000)
{
addr = ApplyMemoryMap(11, chr_banks_2k, addr);
return base.ReadPPUChr(addr);
}
else return base.ReadPPU(addr);
}
public override void ClockPPU()
{
clock_counter++;
if (clock_counter == 3)
{
clock_counter = 0;
ClockClock();
}
}
}
}

View File

@ -123,7 +123,7 @@ namespace BizHawk.Emulation.Sound
//case 0x28: Console.WriteLine("Operator Key On/Off Ctrl {0:X2}", value); break;
case 0x2A: DacValue = value; break;
case 0x2B: DacEnable = (value & 0x80) != 0; break;
case 0x2C: throw new Exception("something wrote to ym2612 port $2C!"); break;//http://forums.sonicretro.org/index.php?showtopic=28589
case 0x2C: throw new Exception("something wrote to ym2612 port $2C!"); //http://forums.sonicretro.org/index.php?showtopic=28589
default:
int chan, oper;