SubNESHawk

also Input register shift fix

# Conflicts:
#	BizHawk.Client.EmuHawk/MainForm.Designer.cs
#	BizHawk.Client.EmuHawk/MainForm.Events.cs
#	BizHawk.Emulation.Cores/Computers/AmstradCPC/AmstradCPC.IEmulator.cs
#	BizHawk.Emulation.Cores/Computers/SinclairSpectrum/ZXSpectrum.IEmulator.cs
#	BizHawk.Emulation.Cores/Consoles/Nintendo/NES/PPU.run.cs
This commit is contained in:
alyosha-tas 2019-01-06 23:05:29 +03:00 committed by feos
parent 4a6a6079b0
commit c19c7cd5c3
56 changed files with 1144 additions and 105 deletions

View File

@ -973,7 +973,14 @@ namespace BizHawk.Client.Common
if (preference == "neshawk")
{
core = CoreInventory.Instance["NES", "NesHawk"];
if (Global.Config.UseSubNESHawk)
{
core = CoreInventory.Instance["NES", "SubNESHawk"];
}
else
{
core = CoreInventory.Instance["NES", "NesHawk"];
}
}
else
{

View File

@ -554,6 +554,7 @@ namespace BizHawk.Client.Common
// as this setting spans multiple cores and doesn't actually affect the behavior of any core,
// it hasn't been absorbed into the new system
public bool GB_AsSGB = false;
public bool UseSubNESHawk = false;
public bool NES_InQuickNES = true;
public bool SNES_InSnes9x = true;
public bool GBA_UsemGBA = true;

View File

@ -199,6 +199,7 @@
this.GBGambatteMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.GBGBHawkMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.GBInSGBMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SubNESHawkMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem16 = new System.Windows.Forms.ToolStripSeparator();
this.allowGameDBCoreOverridesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator();
@ -1845,6 +1846,7 @@
this.SGBCoreSubmenu,
this.GBCoreSubmenu,
this.GBInSGBMenuItem,
this.SubNESHawkMenuItem,
this.toolStripMenuItem16,
this.allowGameDBCoreOverridesToolStripMenuItem,
this.toolStripSeparator8,
@ -1982,6 +1984,13 @@
this.GBInSGBMenuItem.Text = "GB in SGB";
this.GBInSGBMenuItem.Click += new System.EventHandler(this.GbInSgbMenuItem_Click);
//
// SubNESHawkMenuItem
//
this.SubNESHawkMenuItem.Name = "SubNESHawkMenuItem";
this.SubNESHawkMenuItem.Size = new System.Drawing.Size(239, 22);
this.SubNESHawkMenuItem.Text = "SubNESHawk";
this.SubNESHawkMenuItem.Click += new System.EventHandler(this.SubNESHawkMenuItem_Click);
//
// toolStripMenuItem16
//
this.toolStripMenuItem16.Name = "toolStripMenuItem16";
@ -4532,6 +4541,7 @@
private System.Windows.Forms.ToolStripMenuItem MovieSettingsMenuItem;
private System.Windows.Forms.ToolStripMenuItem CoresSubMenu;
private System.Windows.Forms.ToolStripMenuItem GBInSGBMenuItem;
private System.Windows.Forms.ToolStripMenuItem SubNESHawkMenuItem;
private System.Windows.Forms.ToolStripMenuItem batchRunnerToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem DisplayConfigMenuItem;
private System.Windows.Forms.ToolStripMenuItem PCEtileViewerToolStripMenuItem;

View File

@ -1215,6 +1215,7 @@ namespace BizHawk.Client.EmuHawk
private void CoresSubMenu_DropDownOpened(object sender, EventArgs e)
{
GBInSGBMenuItem.Checked = Global.Config.GB_AsSGB;
SubNESHawkMenuItem.Checked = Global.Config.UseSubNESHawk;
allowGameDBCoreOverridesToolStripMenuItem.Checked = Global.Config.CoreForcingViaGameDB;
}
@ -1308,6 +1309,16 @@ namespace BizHawk.Client.EmuHawk
}
}
private void SubNESHawkMenuItem_Click(object sender, EventArgs e)
{
Global.Config.UseSubNESHawk ^= true;
if (!Emulator.IsNull())
{
FlagNeedsReboot();
}
}
private void AllowGameDBCoreOverridesToolStripMenuItem_Click(object sender, EventArgs e)
{
Global.Config.CoreForcingViaGameDB ^= true;

View File

@ -2997,7 +2997,7 @@ namespace BizHawk.Client.EmuHawk
}
bool render = !_throttle.skipNextFrame || (_currAviWriter?.UsesVideo ?? false);
Emulator.FrameAdvance(Global.ControllerOutput, render, renderSound);
bool new_frame = Emulator.FrameAdvance(Global.ControllerOutput, render, renderSound);
Global.MovieSession.HandleMovieAfterFrameLoop();
@ -3036,7 +3036,7 @@ namespace BizHawk.Client.EmuHawk
UpdateToolsAfter(SuppressLua);
}
if (!PauseAvi)
if (!PauseAvi && new_frame)
{
AvFrameAdvance();
}

View File

@ -33,23 +33,23 @@ namespace BizHawk.Emulation.Common
public ControllerDefinition ControllerDefinition => NullController.Instance.Definition;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
if (render == false)
{
return;
return true;
}
if (!_settings.SnowyDisplay)
{
if (_frameBufferClear)
{
return;
return true;
}
_frameBufferClear = true;
Array.Clear(_frameBuffer, 0, 256 * 192);
return;
return true;
}
_frameBufferClear = false;
@ -70,6 +70,8 @@ namespace BizHawk.Emulation.Common
}
Frame++;
return true;
}
public int Frame { get; private set; }

View File

@ -34,7 +34,7 @@ namespace BizHawk.Emulation.Common
/// <param name="render">Whether or not to render video, cores will pass false here in cases such as frame skipping</param>
/// <param name="rendersound">Whether or not to render audio, cores will pass here false here in cases such as fast forwarding where bypassing sound may improve speed</param>
/// </summary>
void FrameAdvance(IController controller, bool render, bool rendersound = true);
bool FrameAdvance(IController controller, bool render, bool rendersound = true);
/// <summary>
/// Gets the current frame count

