From 60af8a36fca5d58d1aee7037bf5b7f3e1a1dfa4d Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 24 Apr 2020 10:14:48 -0400 Subject: [PATCH] GBHawk: add setting to sync domains to vblank (reads only). works better with LUA --- .../Nintendo/GBHawk/GBHawk.IEmulator.cs | 13 ++++ .../Nintendo/GBHawk/GBHawk.IMemoryDomains.cs | 72 +++++++++++++++++-- .../Nintendo/GBHawk/GBHawk.ISettable.cs | 5 ++ .../Nintendo/GBHawk/GBHawk.IStatable.cs | 12 ++-- .../Consoles/Nintendo/GBHawk/GBHawk.cs | 8 +++ 5 files changed, 101 insertions(+), 9 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs index cd10b591b0..c7782789c6 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IEmulator.cs @@ -124,6 +124,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk // send the image on VBlank SendVideoBuffer(); + + if (_settings.VBL_sync) + { + for (int j = 0; j < 0x8000; j++) { RAM_vbls[j] = RAM[j]; } + for (int j = 0; j < 0x4000; j++) { VRAM_vbls[j] = VRAM[j]; } + for (int j = 0; j < 0x80; j++) { ZP_RAM_vbls[j] = ZP_RAM[j]; } + for (int j = 0; j < 0xA0; j++) { OAM_vbls[j] = OAM[j]; } + + if (cart_RAM != null) + { + for (int j = 0; j < cart_RAM.Length; j++) { cart_RAM_vbls[j] = cart_RAM[j]; } + } + } } REG_FF0F_OLD = REG_FF0F; diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IMemoryDomains.cs index b194879498..ec26712605 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IMemoryDomains.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IMemoryDomains.cs @@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk "WRAM", RAM.Length, MemoryDomain.Endian.Little, - addr => RAM[addr], + addr => PeekRAM(addr), (addr, value) => RAM[addr] = value, 1), new MemoryDomainDelegate( @@ -29,21 +29,21 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk "VRAM", VRAM.Length, MemoryDomain.Endian.Little, - addr => VRAM[addr], + addr => PeekVRAM(addr), (addr, value) => VRAM[addr] = value, 1), new MemoryDomainDelegate( "OAM", OAM.Length, MemoryDomain.Endian.Little, - addr => OAM[addr], + addr => PeekOAM(addr), (addr, value) => OAM[addr] = value, 1), new MemoryDomainDelegate( "HRAM", ZP_RAM.Length, MemoryDomain.Endian.Little, - addr => ZP_RAM[addr], + addr => PeekHRAM(addr), (addr, value) => ZP_RAM[addr] = value, 1), new MemoryDomainDelegate( @@ -61,7 +61,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk "CartRAM", cart_RAM.Length, MemoryDomain.Endian.Little, - addr => cart_RAM[addr], + addr => PeekCART(addr), (addr, value) => cart_RAM[addr] = value, 1); domains.Add(CartRam); @@ -71,6 +71,68 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk (ServiceProvider as BasicServiceProvider).Register(MemoryDomains); } + private byte PeekRAM(long addr) + { + ushort addr2 = (ushort)(addr & 0x7FFF); + if (_settings.VBL_sync) + { + return RAM_vbls[addr2]; + } + return RAM[addr2]; + } + + private byte PeekVRAM(long addr) + { + ushort addr2 = (ushort)(addr & 0x3FFF); + if (_settings.VBL_sync) + { + return VRAM_vbls[addr2]; + } + return VRAM[addr2]; + } + + private byte PeekHRAM(long addr) + { + ushort addr2 = (ushort)(addr & 0x7F); + if (_settings.VBL_sync) + { + return ZP_RAM_vbls[addr2]; + } + return ZP_RAM[addr2]; + } + + private byte PeekOAM(long addr) + { + if (addr < 0xA0) + { + if (_settings.VBL_sync) + { + return OAM_vbls[addr]; + } + return OAM[addr]; + } + return 0xFF; + } + + private byte PeekCART(long addr) + { + if (cart_RAM != null) + { + if (addr < cart_RAM.Length) + { + if (_settings.VBL_sync) + { + return cart_RAM_vbls[addr]; + } + return cart_RAM[addr]; + } + + return 0xFF; + } + + return 0xFF; + } + private byte PeekSystemBus(long addr) { ushort addr2 = (ushort)(addr & 0xFFFF); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs index 0d5672456f..7b3b323beb 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.ISettable.cs @@ -49,6 +49,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk [DefaultValue(PaletteType.BW)] public PaletteType Palette { get; set; } + [DisplayName("Read Domains on VBlank")] + [Description("When true, memory domains are only updated on VBlank. More consistent for LUA. NOTE: Does not work for system bus, does not apply to writes.")] + [DefaultValue(false)] + public bool VBL_sync { get; set; } + public GBSettings Clone() { return (GBSettings)MemberwiseClone(); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs index 1ccff5eea4..ecced72d3c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.IStatable.cs @@ -80,10 +80,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk ser.Sync(nameof(vid_buffer), ref vid_buffer, false); // probably a better way to do this - if (cart_RAM != null) - { - ser.Sync(nameof(cart_RAM), ref cart_RAM, false); - } + if (cart_RAM != null) { ser.Sync(nameof(cart_RAM), ref cart_RAM, false); } + + ser.Sync(nameof(RAM_vbls), ref RAM_vbls, false); + ser.Sync(nameof(ZP_RAM_vbls), ref ZP_RAM_vbls, false); + ser.Sync(nameof(VRAM_vbls), ref VRAM_vbls, false); + ser.Sync(nameof(OAM_vbls), ref OAM_vbls, false); + + if (cart_RAM != null) { ser.Sync(nameof(cart_RAM_vbls), ref cart_RAM_vbls, false); } ser.EndSection(); } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs index 782ac39f9e..048683cbf6 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs @@ -47,6 +47,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public byte[] VRAM = new byte[0x4000]; public byte[] OAM = new byte[0xA0]; + // vblank memory domains + public byte[] RAM_vbls = new byte[0x8000]; + public byte[] ZP_RAM_vbls = new byte[0x80]; + public byte[] VRAM_vbls = new byte[0x4000]; + public byte[] OAM_vbls = new byte[0xA0]; + public int RAM_Bank; public byte VRAM_Bank; internal bool is_GBC; @@ -65,6 +71,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk public readonly byte[] header = new byte[0x50]; public byte[] cart_RAM; + public byte[] cart_RAM_vbls; public bool has_bat; private int _frame = 0; @@ -173,6 +180,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk Console.WriteLine("SHA1: " + rom.HashSHA1(0, rom.Length)); _rom = rom; Setup_Mapper(); + if (cart_RAM != null) { cart_RAM_vbls = new byte[cart_RAM.Length]; } timer.Core = this; audio.Core = this;