From aa165f36d2624adf44a728a58bbae7fca29a6335 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 20 Mar 2020 16:39:14 -0400 Subject: [PATCH] O2Hawk: add PAL mode --- Assets/gamedb/gamedb_Odyssey2.txt | 22 +++--- .../Magnavox/Odyssey2/O2Hawk.IEmulator.cs | 68 +++++++++++++++---- .../Consoles/Magnavox/Odyssey2/O2Hawk.cs | 31 ++++----- .../Consoles/Magnavox/Odyssey2/PPU.cs | 40 +++++++---- 4 files changed, 105 insertions(+), 56 deletions(-) diff --git a/Assets/gamedb/gamedb_Odyssey2.txt b/Assets/gamedb/gamedb_Odyssey2.txt index a2bfd99ae0..3f89a2e580 100644 --- a/Assets/gamedb/gamedb_Odyssey2.txt +++ b/Assets/gamedb/gamedb_Odyssey2.txt @@ -3,17 +3,17 @@ ;;; ;;; Homebrew (but not derived from TOSEC) -SHA1:26A044C68FF08F574F6649B731B82CACA8C0E797 D Death Race O2 -SHA1:E04D12B6290370B76F90E76D9DE75B6470B4F913 D redgreen O2 -SHA1:38D4AAB263E10B1DAC3410C120536EE079826BCB D Fatso 2 O2 -SHA1:3720DD6B5EE3DC62C5AF2EA9D915A2B83DE9463D D Chief Chef O2 -SHA1:FEB358E28587DE70D1E89BF0F9A3209CE0B67C57 D Haunted House O2 -SHA1:B1D65BEDB56FE7A9CF60AA054A9FD9BB7F65B77C D 3D Box O2 -SHA1:0270047E2B1FC07581BF0FF9E55035925CF0EFF0 D Guiseppe apr14 O2 -SHA1:0D6B44E2445DBB3BF70C4E05F222822845C29762 D Boob O2 -SHA1:DE888B7AA2716C3134CFF812A4E07E86B2479537 D Shoot the B O2 -SHA1:85A44A99B254D92A7433EE46E4CAA91483D7FEA2 D Go Sub 2 O2 -SHA1:2B34EF0E1A8C0371F00A33D6950E0807F3CB886E D Happy Emu O2 +SHA1:26A044C68FF08F574F6649B731B82CACA8C0E797 D Death Race O2 US +SHA1:E04D12B6290370B76F90E76D9DE75B6470B4F913 D redgreen O2 US +SHA1:38D4AAB263E10B1DAC3410C120536EE079826BCB D Fatso 2 O2 US +SHA1:3720DD6B5EE3DC62C5AF2EA9D915A2B83DE9463D D Chief Chef O2 US +SHA1:FEB358E28587DE70D1E89BF0F9A3209CE0B67C57 D Haunted House O2 US +SHA1:B1D65BEDB56FE7A9CF60AA054A9FD9BB7F65B77C D 3D Box O2 US +SHA1:0270047E2B1FC07581BF0FF9E55035925CF0EFF0 D Guiseppe apr14 O2 US +SHA1:0D6B44E2445DBB3BF70C4E05F222822845C29762 D Boob O2 US +SHA1:DE888B7AA2716C3134CFF812A4E07E86B2479537 D Shoot the B O2 US +SHA1:85A44A99B254D92A7433EE46E4CAA91483D7FEA2 D Go Sub 2 O2 US +SHA1:2B34EF0E1A8C0371F00A33D6950E0807F3CB886E D Happy Emu O2 US diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IEmulator.cs index fcef335386..22eee10652 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.IEmulator.cs @@ -55,20 +55,58 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk bool frame_chk = true; - while (frame_chk) + if (is_pal) { - ppu.tick(); - ppu.tick(); - serialport.serial_transfer_tick(); - ppu.Audio_tick(); - cpu.ExecuteOne(); - - if (!in_vblank && in_vblank_old) + // PAL timing is: 17.7 / 5 ppu + // and 17.7 / 9 for cpu (divide by 3 externally then by 3 again internally) + int ticker = 0; + + while (frame_chk) { - frame_chk = false; - } + ticker++; - in_vblank_old = in_vblank; + if ((ticker % 5) == 0) + { + ppu.tick(); + + if ((ticker % 10) == 0) + { + ppu.Audio_tick(); + } + } + + if ((ticker % 9) == 0) + { + serialport.serial_transfer_tick(); + 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(); + serialport.serial_transfer_tick(); + ppu.Audio_tick(); + cpu.ExecuteOne(); + + if (!in_vblank && in_vblank_old) + { + frame_chk = false; + } + + in_vblank_old = in_vblank; + } } } @@ -184,7 +222,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk public void SendVideoBuffer() { - for (int j = 0; j < 240; j++) + for (int j = 0; j < pic_height; j++) { for (int i = 0; i < 320; i++) { @@ -199,10 +237,12 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk } } + public int pic_height; + public int VirtualWidth => 320; - public int VirtualHeight => 240; + public int VirtualHeight => pic_height; public int BufferWidth => 320; - public int BufferHeight => 240; + public int BufferHeight => pic_height; public int BackgroundColor => unchecked((int)0xFF000000); public int VsyncNumerator => _frameHz; public int VsyncDenominator => 1; diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs index f205d99d42..63b990249c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/O2Hawk.cs @@ -39,6 +39,8 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk public PPU ppu; public SerialPort serialport; + public bool is_pal; + [CoreConstructor("O2")] public O2Hawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings) { @@ -99,23 +101,23 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk SetupMemoryDomains(); HardReset(); - /* - for (int i = 0; i < 64; i++) - { - cpu.Regs[i] = (byte)i; - } - + // set up differences between PAL and NTSC systems + is_pal = true; + pic_height = 288; + _frameHz = 50; - for (int j = 0; j < 0x80; j++) + if ((game.Region == "US") || (game.Region == "EU-US") || (game.Region == null)) { - RAM[j] = (byte)j; + is_pal = false; + pic_height = 240; + _frameHz = 60; } - for (int k = 0; k < 0x100; k++) - { - ppu.WriteReg(k, (byte)k); - } - */ + ppu.set_region(is_pal); + + + _vidbuffer = new int[372 * pic_height]; + frame_buffer = new int[320 * pic_height]; } public DisplayType Region => DisplayType.NTSC; @@ -135,9 +137,6 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk serialport.Reset(); cpu.SetCallbacks(ReadMemory, PeekMemory, PeekMemory, WriteMemory); - - _vidbuffer = new int[372 * 240]; - frame_buffer = new int[320 * 240]; } private void ExecFetch(ushort addr) diff --git a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs index feb5033b2b..79e2b902dc 100644 --- a/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs +++ b/BizHawk.Emulation.Cores/Consoles/Magnavox/Odyssey2/PPU.cs @@ -10,6 +10,11 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk { public O2Hawk Core { get; set; } + // not stated, set on game load + public bool is_pal; + public int LINE_VBL; + public int LINE_MAX; + public const int HBL_CNT = 45; public byte[] Sprites = new byte[16]; @@ -203,7 +208,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk if (cycle >= HBL_CNT) { // draw a pixel - if (LY < 240) + if (LY < LINE_VBL) { if (cycle == HBL_CNT) { @@ -700,7 +705,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk LY++; - if (LY == 240) + if (LY == LINE_VBL) { VBL = true; Core.in_vblank = true; @@ -708,7 +713,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk Core.cpu.IRQPending = true; Core.cpu.T1 = true; } - if (LY == 262) + if (LY == LINE_MAX) { LY = 0; VBL = false; @@ -716,7 +721,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk VDC_status &= 0xF7; for (int i = 0; i < 8; i++) { VDC_col_ret[i] = 0; } } - if (LY < 240) + if (LY < LINE_VBL) { HBL = true; VDC_status &= 0xFE; @@ -726,17 +731,6 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk } } - // might be needed, not sure yet - public void latch_delay() - { - - } - - public void process_sprite() - { - - } - public void Reset() { Sprites = new byte[16]; @@ -749,6 +743,22 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk AudioReset(); } + public void set_region(bool pal_flag) + { + is_pal = pal_flag; + + if (is_pal) + { + LINE_MAX = 312; + LINE_VBL = 288; + } + else + { + LINE_MAX = 262; + LINE_VBL = 240; + } + } + public static readonly byte[] Internal_Graphics = { 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 00, // 0 0x00 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3C, 00, // 1 0x01 0x3C, 0x66, 0x0C, 0x18, 0x30, 0x60, 0x7E, 00, // 2 0x02