View File

@ -1201,6 +1201,30 @@
<Compile Include="Consoles\Nintendo\NES\PPU.regs.cs" />
<Compile Include="Consoles\Nintendo\NES\PPU.run.cs" />
<Compile Include="Consoles\Nintendo\NES\Unif.cs" />
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawk.cs" />
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawk.IDebuggable.cs">
<DependentUpon>SubNESHawk.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawk.IEmulator.cs">
<DependentUpon>SubNESHawk.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawk.IInputPollable.cs">
<DependentUpon>SubNESHawk.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawk.IMemoryDomains.cs">
<DependentUpon>SubNESHawk.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawk.ISaveRam.cs">
<DependentUpon>SubNESHawk.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawk.ISettable.cs">
<DependentUpon>SubNESHawk.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawk.IStatable.cs">
<DependentUpon>SubNESHawk.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawkControllerDeck.cs" />
<Compile Include="Consoles\Nintendo\SubNESHawk\SubNESHawkControllers.cs" />
<Compile Include="Consoles\Nintendo\QuickNES\LibQuickNES.cs" />
<Compile Include="Consoles\Nintendo\QuickNES\Nes_NTSC_Colors.cs" />
<Compile Include="Consoles\Nintendo\QuickNES\QuickNES.cs" />

View File

@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Calculators
public ControllerDefinition ControllerDefinition => TI83Controller;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_controller = controller;
_lagged = true;
@ -59,6 +59,8 @@ namespace BizHawk.Emulation.Cores.Calculators
}
_isLag = _lagged;
return true;
}
public int Frame

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
public ControllerDefinition ControllerDefinition { get; set; }
public void FrameAdvance(IController controller, bool render, bool renderSound)
public bool FrameAdvance(IController controller, bool render, bool renderSound)
{
_controller = controller;
@ -42,6 +42,8 @@ namespace BizHawk.Emulation.Cores.Computers.AmstradCPC
{
_lagCount++;
}
return true;
}
public int Frame

View File

@ -14,9 +14,11 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
public bool DeterministicEmulation => true;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
FrameAdv(controller, render, rendersound);
return true;
}
public void ResetCounters()

View File

@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
public ControllerDefinition ControllerDefinition => C64ControllerDefinition;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_board.Controller = controller;
@ -47,6 +47,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
DoCycle();
}
while (_frameCycles != 0);
return true;
}
public int Frame => _frame;

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
public ControllerDefinition ControllerDefinition { get; set; }
public void FrameAdvance(IController controller, bool render, bool renderSound)
public bool FrameAdvance(IController controller, bool render, bool renderSound)
{
_controller = controller;
@ -42,6 +42,8 @@ namespace BizHawk.Emulation.Cores.Computers.SinclairSpectrum
{
_lagCount++;
}
return true;
}
public int Frame

View File

@ -9,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_controller = controller;
@ -75,6 +75,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
_tia.LineCount = 0;
return true;
}
public int Frame => _frame;

View File

@ -57,7 +57,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
public bool slow_access = false;
public int slow_countdown;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
if (_tracer.Enabled)
{
@ -88,6 +88,8 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
{
_lagcount++;
}
return true;
}
public void RunCPUCycle()

View File

@ -120,7 +120,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
public IEmulatorServiceProvider ServiceProvider { get; }
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
Frame++;
if (controller.IsPressed("Power"))
@ -135,6 +135,8 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
{
LagCount++;
}
return true;
}
public int Frame { get; private set; }

View File

@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision
public ControllerDefinition ControllerDefinition => ControllerDeck.Definition;
public void FrameAdvance(IController controller, bool render, bool renderSound)
public bool FrameAdvance(IController controller, bool render, bool renderSound)
{
_controller = controller;
@ -163,6 +163,8 @@ namespace BizHawk.Emulation.Cores.ColecoVision
{
_lagCount++;
}
return true;
}
public bool use_SGM = false;

View File

@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Intellivision
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
if (_tracer.Enabled)
{
@ -124,6 +124,8 @@ namespace BizHawk.Emulation.Cores.Intellivision
{
SoftReset();
}
return true;
}
public int Frame => _frame;

View File

@ -67,7 +67,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
public ControllerDefinition ControllerDefinition => GBA.GBAController;
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
Frame++;
if (controller.IsPressed("Power"))
@ -97,6 +97,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
// this should be called in hblank on the appropriate line, but until we implement that, just do it here
_scanlinecb?.Invoke();
return true;
}
public int Frame { get; private set; }

View File

@ -95,7 +95,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
public IEmulatorServiceProvider ServiceProvider { get; private set; }
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
Frame++;
@ -108,6 +108,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
if (IsLagFrame)
LagCount++;
return true;
}
public int Frame { get; private set; }

View File

@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
public bool in_vblank;
public bool vblank_rise;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
//Console.WriteLine("-----------------------FRAME-----------------------");
@ -74,6 +74,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
_lagcount++;
}
return true;
}
public void do_frame()

View File

@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
//Console.WriteLine("-----------------------FRAME-----------------------");
//Update the color palette if a setting changed
@ -86,6 +86,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawkLink
{
_lagcount++;
}
return true;
}
public void do_frame()

View File

@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
public ControllerDefinition ControllerDefinition => GbController;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
FrameAdvancePrep(controller);
if (_syncSettings.EqualLengthFrames)
@ -68,6 +68,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
}
FrameAdvancePost();
return true;
}
public int Frame { get; private set; }

View File

@ -344,7 +344,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
LibGambatte.gambatte_setlayers(GambatteState, (_settings.DisplayBG ? 1 : 0) | (_settings.DisplayOBJ ? 2 : 0) | (_settings.DisplayWindow ? 4 : 0));
}
internal void FrameAdvancePost()
internal bool FrameAdvancePost()
{
if (IsLagFrame)
{
@ -352,6 +352,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
}
endofframecallback?.Invoke(LibGambatte.gambatte_cpuread(GambatteState, 0xff40));
return true;
}

