From 8ce51896dc8167120dd5367352254783c784c458 Mon Sep 17 00:00:00 2001 From: sin365 <353374337@qq.com> Date: Tue, 21 Apr 2026 17:48:59 +0800 Subject: [PATCH] =?UTF-8?q?[Essgee]=20=E5=B9=B2=E6=8E=89=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E5=99=A8=20|=20=E8=89=B2=E5=BD=A9=E8=A1=A8=E9=A2=84=E5=85=88?= =?UTF-8?q?=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Essgee.Unity/Emulation/CPU/SM83.cs | 2 + .../Essgee.Unity/Emulation/CPU/SM83CGB.cs | 3 +- .../Emulation/Configuration/GameBoyColor.cs | 33 ++++-- .../Essgee.Unity/Emulation/Utilities.cs | 100 +++++++++++++++--- .../Emulation/Video/Nintendo/CGBVideo.cs | 3 +- 5 files changed, 113 insertions(+), 28 deletions(-) diff --git a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/CPU/SM83.cs b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/CPU/SM83.cs index c8df15c9..4bc6fd91 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/CPU/SM83.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/CPU/SM83.cs @@ -170,6 +170,7 @@ namespace Essgee.Emulation.CPU } else { + /* 全都不要了吧 log if (AppEnvironment.EnableSuperSlowCPULogger && logEntries != null) { string disasm = string.Format("{0} | {1} | {2} | {3}\n", DisassembleOpcode(this, pc).PadRight(48), PrintRegisters(this), PrintFlags(this), PrintInterrupt(this)); @@ -181,6 +182,7 @@ namespace Essgee.Emulation.CPU numLogEntries = 0; } } + */ /* Do HALT bug */ if (doHaltBug) diff --git a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/CPU/SM83CGB.cs b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/CPU/SM83CGB.cs index e6fb54e3..376fb688 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/CPU/SM83CGB.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/CPU/SM83CGB.cs @@ -8,7 +8,8 @@ namespace Essgee.Emulation.CPU public class SM83CGB : SM83 { // TODO: better way of implementing this? - public bool IsDoubleSpeed { get; private set; } + //public bool IsDoubleSpeed { get; private set; } + public bool IsDoubleSpeed; public SM83CGB(MemoryReadDelegate memoryRead, MemoryWriteDelegate memoryWrite) : base(memoryRead, memoryWrite) { } diff --git a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Configuration/GameBoyColor.cs b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Configuration/GameBoyColor.cs index bdc7f505..8b8a4b7c 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Configuration/GameBoyColor.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Configuration/GameBoyColor.cs @@ -9,7 +9,8 @@ namespace Essgee.Emulation.Configuration public class GameBoyColor : IConfiguration { //todo Unity [CheckBoxControl("General", "Use Bootstrap ROM")] - public bool UseBootstrap { get; set; } + //public bool UseBootstrap { get; set; } + public bool UseBootstrap; [IsBootstrapRomPath] //todo Unity [FileBrowserControl("General", "Bootstrap Path", "Game Boy Color Bootstrap ROM (*.gbc;*.bin;*.zip)|*.gbc;*.bin;*.zip")] public string BootstrapRom { get; set; } @@ -25,37 +26,47 @@ namespace Essgee.Emulation.Configuration //todo Unity [DropDownControl("Infrared", "Infrared Source", typeof(Machines.GameBoyColor.InfraredSources))] //[JsonConverter(typeof(StringEnumConverter))] - public Machines.GameBoyColor.InfraredSources InfraredSource { get; set; } + //public Machines.GameBoyColor.InfraredSources InfraredSource { get; set; } + public Machines.GameBoyColor.InfraredSources InfraredSource; //todo Unity [FileBrowserControl("Infrared", "Pokemon Pikachu DB", "Database Binary (*.bin)|*.bin")] public string InfraredDatabasePikachu { get; set; } //todo Unity [DropDownControl("Controls", "Up", typeof(Keys), Keys.F11)] //[JsonConverter(typeof(StringEnumConverter))] - public EssgeeMotionKey ControlsUp { get; set; } + //public EssgeeMotionKey ControlsUp { get; set; } + public EssgeeMotionKey ControlsUp; //todo Unity [DropDownControl("Controls", "Down", typeof(Keys), Keys.F11)] //[JsonConverter(typeof(StringEnumConverter))] - public EssgeeMotionKey ControlsDown { get; set; } + //public EssgeeMotionKey ControlsDown { get; set; } + public EssgeeMotionKey ControlsDown; //todo Unity [DropDownControl("Controls", "Left", typeof(Keys), Keys.F11)] //[JsonConverter(typeof(StringEnumConverter))] - public EssgeeMotionKey ControlsLeft { get; set; } + //public EssgeeMotionKey ControlsLeft { get; set; } + public EssgeeMotionKey ControlsLeft; //todo Unity [DropDownControl("Controls", "Right", typeof(Keys), Keys.F11)] //[JsonConverter(typeof(StringEnumConverter))] - public EssgeeMotionKey ControlsRight { get; set; } + //public EssgeeMotionKey ControlsRight { get; set; } + public EssgeeMotionKey ControlsRight; //todo Unity [DropDownControl("Controls", "A", typeof(Keys), Keys.F11)] //[JsonConverter(typeof(StringEnumConverter))] - public EssgeeMotionKey ControlsA { get; set; } + //public EssgeeMotionKey ControlsA { get; set; } + public EssgeeMotionKey ControlsA; //todo Unity [DropDownControl("Controls", "B", typeof(Keys), Keys.F11)] //[JsonConverter(typeof(StringEnumConverter))] - public EssgeeMotionKey ControlsB { get; set; } + //public EssgeeMotionKey ControlsB { get; set; } + public EssgeeMotionKey ControlsB; //todo Unity [DropDownControl("Controls", "Select", typeof(Keys), Keys.F11)] //[JsonConverter(typeof(StringEnumConverter))] - public EssgeeMotionKey ControlsSelect { get; set; } + //public EssgeeMotionKey ControlsSelect { get; set; } + public EssgeeMotionKey ControlsSelect; //todo Unity [DropDownControl("Controls", "Start", typeof(Keys), Keys.F11)] //[JsonConverter(typeof(StringEnumConverter))] - public EssgeeMotionKey ControlsStart { get; set; } + //public EssgeeMotionKey ControlsStart { get; set; } + public EssgeeMotionKey ControlsStart; //todo Unity [DropDownControl("Controls", "Send IR Signal", typeof(Keys), Keys.F11)] //[JsonConverter(typeof(StringEnumConverter))] - public EssgeeMotionKey ControlsSendIR { get; set; } + //public EssgeeMotionKey ControlsSendIR { get; set; } + public EssgeeMotionKey ControlsSendIR; public GameBoyColor() { diff --git a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs index 1727d4e8..9ca5ce33 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Utilities.cs @@ -4,6 +4,12 @@ namespace Essgee.Emulation { public unsafe static class Utilities { + static Utilities() + { + InitRGB222toBGRA8888Cache(); + InitRGB444toBGRA8888Cache(); + InitRGBCGBtoBGRA8888Cache(); + } public static bool IsBitSet(byte value, int bit) { return ((value & (1 << bit)) != 0); @@ -17,13 +23,34 @@ namespace Essgee.Emulation // buffer[address + 2] = (byte)((r << 6) | (r << 4) | (r << 2) | r); // buffer[address + 3] = 0xFF; //} + + + private static readonly byte[] RGB222toBGRA8888Cache_LutR = new byte[32768]; + private static readonly byte[] RGB222toBGRA8888Cache_LutG = new byte[32768]; + private static readonly byte[] RGB222toBGRA8888Cache_LutB = new byte[32768]; + + static void InitRGB222toBGRA8888Cache() // 静态构造函数初始化LUT + { + for (int i = 0; i < 32768; i++) + { + byte r = (byte)((i >> 0) & 0x3), g = (byte)((i >> 2) & 0x3), b = (byte)((i >> 4) & 0x3); + RGB222toBGRA8888Cache_LutR[i] = (byte)((b << 6) | (b << 4) | (b << 2) | b); + RGB222toBGRA8888Cache_LutG[i] = (byte)((g << 6) | (g << 4) | (g << 2) | g); + RGB222toBGRA8888Cache_LutB[i] = (byte)((r << 6) | (r << 4) | (r << 2) | r); + } + } + public static void RGB222toBGRA8888(int color, ref byte* buffer, int address) { - byte r = (byte)((color >> 0) & 0x3), g = (byte)((color >> 2) & 0x3), b = (byte)((color >> 4) & 0x3); - buffer[address + 0] = (byte)((b << 6) | (b << 4) | (b << 2) | b); - buffer[address + 1] = (byte)((g << 6) | (g << 4) | (g << 2) | g); - buffer[address + 2] = (byte)((r << 6) | (r << 4) | (r << 2) | r); - buffer[address + 3] = 0xFF; + //byte r = (byte)((color >> 0) & 0x3), g = (byte)((color >> 2) & 0x3), b = (byte)((color >> 4) & 0x3); + //buffer[address + 0] = (byte)((b << 6) | (b << 4) | (b << 2) | b); + //buffer[address + 1] = (byte)((g << 6) | (g << 4) | (g << 2) | g); + //buffer[address + 2] = (byte)((r << 6) | (r << 4) | (r << 2) | r); + //buffer[address + 3] = 0xFF; + *(buffer + address) = RGB222toBGRA8888Cache_LutR[color]; + *(buffer + address + 1) = RGB222toBGRA8888Cache_LutR[color]; + *(buffer + address + 2) = RGB222toBGRA8888Cache_LutR[color]; + *(buffer + address + 3) = 0xFF; } //public static void RGB444toBGRA8888(int color, ref byte[] buffer, int address) @@ -35,13 +62,33 @@ namespace Essgee.Emulation // buffer[address + 3] = 0xFF; //} + // 预计算所有可能的颜色转换 + private static readonly byte[] RGB444toBGRA8888Cache_LutR = new byte[32768]; + private static readonly byte[] RGB444toBGRA8888Cache_LutG = new byte[32768]; + private static readonly byte[] RGB444toBGRA8888Cache_LutB = new byte[32768]; + + static void InitRGB444toBGRA8888Cache() // 静态构造函数初始化LUT + { + for (int i = 0; i < 32768; i++) + { + byte r = (byte)((i >> 0) & 0xF), g = (byte)((i >> 4) & 0xF), b = (byte)((i >> 8) & 0xF); + RGB444toBGRA8888Cache_LutR[i] = (byte)((b << 4) | b); + RGB444toBGRA8888Cache_LutG[i] = (byte)((g << 4) | g); + RGB444toBGRA8888Cache_LutB[i] = (byte)((r << 4) | r); + } + } + public unsafe static void RGB444toBGRA8888(int color, ref byte* buffer, int address) { - byte r = (byte)((color >> 0) & 0xF), g = (byte)((color >> 4) & 0xF), b = (byte)((color >> 8) & 0xF); - buffer[address + 0] = (byte)((b << 4) | b); - buffer[address + 1] = (byte)((g << 4) | g); - buffer[address + 2] = (byte)((r << 4) | r); - buffer[address + 3] = 0xFF; + //byte r = (byte)((color >> 0) & 0xF), g = (byte)((color >> 4) & 0xF), b = (byte)((color >> 8) & 0xF); + //buffer[address + 0] = (byte)((b << 4) | b); + //buffer[address + 1] = (byte)((g << 4) | g); + //buffer[address + 2] = (byte)((r << 4) | r); + //buffer[address + 3] = 0xFF; + *(buffer + address) = RGB444toBGRA8888Cache_LutG[color]; + *(buffer + address + 1) = RGB444toBGRA8888Cache_LutG[color]; + *(buffer + address + 2) = RGB444toBGRA8888Cache_LutG[color]; + *(buffer + address + 3) = 0xFF; } //public static void RGBCGBtoBGRA8888(int color, ref byte[] buffer, int address) @@ -53,14 +100,37 @@ namespace Essgee.Emulation // buffer[address + 2] = (byte)(Math.Min(960, (r * 26) + (g * 4) + (b * 2)) >> 2); // buffer[address + 3] = 0xFF; //} + + // 预计算所有可能的颜色转换 + private static readonly byte[] RGBCGBtoBGRA8888Cache_LutR = new byte[32768]; // 15位颜色 = 32768种 + private static readonly byte[] RGBCGBtoBGRA8888Cache_LutG = new byte[32768]; + private static readonly byte[] RGBCGBtoBGRA8888Cache_LutB = new byte[32768]; + + static void InitRGBCGBtoBGRA8888Cache() // 静态构造函数初始化LUT + { + for (int i = 0; i < 32768; i++) + { + byte r = (byte)(i & 0x1F); + byte g = (byte)((i >> 5) & 0x1F); + byte b = (byte)((i >> 10) & 0x1F); + RGBCGBtoBGRA8888Cache_LutR[i] = (byte)(Math.Min(960, (r * 6) + (g * 4) + (b * 22)) >> 2); + RGBCGBtoBGRA8888Cache_LutG[i] = (byte)(Math.Min(960, (g * 24) + (b * 8)) >> 2); + RGBCGBtoBGRA8888Cache_LutB[i] = (byte)(Math.Min(960, (r * 26) + (g * 4) + (b * 2)) >> 2); + } + } + public static void RGBCGBtoBGRA8888(int color, ref byte* buffer, int address) { /* https://byuu.net/video/color-emulation -- "LCD emulation: Game Boy Color" */ - byte r = (byte)((color >> 0) & 0x1F), g = (byte)((color >> 5) & 0x1F), b = (byte)((color >> 10) & 0x1F); - buffer[address + 0] = (byte)(Math.Min(960, (r * 6) + (g * 4) + (b * 22)) >> 2); - buffer[address + 1] = (byte)(Math.Min(960, (g * 24) + (b * 8)) >> 2); - buffer[address + 2] = (byte)(Math.Min(960, (r * 26) + (g * 4) + (b * 2)) >> 2); - buffer[address + 3] = 0xFF; + //byte r = (byte)((color >> 0) & 0x1F), g = (byte)((color >> 5) & 0x1F), b = (byte)((color >> 10) & 0x1F); + //buffer[address + 0] = (byte)(Math.Min(960, (r * 6) + (g * 4) + (b * 22)) >> 2); + //buffer[address + 1] = (byte)(Math.Min(960, (g * 24) + (b * 8)) >> 2); + //buffer[address + 2] = (byte)(Math.Min(960, (r * 26) + (g * 4) + (b * 2)) >> 2); + //buffer[address + 3] = 0xFF; + *(buffer + address) = RGBCGBtoBGRA8888Cache_LutR[color]; + *(buffer + address + 1) = RGBCGBtoBGRA8888Cache_LutG[color]; + *(buffer + address + 2) = RGBCGBtoBGRA8888Cache_LutB[color]; + *(buffer + address + 3) = 0xFF; } } } diff --git a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/CGBVideo.cs b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/CGBVideo.cs index adbcfe87..ba5447fd 100644 --- a/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/CGBVideo.cs +++ b/AxibugEmuOnline.Client/Assets/Plugins/Essgee.Unity/Emulation/Video/Nintendo/CGBVideo.cs @@ -50,7 +50,8 @@ namespace Essgee.Emulation.Video.Nintendo bool hdmaIsActive; byte hdmaBytesLeft; - public int GDMAWaitCycles { get; set; } + //public int GDMAWaitCycles { get; set; } + public int GDMAWaitCycles; protected const byte screenUsageBackgroundHighPriority = (1 << 3);