NES: preliminary support for PAL, Dendy, and RGB (part 1). at the moment, it's all determined from gamedb, and not at all saved to movies or savestates

This commit is contained in:
goyuken 2012-10-31 18:25:46 +00:00
parent ab4d663d23
commit 7dc5808771
4 changed files with 78 additions and 15 deletions

View File

@ -129,6 +129,51 @@ namespace BizHawk.Emulation.Consoles.Nintendo
apu = new APU(this);
if (magicSoundProvider != null) magicSoundProvider.Dispose();
magicSoundProvider = new MagicSoundProvider(this);
// set up region
if (!string.IsNullOrEmpty(cart.system))
{
switch (cart.system)
{
case "NES-PAL":
case "NES-PAL-A":
case "NES-PAL-B":
ppu.region = PPU.Region.PAL;
CoreOutputComm.VsyncNum = 50;
CoreOutputComm.VsyncDen = 1;
cpu_sequence = cpu_sequence_PAL;
break;
case "NES-NTSC":
case "Famicom":
ppu.region = PPU.Region.NTSC;
cpu_sequence = cpu_sequence_NTSC;
break;
// there's no official name for these in bootgod, not sure what we should use
case "PC10":
case "VS":
ppu.region = PPU.Region.RGB;
cpu_sequence = cpu_sequence_NTSC;
break;
// this is in bootgod, but not used at all
case "Dendy":
ppu.region = PPU.Region.Dendy;
CoreOutputComm.VsyncNum = 50;
CoreOutputComm.VsyncDen = 1;
cpu_sequence = cpu_sequence_NTSC;
break;
default:
Console.WriteLine("Unrecognized NES region \"{0}\"! Defaulting to NTSC.");
ppu.region = PPU.Region.NTSC;
cpu_sequence = cpu_sequence_NTSC;
break;
}
}
else
{
Console.WriteLine("Unknown NES region! Defaulting to NTSC.");
ppu.region = PPU.Region.NTSC;
cpu_sequence = cpu_sequence_NTSC;
}
//fceux uses this technique, which presumably tricks some games into thinking the memory is randomized
for (int i = 0; i < 0x800; i++)
@ -186,13 +231,14 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//sequence of ppu clocks per cpu clock: 4,3,3,3,3
//NTSC:
//sequence of ppu clocks per cpu clock: 3
ByteBuffer cpu_sequence;
static ByteBuffer cpu_sequence_NTSC = new ByteBuffer(new byte[]{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3});
static ByteBuffer cpu_sequence_PAL = new ByteBuffer(new byte[]{4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3});
public int cpu_step, cpu_stepcounter, cpu_deadcounter;
protected void RunCpuOne()
{
cpu_stepcounter++;
if (cpu_stepcounter == cpu_sequence_NTSC[cpu_step])
if (cpu_stepcounter == cpu_sequence[cpu_step])
{
cpu_step++;
cpu_step &= 31;

View File

@ -99,7 +99,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
Cart.vram_size = 8;
Cart.wram_size = 32;
Cart.wram_battery = false;
Cart.system = "FDS";
Cart.system = "Famicom";
Cart.board_type = "FAMICOM_DISK_SYSTEM";
diskdrive = new RamAdapter();

View File

@ -13,6 +13,28 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
public partial class PPU
{
// this only handles region differences within the PPU
int preNMIlines;
int postNMIlines;
bool chopdot;
public enum Region { NTSC, PAL, Dendy, RGB };
Region _region;
public Region region { set { _region = value; SyncRegion(); } get { return _region; } }
void SyncRegion()
{
switch (region)
{
case Region.NTSC:
preNMIlines = 1; postNMIlines = 20; chopdot = true; break;
case Region.PAL:
preNMIlines = 1; postNMIlines = 70; chopdot = false; break;
case Region.Dendy:
preNMIlines = 51; postNMIlines = 20; chopdot = false; break;
case Region.RGB:
preNMIlines = 1; postNMIlines = 20; chopdot = false; break;
}
}
public class DebugCallback
{
public int Scanline;
@ -169,7 +191,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
}
//hack
public bool PAL = false;
//public bool PAL = false;
//bool SPRITELIMIT = true;
}

View File

@ -132,10 +132,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
bool nmi_destiny = reg_2000.vblank_nmi_gen && Reg2002_vblank_active;
runppu(3);
if (nmi_destiny) TriggerNMI();
if (PAL)
runppu(70 * (kLineTime) - delay);
else
runppu(20 * (kLineTime) - delay);
runppu(postNMIlines * kLineTime - delay);
//this seems to run just before the dummy scanline begins
clear_2002();
@ -441,7 +438,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//equivelant of half a memory access cycle) before repeating the whole
//pixel/scanline rendering process. If the scanline being rendered is the very
//first one on every second frame, then this delay simply doesn't exist.
if (sl == 0 && idleSynch && evenOddDestiny && !PAL)
if (sl == 0 && idleSynch && evenOddDestiny && chopdot)
{ }
else
runppu(1);
@ -449,8 +446,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
ppur.status.sl = 241;
//idle for one line
runppu(kLineTime);
//idle for pre NMI lines
runppu(preNMIlines * kLineTime);
} //FrameAdvance
@ -463,12 +460,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//should write to those regs during that time, it needs
//to wait for vblank
ppur.status.sl = 241;
if (PAL)
runppu(70 * kLineTime);
else
runppu(20 * kLineTime);
runppu(postNMIlines * kLineTime);
ppur.status.sl = 0;
runppu(242 * kLineTime);
runppu(241 * kLineTime);
runppu(preNMIlines * kLineTime);
--ppudead;
}
}