View File

@ -9,7 +9,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
public ControllerDefinition ControllerDefinition => DualGbController;
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
LCont.Clear();
RCont.Clear();
@ -148,6 +148,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
{
LagCount++;
}
return true;
}
public int Frame { get; private set; }

View File

@ -221,7 +221,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
RunThreadAction(() => { _pendingThreadTerminate = true; });
}
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_inputProvider.Controller = controller;
@ -258,6 +258,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
if(!api.IsCrashed)
Frame++;
return true;
}
public string SystemId { get { return "N64"; } }

View File

@ -244,7 +244,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
int bank_1k = addr >> 10;
int ofs = addr & ((1 << 10) - 1);
if (exram_mode == 1 && NES.ppu.ppuphase == PPU.PPUPHASE.BG)
if (exram_mode == 1 && NES.ppu.ppuphase == PPU.PPU_PHASE_BG)
{
int exram_addr = last_nt_read;
int bank_4k = EXRAM[exram_addr] & 0x3F;
@ -261,9 +261,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (NES.ppu.reg_2000.obj_size_16)
{
bool isPattern = NES.ppu.PPUON;
if (NES.ppu.ppuphase == PPU.PPUPHASE.OBJ && isPattern)
if (NES.ppu.ppuphase == PPU.PPU_PHASE_OBJ && isPattern)
bank_1k = a_banks_1k[bank_1k];
else if (NES.ppu.ppuphase == PPU.PPUPHASE.BG && isPattern)
else if (NES.ppu.ppuphase == PPU.PPU_PHASE_BG && isPattern)
bank_1k = b_banks_1k[bank_1k];
else
{

View File

@ -80,7 +80,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
case 0xF003:
IRQa = value.Bit(1);
IRQSignal = false;
if (NES.ppu.ppuphase !=PPU.PPUPHASE.VBL)
if (NES.ppu.ppuphase !=PPU.PPU_PHASE_VBL)
IRQCount -= 8;
break;
}
@ -88,7 +88,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public override void ClockPPU()
{
if ((NES.ppu.ppuphase != PPU.PPUPHASE.VBL))// && IRQa)
if ((NES.ppu.ppuphase != PPU.PPU_PHASE_VBL))// && IRQa)
{
IRQpre--;
if (IRQpre==0)

View File

@ -79,7 +79,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
magicSoundProvider = null;
}
class MagicSoundProvider : ISoundProvider, IDisposable
public class MagicSoundProvider : ISoundProvider, IDisposable
{
BlipBuffer blip;
NES nes;
@ -157,7 +157,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
}
}
}
MagicSoundProvider magicSoundProvider;
public MagicSoundProvider magicSoundProvider;
public void HardReset()
{
@ -311,7 +311,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
bool resetSignal;
bool hardResetSignal;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_controller = controller;
@ -377,12 +377,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
}
else
{
ppu.ppu_init_frame();
ppu.do_vbl = true;
ppu.do_active_sl = true;
ppu.do_pre_vbl = true;
// do the vbl ticks seperate, that will save us a few checks that don't happen in active region
while (ppu.do_vbl)
{
@ -415,6 +409,50 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
// turn off all cheats
// any cheats still active will be re-applied by the buspoke at the start of the next frame
num_cheats = 0;
return true;
}
// these variables are for subframe input control
public bool controller_was_latched;
public bool frame_is_done;
public bool current_strobe;
public bool new_strobe;
public bool alt_lag;
public byte ctrl_1 = 0;
public byte ctrl_2 = 0;
public byte ctrl_1_new = 0;
public byte ctrl_2_new = 0;
public int shift_1;
public int shift_2;
public bool use_sub_input = false;
// this function will run one step of the ppu
// it will return whether the controller is read or not.
public void do_single_step(out bool cont_read, out bool frame_done)
{
controller_was_latched = false;
frame_is_done = false;
current_strobe = new_strobe;
if (ppu.ppudead > 0)
{
ppu.NewDeadPPU();
}
else if (ppu.do_vbl)
{
ppu.TickPPU_VBL();
}
else if (ppu.do_active_sl)
{
ppu.TickPPU_active();
}
else if (ppu.do_pre_vbl)
{
ppu.TickPPU_preVBL();
}
cont_read = controller_was_latched;
frame_done = frame_is_done;
}
//PAL:
@ -736,6 +774,27 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
var si = new StrobeInfo(latched4016, value);
ControllerDeck.Strobe(si, _controller);
latched4016 = value;
new_strobe = (value & 1) > 0;
if (current_strobe && !new_strobe)
{
controller_was_latched = true;
alt_lag = false;
if (use_sub_input)
{
shift_1 = 7;
shift_2 = 7;
ctrl_1 = ctrl_1_new;
ctrl_2 = ctrl_2_new;
}
}
if (use_sub_input && new_strobe)
{
shift_1 = 7;
shift_2 = 7;
}
}
byte read_joyport(int addr)
@ -743,14 +802,35 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
InputCallbacks.Call();
lagged = false;
byte ret = 0;
if (_isVS)
if (use_sub_input)
{
// for whatever reason, in VS left and right controller have swapped regs
ret = addr == 0x4017 ? ControllerDeck.ReadA(_controller) : ControllerDeck.ReadB(_controller);
if (addr == 0x4016)
{
if (shift_1 >= 0) { ret = (byte)((ctrl_1 >> shift_1) & 1); }
else { ret = 1; }
if (!current_strobe) { shift_1 -= 1; }
}
else
{
if (shift_2 >= 0) { ret = (byte)((ctrl_2 >> shift_2) & 1); }
else { ret = 1; }
if (!current_strobe) { shift_2 -= 1; }
}
}
else
{
ret = addr == 0x4016 ? ControllerDeck.ReadA(_controller) : ControllerDeck.ReadB(_controller);
if (_isVS)
{
// for whatever reason, in VS left and right controller have swapped regs
ret = addr == 0x4017 ? ControllerDeck.ReadA(_controller) : ControllerDeck.ReadB(_controller);
}
else
{
ret = addr == 0x4016 ? ControllerDeck.ReadA(_controller) : ControllerDeck.ReadB(_controller);
}
}
ret &= 0x1f;
@ -810,7 +890,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public byte DummyReadMemory(ushort addr) { return 0; }
private void ApplySystemBusPoke(int addr, byte value)
public void ApplySystemBusPoke(int addr, byte value)
{
if (addr < 0x2000)
{

View File

@ -82,7 +82,16 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ser.Sync("VS_Coin", ref VS_coin_inserted);
ser.Sync("VS_ROM_Control", ref VS_ROM_control);
ser.BeginSection("Board");
// single cycle execution related
ser.Sync("current_strobe", ref current_strobe);
ser.Sync("new_strobe", ref new_strobe);
ser.Sync("ctrl_1", ref ctrl_1);
ser.Sync("ctrl_2", ref ctrl_2);
ser.Sync("shift_1", ref shift_1);
ser.Sync("shift_2", ref shift_2);
ser.Sync("use_sub_input", ref use_sub_input);
ser.BeginSection("Board");
Board.SyncState(ser);
if (Board is NESBoardBase && !((NESBoardBase)Board).SyncStateFlag)
throw new InvalidOperationException("the current NES mapper didnt call base.SyncState");

View File

@ -126,7 +126,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public DisplayType Region { get { return _display_type; } }
class MyVideoProvider : IVideoProvider
public class MyVideoProvider : IVideoProvider
{
//public int ntsc_top = 8;
//public int ntsc_bottom = 231;
@ -246,7 +246,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public int VsyncDenominator => emu.VsyncDen;
}
MyVideoProvider videoProvider;
public MyVideoProvider videoProvider;
[Obsolete] // with the changes to both nes and quicknes cores, nothing uses this anymore
public static readonly ControllerDefinition NESController =

View File

@ -158,11 +158,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
return nes.Board.PeekPPU(addr);
}
public enum PPUPHASE
{
VBL, BG, OBJ
};
public PPUPHASE ppuphase;
public static int PPU_PHASE_VBL = 0;
public static int PPU_PHASE_BG = 1;
public static int PPU_PHASE_OBJ = 2;
public int ppuphase;
private readonly NES nes;
public PPU(NES nes)
@ -247,6 +247,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ser.Sync("OAM", ref OAM, false);
ser.Sync("soam", ref soam, false);
ser.Sync("PALRAM", ref PALRAM, false);
ser.Sync("ppuphase", ref ppuphase);
ser.Sync("Reg2002_objoverflow", ref Reg2002_objoverflow);
ser.Sync("Reg2002_objhit", ref Reg2002_objhit);

View File

@ -551,7 +551,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//does this take 4x longer? nestopia indicates so perhaps...
int addr = ppur.get_2007access();
if (ppuphase == PPUPHASE.BG)
if (ppuphase == PPU_PHASE_BG)
{
if (show_bg_new)
{

View File

@ -151,7 +151,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
// These things happen at the start of every frame
//Reg2002_vblank_active = true;
//Reg2002_vblank_active_pending = true;
ppuphase = PPUPHASE.VBL;
ppuphase = PPU_PHASE_VBL;
bgdata = new BGDataRecord[34];
}
@ -194,6 +194,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{
do_vbl = false;
ppur.status.sl = 0;
do_active_sl = true;
}
}
}
@ -216,7 +217,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
sprite_zero_in_range = false;
yp = ppur.status.sl - 1;
ppuphase = PPUPHASE.BG;
ppuphase = PPU_PHASE_BG;
// "If PPUADDR is not less then 8 when rendering starts, the first 8 bytes in OAM are written to from
// the current location of PPUADDR"
@ -615,7 +616,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (soam_index_prev > 8 && !nes.Settings.AllowMoreThanEightSprites)
soam_index_prev = 8;
ppuphase = PPUPHASE.OBJ;
ppuphase = PPU_PHASE_OBJ;
spriteHeight = reg_2000.obj_size_16 ? 16 : 8;
@ -926,7 +927,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{
if (ppur.status.cycle == 320)
{
ppuphase = PPUPHASE.BG;
ppuphase = PPU_PHASE_BG;
xt = 0;
xp = 0;
}
@ -992,6 +993,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (ppur.status.sl == 241)
{
do_active_sl = false;
do_pre_vbl = true;
}
}
}
@ -1012,6 +1014,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (ppur.status.sl == 241 + preNMIlines)
{
do_pre_vbl = false;
do_vbl = true;
ppu_init_frame();
nes.frame_is_done = true;
}
}
}
@ -1033,6 +1039,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (ppur.status.cycle == 241 * 341 - start_up_offset)
{
ppudead--;
ppu_init_frame();
do_vbl = true;
nes.frame_is_done = true;
}
}
}

