BizHawk/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IEmulator.cs

259 lines
7.2 KiB
C#

using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
{
public partial class O2Hawk : IEmulator, IVideoProvider
{
public IEmulatorServiceProvider ServiceProvider { get; }
public ControllerDefinition ControllerDefinition => _controllerDeck.Definition;
public byte controller_state_1, controller_state_2, kb_state_row, kb_state_col;
public bool in_vblank_old;
public bool in_vblank;
public bool vblank_rise;
public uint ticker;
public bool FrameAdvance(IController controller, bool render, bool rendersound)
{
//Console.WriteLine("-----------------------FRAME-----------------------");
if (_tracer.Enabled)
{
cpu.TraceCallback = s => _tracer.Put(s);
}
else
{
cpu.TraceCallback = null;
}
_frame++;
if (controller.IsPressed("Power"))
{
HardReset();
}
if (controller.IsPressed("Reset"))
{
SoftReset();
}
_islag = true;
do_frame(controller);
if (_islag)
{
_lagcount++;
}
return true;
}
public void do_frame(IController controller)
{
// update the controller state on VBlank
GetControllerState(controller);
bool frame_chk = true;
//Console.WriteLine("----------FRAME----------");
if (is_pal)
{
// PAL timing is: 17.7 / 5 ppu
// and 17.7 / 9 for cpu (divide by 3 externally then by 3 again internally)
while (frame_chk)
{
ticker++;
if (ticker % 5 == 0)
{
ppu.tick();
if (ticker % 10 == 0)
{
ppu.Audio_tick();
}
}
if ((ticker % 9) == 0)
{
cpu.ExecuteOne();
}
if (!in_vblank && in_vblank_old)
{
frame_chk = false;
}
in_vblank_old = in_vblank;
}
}
else
{
// NTSC is 2 to 1 ppu to cpu ticks
while (frame_chk)
{
ppu.tick();
ppu.tick();
ppu.Audio_tick();
cpu.ExecuteOne();
if (!in_vblank && in_vblank_old)
{
frame_chk = false;
}
in_vblank_old = in_vblank;
}
}
// send the image on VBlank
SendVideoBuffer();
}
public void do_single_step()
{
ppu.tick();
ppu.tick();
ppu.Audio_tick();
cpu.ExecuteOne();
}
public void GetControllerState(IController controller)
{
InputCallbacks.Call();
controller_state_1 = _controllerDeck.ReadPort1(controller);
controller_state_2 = _controllerDeck.ReadPort2(controller);
kb_state_row = 8; // nothing pressed
if (controller.IsPressed("0")) { kb_state_row = 0; kb_state_col = 7; }
if (controller.IsPressed("1")) { kb_state_row = 0; kb_state_col = 6; }
if (controller.IsPressed("2")) { kb_state_row = 0; kb_state_col = 5; }
if (controller.IsPressed("3")) { kb_state_row = 0; kb_state_col = 4; }
if (controller.IsPressed("4")) { kb_state_row = 0; kb_state_col = 3; }
if (controller.IsPressed("5")) { kb_state_row = 0; kb_state_col = 2; }
if (controller.IsPressed("6")) { kb_state_row = 0; kb_state_col = 1; }
if (controller.IsPressed("7")) { kb_state_row = 0; kb_state_col = 0; }
if (controller.IsPressed("8")) { kb_state_row = 1; kb_state_col = 7; }
if (controller.IsPressed("9")) { kb_state_row = 1; kb_state_col = 6; }
if (controller.IsPressed("SPC")) { kb_state_row = 1; kb_state_col = 3; }
if (controller.IsPressed("?")) { kb_state_row = 1; kb_state_col = 2; }
if (controller.IsPressed("L")) { kb_state_row = 1; kb_state_col = 1; }
if (controller.IsPressed("P")) { kb_state_row = 1; kb_state_col = 0; }
if (controller.IsPressed("+")) { kb_state_row = 2; kb_state_col = 7; }
if (controller.IsPressed("W")) { kb_state_row = 2; kb_state_col = 6; }
if (controller.IsPressed("E")) { kb_state_row = 2; kb_state_col = 5; }
if (controller.IsPressed("R")) { kb_state_row = 2; kb_state_col = 4; }
if (controller.IsPressed("T")) { kb_state_row = 2; kb_state_col = 3; }
if (controller.IsPressed("U")) { kb_state_row = 2; kb_state_col = 2; }
if (controller.IsPressed("I")) { kb_state_row = 2; kb_state_col = 1; }
if (controller.IsPressed("O")) { kb_state_row = 2; kb_state_col = 0; }
if (controller.IsPressed("Q")) { kb_state_row = 3; kb_state_col = 7; }
if (controller.IsPressed("S")) { kb_state_row = 3; kb_state_col = 6; }
if (controller.IsPressed("D")) { kb_state_row = 3; kb_state_col = 5; }
if (controller.IsPressed("F")) { kb_state_row = 3; kb_state_col = 4; }
if (controller.IsPressed("G")) { kb_state_row = 3; kb_state_col = 3; }
if (controller.IsPressed("H")) { kb_state_row = 3; kb_state_col = 2; }
if (controller.IsPressed("J")) { kb_state_row = 3; kb_state_col = 1; }
if (controller.IsPressed("K")) { kb_state_row = 3; kb_state_col = 0; }
if (controller.IsPressed("A")) { kb_state_row = 4; kb_state_col = 7; }
if (controller.IsPressed("Z")) { kb_state_row = 4; kb_state_col = 6; }
if (controller.IsPressed("X")) { kb_state_row = 4; kb_state_col = 5; }
if (controller.IsPressed("C")) { kb_state_row = 4; kb_state_col = 4; }
if (controller.IsPressed("V")) { kb_state_row = 4; kb_state_col = 3; }
if (controller.IsPressed("B")) { kb_state_row = 4; kb_state_col = 2; }
if (controller.IsPressed("M")) { kb_state_row = 4; kb_state_col = 1; }
if (controller.IsPressed(".")) { kb_state_row = 4; kb_state_col = 0; }
if (controller.IsPressed("-")) { kb_state_row = 5; kb_state_col = 7; }
if (controller.IsPressed("*")) { kb_state_row = 5; kb_state_col = 6; }
if (controller.IsPressed("/")) { kb_state_row = 5; kb_state_col = 5; }
if (controller.IsPressed("=")) { kb_state_row = 5; kb_state_col = 4; }
if (controller.IsPressed("YES")) { kb_state_row = 5; kb_state_col = 3; }
if (controller.IsPressed("NO")) { kb_state_row = 5; kb_state_col = 2; }
if (controller.IsPressed("CLR")) { kb_state_row = 5; kb_state_col = 1; }
if (controller.IsPressed("ENT")) { kb_state_row = 5; kb_state_col = 0; }
}
public void KB_Scan()
{
if (kb_byte == kb_state_row)
{
kb_byte &= 0xEF;
kb_byte |= (byte)(kb_state_col << 5);
}
else
{
kb_byte |= 0x10;
}
}
public int Frame => _frame;
public string SystemId => "O2";
public bool DeterministicEmulation { get; set; }
public void ResetCounters()
{
_frame = 0;
_lagcount = 0;
_islag = false;
}
public void Dispose()
{
ppu.DisposeSound();
}
#region Video provider
public int _frameHz = 60;
public int[] _vidbuffer;
public int[] frame_buffer;
public int[] GetVideoBuffer()
{
return frame_buffer;
}
public void SendVideoBuffer()
{
for (int j = 0; j < pic_height; j++)
{
for (int i = 0; i < 320; i++)
{
frame_buffer[j * 320 + i] = _vidbuffer[j * 372 + i];
_vidbuffer[j * 372 + i] = 0;
}
for (int k = 320; k < 372; k++)
{
_vidbuffer[j * 372 + k] = 0;
}
}
}
public int pic_height;
public int VirtualWidth => 320;
public int VirtualHeight => pic_height;
public int BufferWidth => 320;
public int BufferHeight => pic_height;
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
}
}