View File

@ -179,7 +179,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
#endregion
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
CheckDisposed();
using (FP.Save())
@ -211,6 +211,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
if (CB1 != null) CB1();
if (CB2 != null) CB2();
}
return true;
}
IntPtr Context;

View File

@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_controller = controller;
@ -80,6 +80,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
{
LagCount++;
}
return true;
}
public int Frame

View File

@ -0,0 +1 @@
TODO:

View File

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk : IDebuggable
{
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
{
return new Dictionary<string, RegisterValue>
{
/*
["A"] = cpu.A,
["X"] = cpu.X,
["Y"] = cpu.Y,
["S"] = cpu.S,
["PC"] = cpu.PC,
["Flag C"] = cpu.FlagC,
["Flag Z"] = cpu.FlagZ,
["Flag I"] = cpu.FlagI,
["Flag D"] = cpu.FlagD,
["Flag B"] = cpu.FlagB,
["Flag V"] = cpu.FlagV,
["Flag N"] = cpu.FlagN,
["Flag T"] = cpu.FlagT
*/
};
}
public void SetCpuRegister(string register, int value)
{
switch (register)
{
default:
throw new InvalidOperationException();
case "A":
//cpu.A = (byte)value;
break;
case "X":
//cpu.X = (byte)value;
break;
case "Y":
//cpu.Y = (byte)value;
break;
case "S":
//cpu.S = (byte)value;
break;
case "PC":
//cpu.PC = (ushort)value;
break;
case "Flag I":
//cpu.FlagI = value > 0;
break;
}
}
public bool CanStep(StepType type)
{
return false;
}
public IMemoryCallbackSystem MemoryCallbacks { get; private set; }
[FeatureNotImplemented]
public void Step(StepType type) { throw new NotImplementedException(); }
public long TotalExecutedCycles
{
get { return subnes.cpu.TotalExecutedCycles; }
}
}
}

View File

@ -0,0 +1,215 @@
using System;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Nintendo.NES;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk : IEmulator
{
public IEmulatorServiceProvider ServiceProvider { get; }
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
//Console.WriteLine("-----------------------FRAME-----------------------");
if (_tracer.Enabled)
{
subnes.cpu.TraceCallback = s => _tracer.Put(s);
}
else
{
subnes.cpu.TraceCallback = null;
}
_frame++;
if (controller.IsPressed("Power"))
{
HardReset();
}
if (controller.IsPressed("Reset"))
{
SoftReset();
}
_islag = true;
subnes.alt_lag = true;
GetControllerState(controller);
do_frame();
bool ret = pass_a_frame;
if (pass_a_frame)
{
subnes.videoProvider.FillFrameBuffer();
}
_islag = subnes.alt_lag;
if (_islag)
{
_lagcount++;
}
return ret;
}
public bool stop_cur_frame;
public bool pass_new_input;
public bool pass_a_frame;
public byte ctrl_byte_1;
public byte ctrl_byte_2;
public void do_frame()
{
stop_cur_frame = false;
while (!stop_cur_frame)
{
subnes.do_single_step(out pass_new_input, out pass_a_frame);
stop_cur_frame |= pass_a_frame;
stop_cur_frame |= pass_new_input;
}
}
public void GetControllerState(IController controller)
{
InputCallbacks.Call();
ctrl_byte_1 = _controllerDeck.ReadPort1(controller);
ctrl_byte_2 = _controllerDeck.ReadPort2(controller);
subnes.ctrl_1_new = ctrl_byte_1;
subnes.ctrl_2_new = ctrl_byte_2;
}
public int Frame => _frame;
public string SystemId => "NES";
public bool DeterministicEmulation { get; set; }
public void ResetCounters()
{
_frame = 0;
_lagcount = 0;
_islag = false;
}
public CoreComm CoreComm { get; }
public void Dispose()
{
subnes.Dispose();
}
/*
#region Video provider
public int _frameHz = 60;
public int[] _vidbuffer = new int[160 * 2 * 144];
public int[] buff_L = new int[160 * 144];
public int[] buff_R = new int[160 * 144];
public int[] GetVideoBuffer()
{
// combine the 2 video buffers from the instances
for (int i = 0; i < 144; i++)
{
for (int j = 0; j < 160; j++)
{
_vidbuffer[i * 320 + j] = buff_L[i * 160 + j];
_vidbuffer[i * 320 + j + 160] = buff_R[i * 160 + j];
}
}
return _vidbuffer;
}
public int VirtualWidth => 160 * 2;
public int VirtualHeight => 144;
public int BufferWidth => 160 * 2;
public int BufferHeight => 144;
public int BackgroundColor => unchecked((int)0xFF000000);
public int VsyncNumerator => _frameHz;
public int VsyncDenominator => 1;
public static readonly uint[] color_palette_BW = { 0xFFFFFFFF , 0xFFAAAAAA, 0xFF555555, 0xFF000000 };
public static readonly uint[] color_palette_Gr = { 0xFFA4C505, 0xFF88A905, 0xFF1D551D, 0xFF052505 };
public uint[] color_palette = new uint[4];
#endregion
#region audio
public bool CanProvideAsync => false;
public void SetSyncMode(SyncSoundMode mode)
{
if (mode != SyncSoundMode.Sync)
{
throw new InvalidOperationException("Only Sync mode is supported_");
}
}
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
public void GetSamplesSync(out short[] samples, out int nsamp)
{
short[] temp_samp_L;
short[] temp_samp_R;
int nsamp_L;
int nsamp_R;
L.audio.GetSamplesSync(out temp_samp_L, out nsamp_L);
R.audio.GetSamplesSync(out temp_samp_R, out nsamp_R);
if (linkSettings.AudioSet == GBLinkSettings.AudioSrc.Left)
{
samples = temp_samp_L;
nsamp = nsamp_L;
}
else if (linkSettings.AudioSet == GBLinkSettings.AudioSrc.Right)
{
samples = temp_samp_R;
nsamp = nsamp_R;
}
else
{
samples = new short[0];
nsamp = 0;
}
}
public void GetSamplesAsync(short[] samples)
{
throw new NotSupportedException("Async is not available");
}
public void DiscardSamples()
{
L.audio.DiscardSamples();
R.audio.DiscardSamples();
}
private void GetSamples(short[] samples)
{
}
public void DisposeSound()
{
L.audio.DisposeSound();
R.audio.DisposeSound();
}
#endregion
*/
}
}

View File

@ -0,0 +1,24 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk : IInputPollable
{
public int LagCount
{
get { return _lagcount; }
set { _lagcount = value; }
}
public bool IsLagFrame
{
get { return _islag; }
set { _islag = value; }
}
public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem();
public bool _islag = true;
private int _lagcount;
}
}

View File

@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk
{
private MemoryDomainList _memoryDomains;
private bool _memoryDomainsSetup = false;
private void SetupMemoryDomains()
{
var domains = new List<MemoryDomain>();
var RAM = new MemoryDomainByteArray("RAM", MemoryDomain.Endian.Little, subnes.ram, true, 1);
var SystemBus = new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little,
addr => subnes.PeekMemory((ushort)addr), (addr, value) => subnes.ApplySystemBusPoke((int)addr, value), 1);
var PPUBus = new MemoryDomainDelegate("PPU Bus", 0x4000, MemoryDomain.Endian.Little,
addr => subnes.ppu.ppubus_peek((int)addr), (addr, value) => subnes.ppu.ppubus_write((int)addr, value), 1);
var CIRAMdomain = new MemoryDomainByteArray("CIRAM (nametables)", MemoryDomain.Endian.Little, subnes.CIRAM, true, 1);
var OAMdoman = new MemoryDomainByteArray("OAM", MemoryDomain.Endian.Unknown, subnes.ppu.OAM, true, 1);
domains.Add(RAM);
domains.Add(SystemBus);
domains.Add(PPUBus);
domains.Add(CIRAMdomain);
domains.Add(OAMdoman);
if (!(subnes.Board is NES.FDS) && subnes.Board.SaveRam != null)
{
var BatteryRam = new MemoryDomainByteArray("Battery RAM", MemoryDomain.Endian.Little, subnes.Board.SaveRam, true, 1);
domains.Add(BatteryRam);
}
if (subnes.Board.ROM != null)
{
var PRGROM = new MemoryDomainByteArray("PRG ROM", MemoryDomain.Endian.Little, subnes.Board.ROM, true, 1);
domains.Add(PRGROM);
}
if (subnes.Board.VROM != null)
{
var CHRROM = new MemoryDomainByteArray("CHR VROM", MemoryDomain.Endian.Little, subnes.Board.VROM, true, 1);
domains.Add(CHRROM);
}
if (subnes.Board.VRAM != null)
{
var VRAM = new MemoryDomainByteArray("VRAM", MemoryDomain.Endian.Little, subnes.Board.VRAM, true, 1);
domains.Add(VRAM);
}
if (subnes.Board.WRAM != null)
{
var WRAM = new MemoryDomainByteArray("WRAM", MemoryDomain.Endian.Little, subnes.Board.WRAM, true, 1);
domains.Add(WRAM);
}
// if there were more boards with special ram sets, we'd want to do something more general
if (subnes.Board is NES.FDS)
{
domains.Add((subnes.Board as NES.FDS).GetDiskPeeker());
}
else if (subnes.Board is NES.ExROM)
{
domains.Add((subnes.Board as NES.ExROM).GetExRAM());
}
if (!_memoryDomainsSetup)
{
_memoryDomains = new MemoryDomainList(domains);
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(_memoryDomains);
_memoryDomainsSetup = true;
}
else
{
var src = new MemoryDomainList(domains);
_memoryDomains.MergeList(src);
}
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk : ISaveRam
{
public bool SaveRamModified
{
get
{
if (subnes.Board == null) return false;
if (subnes.Board is NES.FDS) return true;
if (subnes.Board.SaveRam == null) return false;
return true;
}
}
public byte[] CloneSaveRam()
{
if (subnes.Board is NES.FDS)
return (subnes.Board as NES.FDS).ReadSaveRam();
if (subnes.Board == null || subnes.Board.SaveRam == null)
return null;
return (byte[])subnes.Board.SaveRam.Clone();
}
public void StoreSaveRam(byte[] data)
{
if (subnes.Board is NES.FDS)
{
(subnes.Board as NES.FDS).StoreSaveRam(data);
return;
}
if (subnes.Board == null || subnes.Board.SaveRam == null)
return;
Array.Copy(data, subnes.Board.SaveRam, data.Length);
}
}
}

View File

@ -0,0 +1,58 @@
using System;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Nintendo.NES;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk : IEmulator, IStatable, ISettable<SubNESHawk.SubNESHawkSettings, SubNESHawk.SubNESHawkSyncSettings>
{
public SubNESHawkSettings GetSettings()
{
return subnesSettings.Clone();
}
public SubNESHawkSyncSettings GetSyncSettings()
{
return subnesSyncSettings.Clone();
}
public bool PutSettings(SubNESHawkSettings o)
{
subnesSettings = o;
return false;
}
public bool PutSyncSettings(SubNESHawkSyncSettings o)
{
bool ret = SubNESHawkSyncSettings.NeedsReboot(subnesSyncSettings, o);
subnesSyncSettings = o;
return ret;
}
private SubNESHawkSettings subnesSettings = new SubNESHawkSettings();
public SubNESHawkSyncSettings subnesSyncSettings = new SubNESHawkSyncSettings();
public class SubNESHawkSettings
{
public SubNESHawkSettings Clone()
{
return (SubNESHawkSettings)MemberwiseClone();
}
}
public class SubNESHawkSyncSettings
{
public SubNESHawkSyncSettings Clone()
{
return (SubNESHawkSyncSettings)MemberwiseClone();
}
public static bool NeedsReboot(SubNESHawkSyncSettings x, SubNESHawkSyncSettings y)
{
return !DeepEquality.DeepEquals(x, y);
}
}
}
}

View File

@ -0,0 +1,63 @@
using System.IO;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Nintendo.NES;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public partial class SubNESHawk : IStatable
{
public bool BinarySaveStatesPreferred => true;
public void SaveStateText(TextWriter writer)
{
subnes.SaveStateText(writer);
SyncState(new Serializer(writer));
}
public void LoadStateText(TextReader reader)
{
subnes.LoadStateText(reader);
SyncState(new Serializer(reader));
}
public void SaveStateBinary(BinaryWriter bw)
{
subnes.SaveStateBinary(bw);
// other variables
SyncState(new Serializer(bw));
}
public void LoadStateBinary(BinaryReader br)
{
subnes.LoadStateBinary(br);
// other variables
SyncState(new Serializer(br));
}
public byte[] SaveStateBinary()
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
return ms.ToArray();
}
//private JsonSerializer ser = new JsonSerializer { Formatting = Formatting.Indented };
private void SyncState(Serializer ser)
{
ser.Sync("Lag", ref _lagcount);
ser.Sync("Frame", ref _frame);
ser.Sync("IsLag", ref _islag);
ser.Sync("pass_a_frame", ref pass_a_frame);
ser.Sync("pass_new_input", ref pass_new_input);
ser.Sync("ctrl_byte_1", ref ctrl_byte_1);
ser.Sync("ctrl_byte_2", ref ctrl_byte_2);
_controllerDeck.SyncState(ser);
}
}
}

View File

@ -0,0 +1,80 @@
using System;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Nintendo.NES;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
[Core(
"SubNESHawk",
"",
isPorted: false,
isReleased: false)]
[ServiceNotApplicable(typeof(IDriveLight))]
public partial class SubNESHawk : IEmulator, ISaveRam, IDebuggable, IStatable, IInputPollable, IRegionable,
ISettable<SubNESHawk.SubNESHawkSettings, SubNESHawk.SubNESHawkSyncSettings>
{
public NES.NES subnes;
[CoreConstructor("NES")]
public SubNESHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings)
{
var ser = new BasicServiceProvider(this);
subnesSettings = (SubNESHawkSettings)settings ?? new SubNESHawkSettings();
subnesSyncSettings = (SubNESHawkSyncSettings)syncSettings ?? new SubNESHawkSyncSettings();
_controllerDeck = new SubNESHawkControllerDeck(SubNESHawkControllerDeck.DefaultControllerName, SubNESHawkControllerDeck.DefaultControllerName);
CoreComm = comm;
var temp_set = new NES.NES.NESSettings();
var temp_sync = new NES.NES.NESSyncSettings();
subnes = new NES.NES(new CoreComm(comm.ShowMessage, comm.Notify) { CoreFileProvider = comm.CoreFileProvider },
game, rom, temp_set, temp_sync);
ser.Register<IVideoProvider>(subnes.videoProvider);
ser.Register<ISoundProvider>(subnes.magicSoundProvider);
_tracer = new TraceBuffer { Header = subnes.cpu.TraceHeader };
ser.Register<ITraceable>(_tracer);
ServiceProvider = ser;
SetupMemoryDomains();
HardReset();
// input override for subframe input
subnes.use_sub_input = true;
}
public void HardReset()
{
subnes.HardReset();
}
public void SoftReset()
{
subnes.Board.NESSoftReset();
subnes.cpu.NESSoftReset();
subnes.apu.NESSoftReset();
subnes.ppu.NESSoftReset();
}
public DisplayType Region => DisplayType.NTSC;
public int _frame = 0;
private readonly SubNESHawkControllerDeck _controllerDeck;
private readonly ITraceable _tracer;
private void ExecFetch(ushort addr)
{
MemoryCallbacks.CallExecutes(addr, "System Bus");
}
}
}

View File

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Common;
using BizHawk.Common.ReflectionExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
public class SubNESHawkControllerDeck
{
public SubNESHawkControllerDeck(string controller1Name, string controller2Name)
{
if (!ValidControllerTypes.ContainsKey(controller1Name))
{
throw new InvalidOperationException("Invalid controller type: " + controller1Name);
}
if (!ValidControllerTypes.ContainsKey(controller2Name))
{
throw new InvalidOperationException("Invalid controller type: " + controller2Name);
}
Port1 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller1Name], 1);
Port2 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller2Name], 2);
Definition = new ControllerDefinition
{
Name = Port1.Definition.Name,
BoolButtons = Port1.Definition.BoolButtons
.Concat(Port2.Definition.BoolButtons)
.Concat(new[]
{
"Power",
"Reset",
})
.ToList()
};
}
public byte ReadPort1(IController c)
{
return Port1.Read(c);
}
public byte ReadPort2(IController c)
{
return Port2.Read(c);
}
public ControllerDefinition Definition { get; }
public void SyncState(Serializer ser)
{
ser.BeginSection("Port1");
Port1.SyncState(ser);
ser.EndSection();
ser.BeginSection("Port2");
Port2.SyncState(ser);
ser.EndSection();
}
private readonly IPort Port1;
private readonly IPort Port2;
private static Dictionary<string, Type> _controllerTypes;
public static Dictionary<string, Type> ValidControllerTypes
{
get
{
if (_controllerTypes == null)
{
_controllerTypes = typeof(SubNESHawkControllerDeck).Assembly
.GetTypes()
.Where(t => typeof(IPort).IsAssignableFrom(t))
.Where(t => !t.IsAbstract && !t.IsInterface)
.ToDictionary(tkey => tkey.DisplayName());
}
return _controllerTypes;
}
}
public static string DefaultControllerName => typeof(StandardControls).DisplayName();
}
}

View File

@ -0,0 +1,94 @@
using System;
using System.ComponentModel;
using System.Linq;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.SubNESHawk
{
/// <summary>
/// Represents a Standard Nintendo Controller
/// </summary>
public interface IPort
{
byte Read(IController c);
ControllerDefinition Definition { get; }
void SyncState(Serializer ser);
int PortNum { get; }
}
[DisplayName("NES Controller")]
public class StandardControls : IPort
{
public StandardControls(int portNum)
{
PortNum = portNum;
Definition = new ControllerDefinition
{
Name = "NES Controller",
BoolButtons = BaseDefinition
.Select(b => "P" + PortNum + " " + b)
.ToList()
};
}
public int PortNum { get; }
public ControllerDefinition Definition { get; }
public byte Read(IController c)
{
byte result = 0;
if (c.IsPressed(Definition.BoolButtons[0]))
{
result |= 8;
}
if (c.IsPressed(Definition.BoolButtons[1]))
{
result |= 4;
}
if (c.IsPressed(Definition.BoolButtons[2]))
{
result |= 2;
}
if (c.IsPressed(Definition.BoolButtons[3]))
{
result |= 1;
}
if (c.IsPressed(Definition.BoolButtons[4]))
{
result |= 16;
}
if (c.IsPressed(Definition.BoolButtons[5]))
{
result |= 32;
}
if (c.IsPressed(Definition.BoolButtons[6]))
{
result |= 64;
}
if (c.IsPressed(Definition.BoolButtons[7]))
{
result |= 128;
}
return result;
}
private static readonly string[] BaseDefinition =
{
"Up", "Down", "Left", "Right", "Start", "Select", "B", "A"
};
public void SyncState(Serializer ser)
{
//nothing
}
}
}

View File

@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_controller = controller;
_lagged = true;
@ -39,6 +39,8 @@ namespace BizHawk.Emulation.Cores.PCEngine
{
_isLag = false;
}
return true;
}
public int Frame

View File

@ -47,7 +47,7 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK
_serviceProvider.Register<IVideoProvider>(_videoProvider);
}
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
var t1 = Task.Run(() =>
{
@ -67,6 +67,8 @@ namespace BizHawk.Emulation.Cores.Consoles.SNK
Frame++;
_soundProvider.Fetch();
_videoProvider.Fetch();
return true;
}
#region link cable

View File

@ -37,7 +37,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
}
}
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_controller = controller;
_lagged = true;
@ -86,6 +86,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
{
_isLag = false;
}
return true;
}
public int Frame => _frame;

View File

@ -7,45 +7,45 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public IEmulatorServiceProvider ServiceProvider { get; private set; }
public ControllerDefinition ControllerDefinition { get; private set; }
// TODO: use render and rendersound
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
public ControllerDefinition ControllerDefinition { get; private set; }
// TODO: use render and rendersound
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
if (controller.IsPressed("Reset"))
Core.gpgx_reset(false);
if (controller.IsPressed("Power"))
Core.gpgx_reset(true);
if (_cds != null)
{
var prev = controller.IsPressed("Previous Disk");
var next = controller.IsPressed("Next Disk");
int newDisk = _discIndex;
if (prev && !_prevDiskPressed)
newDisk--;
if (next && !_nextDiskPressed)
newDisk++;
_prevDiskPressed = prev;
_nextDiskPressed = next;
if (newDisk < -1)
newDisk = -1;
if (newDisk >= _cds.Length)
newDisk = _cds.Length - 1;
if (newDisk != _discIndex)
{
_discIndex = newDisk;
Core.gpgx_swap_disc(_discIndex == -1 ? null : GetCDDataStruct(_cds[_discIndex]));
Console.WriteLine("IMMA CHANGING MAH DISKS");
}
}
// this shouldn't be needed, as nothing has changed
// if (!Core.gpgx_get_control(input, inputsize))
// throw new Exception("gpgx_get_control() failed!");
Core.gpgx_reset(true);
if (_cds != null)
{
var prev = controller.IsPressed("Previous Disk");
var next = controller.IsPressed("Next Disk");
int newDisk = _discIndex;
if (prev && !_prevDiskPressed)
newDisk--;
if (next && !_nextDiskPressed)
newDisk++;
_prevDiskPressed = prev;
_nextDiskPressed = next;
if (newDisk < -1)
newDisk = -1;
if (newDisk >= _cds.Length)
newDisk = _cds.Length - 1;
if (newDisk != _discIndex)
{
_discIndex = newDisk;
Core.gpgx_swap_disc(_discIndex == -1 ? null : GetCDDataStruct(_cds[_discIndex]));
Console.WriteLine("IMMA CHANGING MAH DISKS");
}
}
// this shouldn't be needed, as nothing has changed
// if (!Core.gpgx_get_control(input, inputsize))
// throw new Exception("gpgx_get_control() failed!");
ControlConverter.ScreenWidth = vwidth;
ControlConverter.ScreenHeight = vheight;
ControlConverter.Convert(controller, input);
@ -66,6 +66,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
if (_cds != null)
DriveLightOn = _drivelight;
return true;
}
public int Frame { get; private set; }
@ -96,7 +98,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
if (_elf != null)
_elf.Dispose();
if (_cds != null)
foreach (var cd in _cds)
foreach (var cd in _cds)
cd.Dispose();
_disposed = true;
}

View File

@ -131,7 +131,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSP
}
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
Frame++;
UpdateInput(controller);
@ -147,6 +147,8 @@ namespace BizHawk.Emulation.Cores.Sony.PSP
//nsampavail = PPSSPPDll.mixsound(audiobuffer, audiobuffer.Length / 2);
LogFlush();
//Console.WriteLine("Audio Service: {0}", nsampavail);
return true;
}
public int Frame

View File

@ -743,7 +743,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
private IController _controller;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_controller = controller;
FrameAdvance_PrepDiscState();
@ -801,7 +801,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
LagCount++;
//what happens to sound in this case?
if (render == false) return;
if (render == false) return true;
OctoshockDll.ShockFramebufferInfo fb = new OctoshockDll.ShockFramebufferInfo();
@ -843,6 +843,8 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
if (sbuffcontains * 2 > sbuff.Length) throw new InvalidOperationException("shock_GetSamples returned too many samples: " + sbuffcontains);
OctoshockDll.shock_GetSamples(psx, samples);
}
return true;
}
public ControllerDefinition ControllerDefinition { get; private set; }

View File

@ -61,7 +61,7 @@ namespace BizHawk.Emulation.Cores.WonderSwan
}
}
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
public bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
Frame++;
IsLagFrame = true;
@ -79,6 +79,8 @@ namespace BizHawk.Emulation.Cores.WonderSwan
if (IsLagFrame)
LagCount++;
return true;
}
public CoreComm CoreComm { get; private set; }

View File

@ -154,11 +154,13 @@ namespace BizHawk.Emulation.Cores.Libretro
private IController _controller;
public void FrameAdvance(IController controller, bool render, bool rendersound)
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
_controller = controller;
api.CMD_Run();
timeFrameCounter++;
return true;
}
GCHandle vidBufferHandle;

View File

@ -191,7 +191,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
protected virtual void FrameAdvancePost()
{ }
public unsafe void FrameAdvance(IController controller, bool render, bool rendersound = true)
public unsafe bool FrameAdvance(IController controller, bool render, bool rendersound = true)
{
using (_exe.EnterExit())
{
@ -218,6 +218,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
FrameAdvancePost();
}
}
return true;
}
private bool _disposed = false;