diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index 7f02da9f0b..785b5202bd 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -1059,7 +1059,7 @@ namespace BizHawk.Client.Common nextEmulator = cpc; break; case "GBA": - core = CoreInventory.Instance["GBA", Global.Config.PreferredCores["GBA"]]; + core = CoreInventory.Instance["GBA", CoreNames.Mgba]; break; case "PSX": nextEmulator = new Octoshock(nextComm, null, null, rom.FileData, GetCoreSettings(), GetCoreSyncSettings(), "PSX etc."); diff --git a/BizHawk.Client.Common/config/Config.cs b/BizHawk.Client.Common/config/Config.cs index 17013e7743..428290b79a 100644 --- a/BizHawk.Client.Common/config/Config.cs +++ b/BizHawk.Client.Common/config/Config.cs @@ -320,7 +320,6 @@ namespace BizHawk.Client.Common { ["NES"] = CoreNames.QuickNes, ["SNES"] = CoreNames.Snes9X, - ["GBA"] = CoreNames.Mgba, ["GB"] = CoreNames.Gambatte }; diff --git a/BizHawk.Client.Common/movie/import/VbmImport.cs b/BizHawk.Client.Common/movie/import/VbmImport.cs index 278e17b771..c7b08b1423 100644 --- a/BizHawk.Client.Common/movie/import/VbmImport.cs +++ b/BizHawk.Client.Common/movie/import/VbmImport.cs @@ -310,6 +310,6 @@ namespace BizHawk.Client.Common.movie.import } private static SimpleController GbaController() - => new SimpleController { Definition = GBA.GBAController }; + => new SimpleController { Definition = MGBAHawk.GBAController }; } } diff --git a/BizHawk.Client.EmuHawk/MainForm.Designer.cs b/BizHawk.Client.EmuHawk/MainForm.Designer.cs index f5b939ac88..067363a719 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Designer.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Designer.cs @@ -191,9 +191,6 @@ this.CoreSNESSubMenu = new System.Windows.Forms.ToolStripMenuItem(); this.Coresnes9xMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.CorebsnesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GbaCoreSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.VbaNextCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.MgbaCoreMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.SGBCoreSubmenu = new System.Windows.Forms.ToolStripMenuItem(); this.SgbBsnesMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.SgbSameBoyMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -292,9 +289,6 @@ this.GBGameGenieMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.GBPrinterViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.GBASubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.GBACoreSelectionSubMenu = new System.Windows.Forms.ToolStripMenuItem(); - this.GBAmGBAMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.GBAVBANextMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.GBAcoresettingsToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator33 = new System.Windows.Forms.ToolStripSeparator(); this.GbaGpuViewerMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -1802,7 +1796,6 @@ this.CoresSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.NesCoreSubMenu, this.CoreSNESSubMenu, - this.GbaCoreSubMenu, this.SGBCoreSubmenu, this.GBCoreSubmenu, this.GBInSGBMenuItem, @@ -1885,30 +1878,6 @@ this.CorebsnesMenuItem.Text = "BSNES"; this.CorebsnesMenuItem.Click += new System.EventHandler(this.CoreSnesToggle_Click); // - // GbaCoreSubMenu - // - this.GbaCoreSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.VbaNextCoreMenuItem, - this.MgbaCoreMenuItem}); - this.GbaCoreSubMenu.Name = "GbaCoreSubMenu"; - this.GbaCoreSubMenu.Size = new System.Drawing.Size(223, 22); - this.GbaCoreSubMenu.Text = "GBA"; - this.GbaCoreSubMenu.DropDownOpened += new System.EventHandler(this.GbaCoreSubMenu_DropDownOpened); - // - // VbaNextCoreMenuItem - // - this.VbaNextCoreMenuItem.Name = "VbaNextCoreMenuItem"; - this.VbaNextCoreMenuItem.Size = new System.Drawing.Size(120, 22); - this.VbaNextCoreMenuItem.Text = "VBA-Next"; - this.VbaNextCoreMenuItem.Click += new System.EventHandler(this.GbaCorePick_Click); - // - // MgbaCoreMenuItem - // - this.MgbaCoreMenuItem.Name = "MgbaCoreMenuItem"; - this.MgbaCoreMenuItem.Size = new System.Drawing.Size(120, 22); - this.MgbaCoreMenuItem.Text = "mGBA"; - this.MgbaCoreMenuItem.Click += new System.EventHandler(this.GbaCorePick_Click); - // // SGBCoreSubmenu // this.SGBCoreSubmenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -2655,7 +2624,6 @@ // GBASubMenu // this.GBASubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.GBACoreSelectionSubMenu, this.GBAcoresettingsToolStripMenuItem1, this.toolStripSeparator33, this.GbaGpuViewerMenuItem}); @@ -2664,30 +2632,6 @@ this.GBASubMenu.Text = "GBA"; this.GBASubMenu.DropDownOpened += new System.EventHandler(this.GBASubMenu_DropDownOpened); // - // GBACoreSelectionSubMenu - // - this.GBACoreSelectionSubMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.GBAmGBAMenuItem, - this.GBAVBANextMenuItem}); - this.GBACoreSelectionSubMenu.Name = "GBACoreSelectionSubMenu"; - this.GBACoreSelectionSubMenu.Size = new System.Drawing.Size(129, 22); - this.GBACoreSelectionSubMenu.Text = "&Core"; - this.GBACoreSelectionSubMenu.DropDownOpened += new System.EventHandler(this.GBACoreSelectionSubMenu_DropDownOpened); - // - // GBAmGBAMenuItem - // - this.GBAmGBAMenuItem.Name = "GBAmGBAMenuItem"; - this.GBAmGBAMenuItem.Size = new System.Drawing.Size(120, 22); - this.GBAmGBAMenuItem.Text = "mGBA"; - this.GBAmGBAMenuItem.Click += new System.EventHandler(this.UsemGBAMenuItem_Click); - // - // GBAVBANextMenuItem - // - this.GBAVBANextMenuItem.Name = "GBAVBANextMenuItem"; - this.GBAVBANextMenuItem.Size = new System.Drawing.Size(120, 22); - this.GBAVBANextMenuItem.Text = "&VBA-Next"; - this.GBAVBANextMenuItem.Click += new System.EventHandler(this.UseVbaNextMenuItem_Click); - // // GBAcoresettingsToolStripMenuItem1 // this.GBAcoresettingsToolStripMenuItem1.Name = "GBAcoresettingsToolStripMenuItem1"; @@ -4398,9 +4342,6 @@ private System.Windows.Forms.ToolStripMenuItem subNesHawkMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator34; private System.Windows.Forms.ToolStripSeparator toolStripSeparator35; - private System.Windows.Forms.ToolStripMenuItem GBACoreSelectionSubMenu; - private System.Windows.Forms.ToolStripMenuItem GBAmGBAMenuItem; - private System.Windows.Forms.ToolStripMenuItem GBAVBANextMenuItem; private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem1; private System.Windows.Forms.ToolStripMenuItem PSXHashDiscsToolStripMenuItem; private System.Windows.Forms.Timer timerMouseIdle; @@ -4455,9 +4396,6 @@ private System.Windows.Forms.ToolStripMenuItem NesCoreSubMenu; private System.Windows.Forms.ToolStripMenuItem QuicknesCoreMenuItem; private System.Windows.Forms.ToolStripMenuItem NesCoreMenuItem; - private System.Windows.Forms.ToolStripMenuItem GbaCoreSubMenu; - private System.Windows.Forms.ToolStripMenuItem VbaNextCoreMenuItem; - private System.Windows.Forms.ToolStripMenuItem MgbaCoreMenuItem; private System.Windows.Forms.ToolStripMenuItem Atari7800HawkCoreMenuItem; private System.Windows.Forms.ToolStripMenuItem SGBCoreSubmenu; private System.Windows.Forms.ToolStripMenuItem SgbBsnesMenuItem; diff --git a/BizHawk.Client.EmuHawk/MainForm.Events.cs b/BizHawk.Client.EmuHawk/MainForm.Events.cs index b558c4eb02..f10acfda1e 100644 --- a/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -1258,23 +1258,6 @@ namespace BizHawk.Client.EmuHawk } } - private void GbaCoreSubMenu_DropDownOpened(object sender, EventArgs e) - { - VbaNextCoreMenuItem.Checked = Config.PreferredCores["GBA"] == CoreNames.VbaNext; - MgbaCoreMenuItem.Checked = Config.PreferredCores["GBA"] == CoreNames.Mgba; - } - - private void GbaCorePick_Click(object sender, EventArgs e) - { - Config.PreferredCores["GBA"] = Config.PreferredCores["GBA"] == CoreNames.VbaNext - ? CoreNames.Mgba - : CoreNames.VbaNext; - if (Emulator.SystemId == "GBA") - { - FlagNeedsReboot(); - } - } - private void SGBCoreSubmenu_DropDownOpened(object sender, EventArgs e) { SgbBsnesMenuItem.Checked = Config.SgbUseBsnes; @@ -2000,29 +1983,11 @@ namespace BizHawk.Client.EmuHawk Tools.Load(); } - private void UsemGBAMenuItem_Click(object sender, EventArgs e) - { - Config.PreferredCores["GBA"] = CoreNames.Mgba; - FlagNeedsReboot(); - } - - private void UseVbaNextMenuItem_Click(object sender, EventArgs e) - { - Config.PreferredCores["GBA"] = CoreNames.VbaNext; - FlagNeedsReboot(); - } - private void GBASubMenu_DropDownOpened(object sender, EventArgs e) { GbaGpuViewerMenuItem.Enabled = !OSTailoredCode.IsUnixHost; } - private void GBACoreSelectionSubMenu_DropDownOpened(object sender, EventArgs e) - { - GBAmGBAMenuItem.Checked = Config.PreferredCores["GBA"] == CoreNames.Mgba; - GBAVBANextMenuItem.Checked = Config.PreferredCores["GBA"] == CoreNames.VbaNext; - } - #endregion #region NDS diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 65be34780c..310f093b9d 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -1663,9 +1663,8 @@ namespace BizHawk.Client.EmuHawk byte[] sram; - // GBA meteor core might not know how big the saveram ought to be, so just send it the whole file - // GBA vba-next core will try to eat anything, regardless of size - if (Emulator is VBANext || Emulator is MGBAHawk || Emulator is NeoGeoPort) + // some cores might not know how big the saveram ought to be, so just send it the whole file + if (Emulator is MGBAHawk || Emulator is NeoGeoPort) { sram = File.ReadAllBytes(saveRamPath); } diff --git a/BizHawk.Client.EmuHawk/tools/BatchRunner.cs b/BizHawk.Client.EmuHawk/tools/BatchRunner.cs index bbcdaf1040..c0f11d6a3d 100644 --- a/BizHawk.Client.EmuHawk/tools/BatchRunner.cs +++ b/BizHawk.Client.EmuHawk/tools/BatchRunner.cs @@ -166,11 +166,6 @@ namespace BizHawk.Client.EmuHawk _current.CoreType = emu.GetType(); var controller = new Controller(emu.ControllerDefinition); _current.BoardName = emu.HasBoardInfo() ? emu.AsBoardInfo().BoardName : null; - // hack - if (emu is VBANext vba) - { - _current.BoardName = vba.GameCode; - } _current.Frames = 0; _current.LaggedFrames = 0; diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 63f847103a..7cd09a2f55 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -42,7 +42,6 @@ - diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/GBA.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/GBA.cs deleted file mode 100644 index 717e57a20f..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/GBA.cs +++ /dev/null @@ -1,28 +0,0 @@ -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public static class GBA - { - private static readonly ControllerDefinition.AxisRange TiltRange = new ControllerDefinition.AxisRange(-32767, 0, 32767); - - public static readonly ControllerDefinition GBAController = new ControllerDefinition - { - Name = "GBA Controller", - BoolButtons = - { - "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "L", "R", "Power" - }, - AxisControls = - { - "Tilt X", "Tilt Y", "Tilt Z", - "Light Sensor" - }, - AxisRanges = - { - TiltRange, TiltRange, TiltRange, - new ControllerDefinition.AxisRange(0, 100, 200), - } - }; - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs deleted file mode 100644 index 7c955cc8b3..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibVBANext.cs +++ /dev/null @@ -1,214 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public class LibVBANext - { - const string dllname = "libvbanext.dll"; - const CallingConvention cc = CallingConvention.Cdecl; - - [Flags] - public enum Buttons : int - { - A = 1, - B = 2, - Select = 4, - Start = 8, - Right = 16, - Left = 32, - Up = 64, - Down = 128, - R = 256, - L = 512 - } - - [StructLayout(LayoutKind.Sequential)] - public class FrontEndSettings - { - public enum SaveType : int - { - auto = 0, - eeprom = 1, - sram = 2, - flash = 3, - eeprom_sensor = 4, - none = 5 - } - public enum FlashSize : int - { - small = 0x10000, - big = 0x20000 - } - public SaveType saveType; - public FlashSize flashSize = FlashSize.big; - public bool enableRtc; - public bool mirroringEnable; - public bool skipBios; - - public bool RTCUseRealTime = true; - public int RTCyear; // 00..99 - public int RTCmonth; // 00..11 - public int RTCmday; // 01..31 - public int RTCwday; // 00..06 - public int RTChour; // 00..23 - public int RTCmin; // 00..59 - public int RTCsec; // 00..59 - } - - /// - /// create a new context - /// - [DllImport(dllname, CallingConvention = cc)] - public static extern IntPtr Create(); - - /// - /// destroy a context - /// - [DllImport(dllname, CallingConvention = cc)] - public static extern void Destroy(IntPtr g); - - /// - /// load a rom - /// - /// success - [DllImport(dllname, CallingConvention = cc)] - public static extern bool LoadRom(IntPtr g, byte[] romfile, uint romfilelen, byte[] biosfile, uint biosfilelen, [In]FrontEndSettings settings); - - /// - /// hard reset - /// - [DllImport(dllname, CallingConvention = cc)] - public static extern void Reset(IntPtr g); - - /// - /// frame advance - /// - /// 240x160 packed argb32 - /// buffer to recieve stereo audio - /// number of samples created - /// true if lagged - [DllImport(dllname, CallingConvention = cc)] - public static extern bool FrameAdvance(IntPtr g, Buttons input, int[] videobuffer, short[] audiobuffer, out int numsamp, int[] videopalette); - - [DllImport(dllname, CallingConvention = cc)] - public static extern int BinStateSize(IntPtr g); - [DllImport(dllname, CallingConvention = cc)] - public static extern bool BinStateSave(IntPtr g, byte[] data, int length); - [DllImport(dllname, CallingConvention = cc)] - public static extern bool BinStateLoad(IntPtr g, byte[] data, int length); - [DllImport(dllname, CallingConvention = cc)] - public static extern void TxtStateSave(IntPtr g, [In]ref TextStateFPtrs ff); - [DllImport(dllname, CallingConvention = cc)] - public static extern void TxtStateLoad(IntPtr g, [In]ref TextStateFPtrs ff); - - [DllImport(dllname, CallingConvention = cc)] - public static extern int SaveRamSize(IntPtr g); - [DllImport(dllname, CallingConvention = cc)] - public static extern bool SaveRamSave(IntPtr g, byte[] data, int length); - [DllImport(dllname, CallingConvention = cc)] - public static extern bool SaveRamLoad(IntPtr g, byte[] data, int length); - [DllImport(dllname, CallingConvention = cc)] - public static extern void GetMemoryAreas(IntPtr g, [Out]MemoryAreas mem); - - [DllImport(dllname, CallingConvention = cc)] - public static extern void SystemBusWrite(IntPtr g, int addr, byte val); - [DllImport(dllname, CallingConvention = cc)] - public static extern byte SystemBusRead(IntPtr g, int addr); - - [UnmanagedFunctionPointer(cc)] - public delegate void StandardCallback(); - - [DllImport(dllname, CallingConvention = cc)] - public static extern void SetScanlineCallback(IntPtr g, StandardCallback cb, int scanline); - - [DllImport(dllname, CallingConvention = cc)] - public static extern IntPtr GetRegisters(IntPtr g); - - [UnmanagedFunctionPointer(cc)] - public delegate void AddressCallback(uint addr); - - /// if bit 0 is set, thumb mode - [UnmanagedFunctionPointer(cc)] - public delegate void TraceCallback(uint addr, uint opcode); - - [DllImport(dllname, CallingConvention = cc)] - public static extern void SetPadCallback(IntPtr g, StandardCallback cb); - [DllImport(dllname, CallingConvention = cc)] - public static extern void SetFetchCallback(IntPtr g, AddressCallback cb); - [DllImport(dllname, CallingConvention = cc)] - public static extern void SetReadCallback(IntPtr g, AddressCallback cb); - [DllImport(dllname, CallingConvention = cc)] - public static extern void SetWriteCallback(IntPtr g, AddressCallback cb); - [DllImport(dllname, CallingConvention = cc)] - public static extern void SetTraceCallback(IntPtr g, TraceCallback cb); - - - [StructLayout(LayoutKind.Sequential)] - public class MemoryAreas - { - public IntPtr bios; - public IntPtr iwram; - public IntPtr ewram; - public IntPtr palram; - public IntPtr vram; - public IntPtr oam; - public IntPtr rom; - public IntPtr mmio; - public IntPtr sram; - public int sram_size; - } - - // this isn't used directly at the moment. but it could be used for something eventually... - [StructLayout(LayoutKind.Sequential)] - public class Registers - { - public int R0; - public int R1; - public int R2; - public int R3; - public int R4; - public int R5; - public int R6; - public int R7; - public int R8; - public int R9; - public int R10; - public int R11; - public int R12; - public int R13; - public int R14; - public int R15; - public int CPSR; - public int SPSR; - public int R13_IRQ; - public int R14_IRQ; - public int SPSR_IRQ; - public int _unk0; // what are these??? - public int _unk1; - public int _unk2; - public int _unk3; - public int _unk4; - public int R13_USR; - public int R14_USR; - public int R13_SVC; - public int R14_SVC; - public int SPSR_SVC; - public int R13_ABT; - public int R14_ABT; - public int SPSR_ABT; - public int R13_UND; - public int R14_UND; - public int SPSR_UND; - public int R8_FIQ; - public int R9_FIQ; - public int R10_FIQ; - public int R11_FIQ; - public int R12_FIQ; - public int R13_FIQ; - public int R14_FIQ; - public int SPSR_FIQ; - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs index a59af3dc2c..d395d60e90 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibmGBA.cs @@ -1,10 +1,39 @@ using System; using System.Runtime.InteropServices; +using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Nintendo.GBA { public static class LibmGBA { + [Flags] + public enum Buttons : int + { + A = 1, + B = 2, + Select = 4, + Start = 8, + Right = 16, + Left = 32, + Up = 64, + Down = 128, + R = 256, + L = 512 + } + + public static Buttons GetButtons(IController c) + { + Buttons ret = 0; + foreach (string s in Enum.GetNames(typeof(Buttons))) + { + if (c.IsPressed(s)) + { + ret |= (Buttons)Enum.Parse(typeof(Buttons), s); + } + } + return ret; + } + const string dll = "mgba.dll"; const CallingConvention cc = CallingConvention.Cdecl; @@ -95,7 +124,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public static extern void BizReset(IntPtr ctx); [DllImport(dll, CallingConvention = cc)] - public static extern bool BizAdvance(IntPtr ctx, LibVBANext.Buttons keys, int[] vbuff, ref int nsamp, short[] sbuff, + public static extern bool BizAdvance(IntPtr ctx, Buttons keys, int[] vbuff, ref int nsamp, short[] sbuff, long time, short gyrox, short gyroy, short gyroz, byte luma); [DllImport(dll, CallingConvention = cc)] diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs index 0bdafd1470..5316562699 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/MGBAHawk.cs @@ -73,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA public IEmulatorServiceProvider ServiceProvider { get; } - public ControllerDefinition ControllerDefinition => GBA.GBAController; + public ControllerDefinition ControllerDefinition => GBAController; private ITraceable Tracer { get; } @@ -117,7 +117,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA IsLagFrame = LibmGBA.BizAdvance( Core, - VBANext.GetButtons(controller), + LibmGBA.GetButtons(controller), render ? _videobuff : _dummyvideobuff, ref _nsamp, renderSound ? _soundbuff : _dummysoundbuff, @@ -249,5 +249,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA long increment = Frame * 4389L >> 18; return baseTime + increment; } + + private static readonly ControllerDefinition.AxisRange TiltRange = new ControllerDefinition.AxisRange(-32767, 0, 32767); + + public static readonly ControllerDefinition GBAController = new ControllerDefinition + { + Name = "GBA Controller", + BoolButtons = + { + "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "L", "R", "Power" + }, + AxisControls = + { + "Tilt X", "Tilt Y", "Tilt Z", + "Light Sensor" + }, + AxisRanges = + { + TiltRange, TiltRange, TiltRange, + new ControllerDefinition.AxisRange(0, 100, 200), + } + }; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IDebuggable.cs deleted file mode 100644 index 68c4559bd9..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IDebuggable.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class VBANext : IDebuggable - { - public IDictionary GetCpuFlagsAndRegisters() => regs.GetAllRegisters(); - - public void SetCpuRegister(string register, int value) => regs.SetRegister(register, value); - - public bool CanStep(StepType type) => false; - - private readonly MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem(new[] { "System Bus" }); - public IMemoryCallbackSystem MemoryCallbacks => _memorycallbacks; - - [FeatureNotImplemented] - public void Step(StepType type) => throw new NotImplementedException(); - - [FeatureNotImplemented] - public long TotalExecutedCycles => throw new NotImplementedException(); - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IGBAGPUViewable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IGBAGPUViewable.cs deleted file mode 100644 index ea14fb717e..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IGBAGPUViewable.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class VBANext : IGBAGPUViewable - { - public GBAGPUMemoryAreas GetMemoryAreas() - { - var s = new LibVBANext.MemoryAreas(); - LibVBANext.GetMemoryAreas(Core, s); - return new GBAGPUMemoryAreas - { - mmio = s.mmio, - oam = s.oam, - palram = s.palram, - vram = s.vram - }; - } - - public void SetScanlineCallback(Action callback, int scanline) - { - if (scanline < 0 || scanline > 227) - { - throw new ArgumentOutOfRangeException(nameof(scanline), "Scanline must be in [0, 227]!"); - } - - if (callback == null) - { - scanlinecb = null; - LibVBANext.SetScanlineCallback(Core, scanlinecb, 0); - } - else - { - scanlinecb = new LibVBANext.StandardCallback(callback); - LibVBANext.SetScanlineCallback(Core, scanlinecb, scanline); - } - } - - private LibVBANext.StandardCallback scanlinecb; - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IMemoryDomains.cs deleted file mode 100644 index bd0fb8c2c3..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IMemoryDomains.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class VBANext - { - private IMemoryDomains _memoryDomains; - - private void InitMemoryDomains() - { - var mm = new List(); - var s = new LibVBANext.MemoryAreas(); - var l = MemoryDomain.Endian.Little; - LibVBANext.GetMemoryAreas(Core, s); - - mm.Add(new MemoryDomainIntPtr("IWRAM", l, s.iwram, 32 * 1024, true, 4)); - mm.Add(new MemoryDomainIntPtr("EWRAM", l, s.ewram, 256 * 1024, true, 4)); - mm.Add(new MemoryDomainIntPtr("BIOS", l, s.bios, 16 * 1024, false, 4)); - mm.Add(new MemoryDomainIntPtr("PALRAM", l, s.palram, 1024, false, 4)); - mm.Add(new MemoryDomainIntPtr("VRAM", l, s.vram, 96 * 1024, true, 4)); - mm.Add(new MemoryDomainIntPtr("OAM", l, s.oam, 1024, true, 4)); - - mm.Add(new MemoryDomainIntPtr("ROM", l, s.rom, 32 * 1024 * 1024, true, 4)); - - mm.Add(new MemoryDomainIntPtr("SRAM", l, s.sram, s.sram_size, true, 4)); - - mm.Add(new MemoryDomainDelegate("System Bus", 0x10000000, l, - delegate(long addr) - { - if (addr < 0 || addr >= 0x10000000) - { - throw new ArgumentOutOfRangeException(); - } - - return LibVBANext.SystemBusRead(Core, (int)addr); - }, - delegate(long addr, byte val) - { - if (addr < 0 || addr >= 0x10000000) - { - throw new ArgumentOutOfRangeException(); - } - - LibVBANext.SystemBusWrite(Core, (int)addr, val); - }, 4)); - - // special combined ram memory domain - { - var ew = mm[1]; - var iw = mm[0]; - MemoryDomain cr = new MemoryDomainDelegate("Combined WRAM", (256 + 32) * 1024, MemoryDomain.Endian.Little, - delegate(long addr) - { - if (addr < 0 || addr >= (256 + 32) * 1024) - throw new IndexOutOfRangeException(); - if (addr >= 256 * 1024) - return iw.PeekByte(addr & 32767); - else - return ew.PeekByte(addr); - }, - delegate(long addr, byte val) - { - if (addr < 0 || addr >= (256 + 32) * 1024) - throw new IndexOutOfRangeException(); - if (addr >= 256 * 1024) - iw.PokeByte(addr & 32767, val); - else - ew.PokeByte(addr, val); - }, 4); - mm.Add(cr); - } - - _memoryDomains = new MemoryDomainList(mm); - (ServiceProvider as BasicServiceProvider).Register(_memoryDomains); - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.ISaveRam.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.ISaveRam.cs deleted file mode 100644 index 0f4feb4ac7..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.ISaveRam.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class VBANext : ISaveRam - { - public bool SaveRamModified => LibVBANext.SaveRamSize(Core) != 0; - - public byte[] CloneSaveRam() - { - var data = new byte[LibVBANext.SaveRamSize(Core)]; - if (!LibVBANext.SaveRamSave(Core, data, data.Length)) - { - throw new InvalidOperationException($"{nameof(LibVBANext.SaveRamSave)}() failed!"); - } - - return data; - } - - public void StoreSaveRam(byte[] data) - { - // internally, we try to salvage bad-sized saverams - if (!LibVBANext.SaveRamLoad(Core, data, data.Length)) - { - throw new InvalidOperationException($"{nameof(LibVBANext.SaveRamLoad)}() failed!"); - } - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.ISettings.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.ISettings.cs deleted file mode 100644 index 4e6c6b4065..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.ISettings.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.ComponentModel; - -using BizHawk.Common; -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class VBANext : ISettable - { - public object GetSettings() - { - return null; - } - - public SyncSettings GetSyncSettings() - { - return _syncSettings.Clone(); - } - - public PutSettingsDirtyBits PutSettings(object o) - { - return PutSettingsDirtyBits.None; - } - - public PutSettingsDirtyBits PutSyncSettings(SyncSettings o) - { - bool ret = SyncSettings.NeedsReboot(o, _syncSettings); - _syncSettings = o; - return ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None; - } - - private SyncSettings _syncSettings; - - public class SyncSettings - { - [DisplayName("Skip BIOS")] - [Description("Skips the BIOS intro. A BIOS file is still required.")] - [DefaultValue(true)] - public bool SkipBios { get; set; } - - [DisplayName("RTC Use Real Time")] - [Description("Causes the internal clock to reflect your system clock. Only relevant when a game has an RTC chip. Forced to false for movie recording.")] - [DefaultValue(true)] - public bool RTCUseRealTime { get; set; } - - [DisplayName("RTC Initial Time")] - [Description("The initial time of emulation. Only relevant when a game has an RTC chip and \"RTC Use Real Time\" is false.")] - [DefaultValue(typeof(DateTime), "2010-01-01")] - public DateTime RTCInitialTime { get; set; } - - public enum DayOfWeek - { - Sunday = 0, - Monday, - Tuesday, - Wednesday, - Thursday, - Friday, - Saturday - } - - [DisplayName("RTC Initial Day")] - [Description("The day of the week to go with \"RTC Initial Time\". Due to peculiarities in the RTC chip, this can be set indepedently of the year, month, and day of month.")] - [DefaultValue(DayOfWeek.Friday)] - public DayOfWeek RTCInitialDay { get; set; } - - public SyncSettings() - { - SettingsUtil.SetDefaultValues(this); - } - - public static bool NeedsReboot(SyncSettings x, SyncSettings y) - { - return !DeepEquality.DeepEquals(x, y); - } - - public SyncSettings Clone() - { - return (SyncSettings)MemberwiseClone(); - } - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.ISoundProvider.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.ISoundProvider.cs deleted file mode 100644 index 02f8b301e9..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.ISoundProvider.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class VBANext : ISoundProvider - { - private readonly short[] _soundbuff = new short[2048]; - private int _numsamp; - - public void GetSamplesSync(out short[] samples, out int nsamp) - { - samples = _soundbuff; - nsamp = _numsamp; - } - - public void DiscardSamples() - { - } - - public bool CanProvideAsync => false; - - public void SetSyncMode(SyncSoundMode mode) - { - if (mode == SyncSoundMode.Async) - { - throw new NotSupportedException("Async mode is not supported."); - } - } - - public SyncSoundMode SyncMode => SyncSoundMode.Sync; - - public void GetSamplesAsync(short[] samples) - { - throw new InvalidOperationException("Async mode is not supported."); - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IStatable.cs deleted file mode 100644 index a2d8d36355..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IStatable.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.IO; -using Newtonsoft.Json; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class VBANext : ITextStatable - { - public void SaveStateText(TextWriter writer) - { - var s = new TextState(); - s.Prepare(); - var ff = s.GetFunctionPointersSave(); - LibVBANext.TxtStateSave(Core, ref ff); - s.ExtraData.IsLagFrame = IsLagFrame; - s.ExtraData.LagCount = LagCount; - s.ExtraData.Frame = Frame; - - ser.Serialize(writer, s); - } - - public void LoadStateText(TextReader reader) - { - var s = (TextState)ser.Deserialize(reader, typeof(TextState)); - s.Prepare(); - var ff = s.GetFunctionPointersLoad(); - LibVBANext.TxtStateLoad(Core, ref ff); - IsLagFrame = s.ExtraData.IsLagFrame; - LagCount = s.ExtraData.LagCount; - Frame = s.ExtraData.Frame; - } - - public void SaveStateBinary(BinaryWriter writer) - { - if (!LibVBANext.BinStateSave(Core, _savebuff, _savebuff.Length)) - throw new InvalidOperationException($"Core's {nameof(LibVBANext.BinStateSave)}() returned false!"); - writer.Write(_savebuff.Length); - writer.Write(_savebuff); - - // other variables - writer.Write(IsLagFrame); - writer.Write(LagCount); - writer.Write(Frame); - } - - public void LoadStateBinary(BinaryReader reader) - { - int length = reader.ReadInt32(); - if (length != _savebuff.Length) - throw new InvalidOperationException("Save buffer size mismatch!"); - reader.Read(_savebuff, 0, length); - if (!LibVBANext.BinStateLoad(Core, _savebuff, _savebuff.Length)) - throw new InvalidOperationException($"Core's {nameof(LibVBANext.BinStateLoad)}() returned false!"); - - // other variables - IsLagFrame = reader.ReadBoolean(); - LagCount = reader.ReadInt32(); - Frame = reader.ReadInt32(); - } - - public byte[] SaveStateBinary() - { - var ms = new MemoryStream(_savebuff2, true); - var bw = new BinaryWriter(ms); - SaveStateBinary(bw); - bw.Flush(); - if (ms.Position != _savebuff2.Length) - throw new InvalidOperationException(); - ms.Close(); - return _savebuff2; - } - - private JsonSerializer ser = new JsonSerializer { Formatting = Formatting.Indented }; - private readonly byte[] _savebuff; - private readonly byte[] _savebuff2; - - private class TextStateData - { - public int Frame; - public int LagCount; - public bool IsLagFrame; - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IVideoProvider.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IVideoProvider.cs deleted file mode 100644 index 049cb587ec..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.IVideoProvider.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; - -using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Nintendo.Gameboy; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class VBANext : IVideoProvider - { - public int VirtualWidth => 240; - public int VirtualHeight => 160; - public int BufferWidth => 240; - public int BufferHeight => 160; - - public int BackgroundColor => unchecked((int)0xff000000); - - public int[] GetVideoBuffer() - { - return _videobuff; - } - - public int VsyncNumerator => 262144; - - public int VsyncDenominator => 4389; - - private readonly int[] _videobuff = new int[240 * 160]; - private readonly int[] _videopalette = new int[65536]; - - private void SetupColors() - { - int[] tmp = GBColors.GetLut(GBColors.ColorType.vivid); - - // reorder - for (int i = 0; i < 32768; i++) - { - int j = i & 0x3e0 | (i & 0x1f) << 10 | i >> 10 & 0x1f; - _videopalette[i] = tmp[j]; - } - - // duplicate - Array.Copy(_videopalette, 0, _videopalette, 32768, 32768); - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs deleted file mode 100644 index a2de55bb37..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBANext.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using System.Linq; -using System.Text; - -using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Components.ARM; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - [Core(CoreNames.VbaNext, "many authors", true, true, "cd508312a29ed8c29dacac1b11c2dce56c338a54", "https://github.com/libretro/vba-next", false)] - [ServiceNotApplicable(new[] { typeof(IDriveLight), typeof(IRegionable) })] - public partial class VBANext : IEmulator, IVideoProvider, ISoundProvider, IInputPollable, - IGBAGPUViewable, ISaveRam, IStatable, IDebuggable, ISettable - { - [CoreConstructor("GBA")] - public VBANext(byte[] file, CoreComm comm, GameInfo game, bool deterministic, object syncsettings) - { - var ser = new BasicServiceProvider(this); - ser.Register(new ArmV4Disassembler()); - ServiceProvider = ser; - - byte[] biosfile = comm.CoreFileProvider.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory."); - if (file.Length > 32 * 1024 * 1024) - throw new ArgumentException("ROM is too big to be a GBA ROM!"); - if (biosfile.Length != 16 * 1024) - throw new ArgumentException("BIOS file is not exactly 16K!"); - - var FES = new LibVBANext.FrontEndSettings - { - saveType = (LibVBANext.FrontEndSettings.SaveType)game.GetInt("saveType", 0), - flashSize = (LibVBANext.FrontEndSettings.FlashSize)game.GetInt("flashSize", 0x10000), - enableRtc = game.GetInt("rtcEnabled", 0) != 0, - mirroringEnable = game.GetInt("mirroringEnabled", 0) != 0 - }; - Console.WriteLine("GameDB loaded settings: saveType={0}, flashSize={1}, rtcEnabled={2}, mirroringEnabled={3}", - FES.saveType, FES.flashSize, FES.enableRtc, FES.mirroringEnable); - - _syncSettings = (SyncSettings)syncsettings ?? new SyncSettings(); - DeterministicEmulation = deterministic; - - FES.skipBios = _syncSettings.SkipBios; - FES.RTCUseRealTime = _syncSettings.RTCUseRealTime; - FES.RTCwday = (int)_syncSettings.RTCInitialDay; - FES.RTCyear = _syncSettings.RTCInitialTime.Year % 100; - FES.RTCmonth = _syncSettings.RTCInitialTime.Month - 1; - FES.RTCmday = _syncSettings.RTCInitialTime.Day; - FES.RTChour = _syncSettings.RTCInitialTime.Hour; - FES.RTCmin = _syncSettings.RTCInitialTime.Minute; - FES.RTCsec = _syncSettings.RTCInitialTime.Second; - if (DeterministicEmulation) - { - // FES.skipBios = false; // this is OK; it is deterministic and probably accurate - FES.RTCUseRealTime = false; - } - - Core = LibVBANext.Create(); - if (Core == IntPtr.Zero) - throw new InvalidOperationException($"{nameof(LibVBANext.Create)}() returned nullptr!"); - try - { - if (!LibVBANext.LoadRom(Core, file, (uint)file.Length, biosfile, (uint)biosfile.Length, FES)) - throw new InvalidOperationException($"{nameof(LibVBANext.LoadRom)}() returned false!"); - - Tracer = new TraceBuffer() - { - Header = "ARM7: PC, machine code, mnemonic, operands, registers (r0-r16)" - }; - ser.Register(Tracer); - - GameCode = Encoding.ASCII.GetString(file, 0xac, 4); - Console.WriteLine("Game code \"{0}\"", GameCode); - - _savebuff = new byte[LibVBANext.BinStateSize(Core)]; - _savebuff2 = new byte[_savebuff.Length + 13]; - InitMemoryDomains(); - InitRegisters(); - InitCallbacks(); - - // todo: hook me up as a setting - SetupColors(); - } - catch - { - Dispose(); - throw; - } - } - - IntPtr Core; - - public IEmulatorServiceProvider ServiceProvider { get; } - - public bool FrameAdvance(IController controller, bool render, bool rendersound = true) - { - Frame++; - - if (controller.IsPressed("Power")) - LibVBANext.Reset(Core); - - SyncTraceCallback(); - - IsLagFrame = LibVBANext.FrameAdvance(Core, GetButtons(controller), _videobuff, _soundbuff, out _numsamp, _videopalette); - - if (IsLagFrame) - LagCount++; - - return true; - } - - public int Frame { get; private set; } - public int LagCount { get; set; } - public bool IsLagFrame { get; set; } - - private ITraceable Tracer { get; set; } - - public string SystemId => "GBA"; - - public bool DeterministicEmulation { get; } - - public void ResetCounters() - { - Frame = 0; - LagCount = 0; - IsLagFrame = false; - } - - /// - /// set in the ROM internal header - /// - public string GameCode { get; } - - public void Dispose() - { - if (Core != IntPtr.Zero) - { - LibVBANext.Destroy(Core); - Core = IntPtr.Zero; - } - } - - #region Debugging - - LibVBANext.StandardCallback padcb; - LibVBANext.AddressCallback fetchcb; - LibVBANext.AddressCallback readcb; - LibVBANext.AddressCallback writecb; - LibVBANext.TraceCallback tracecb; - - private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); - public IInputCallbackSystem InputCallbacks => _inputCallbacks; - - TraceInfo Trace(uint addr, uint opcode) - { - return new TraceInfo - { - Disassembly = $"{addr:X8}: {opcode:X8} {Darm.DisassembleStuff(addr, opcode)}".PadRight(54), - RegisterInfo = regs.TraceString() - }; - } - - void InitCallbacks() - { - padcb = new LibVBANext.StandardCallback(() => InputCallbacks.Call()); - fetchcb = new LibVBANext.AddressCallback((addr) => { - if (MemoryCallbacks.HasExecutes) - { - uint flags = (uint)MemoryCallbackFlags.AccessExecute; - MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus"); - } - }); - readcb = new LibVBANext.AddressCallback((addr) => - { - if (MemoryCallbacks.HasReads) - { - uint flags = (uint)MemoryCallbackFlags.AccessRead; - MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus"); - } - }); - writecb = new LibVBANext.AddressCallback((addr) => - { - if (MemoryCallbacks.HasWrites) - { - uint flags = (uint)MemoryCallbackFlags.AccessWrite; - MemoryCallbacks.CallMemoryCallbacks(addr, 0, flags, "System Bus"); - } - }); - tracecb = new LibVBANext.TraceCallback((addr, opcode) => Tracer.Put(Trace(addr, opcode))); - _inputCallbacks.ActiveChanged += SyncPadCallback; - _memorycallbacks.ActiveChanged += SyncMemoryCallbacks; - } - - void SyncPadCallback() - { - LibVBANext.SetPadCallback(Core, InputCallbacks.Any() ? padcb : null); - } - - void SyncMemoryCallbacks() - { - LibVBANext.SetFetchCallback(Core, MemoryCallbacks.HasExecutes ? fetchcb : null); - LibVBANext.SetReadCallback(Core, MemoryCallbacks.HasReads ? readcb : null); - LibVBANext.SetWriteCallback(Core, MemoryCallbacks.HasWrites ? writecb : null); - } - - void SyncTraceCallback() - { - LibVBANext.SetTraceCallback(Core, Tracer.Enabled ? tracecb : null); - } - - VBARegisterHelper regs; - - void InitRegisters() - { - regs = new VBARegisterHelper(Core); - } - - #endregion - - #region Controller - - public ControllerDefinition ControllerDefinition => GBA.GBAController; - - public static LibVBANext.Buttons GetButtons(IController c) - { - LibVBANext.Buttons ret = 0; - foreach (string s in Enum.GetNames(typeof(LibVBANext.Buttons))) - { - if (c.IsPressed(s)) - { - ret |= (LibVBANext.Buttons)Enum.Parse(typeof(LibVBANext.Buttons), s); - } - } - return ret; - } - - #endregion - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBARegisterHelper.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBARegisterHelper.cs deleted file mode 100644 index d17c116601..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/VBARegisterHelper.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public unsafe class VBARegisterHelper - { - private readonly IntPtr _origin; - private readonly Dictionary _locs = new Dictionary(); - - public VBARegisterHelper(IntPtr Core) - { - _origin = LibVBANext.GetRegisters(Core); - foreach (var field in typeof(LibVBANext.Registers).GetFields()) - { - var ofs = Marshal.OffsetOf(typeof(LibVBANext.Registers), field.Name); - _locs[field.Name] = IntPtr.Add(_origin, (int)ofs); - } - } - - public int GetRegister(string name) - { - int* p = (int*)_locs[name]; - return *p; - } - - public void SetRegister(string name, int val) - { - int* p = (int*)_locs[name]; - *p = val; - } - - public Dictionary GetAllRegisters() - { - var ret = new Dictionary(); - foreach (var kvp in _locs) - { - ret[kvp.Key] = GetRegister(kvp.Key); - } - - return ret; - } - - public string TraceString() - { - var sb = new StringBuilder(); - int* p = (int*)_origin; - for (int i = 0; i < 17; i++) - { - sb.Append($"r{i}:{p[i]:X8}"); - if (i != 16) - { - sb.Append(' '); - } - } - - return sb.ToString(); - } - } -} diff --git a/BizHawk.Emulation.Cores/CoreNames.cs b/BizHawk.Emulation.Cores/CoreNames.cs index fc2dfbbc86..a8c9e907c0 100644 --- a/BizHawk.Emulation.Cores/CoreNames.cs +++ b/BizHawk.Emulation.Cores/CoreNames.cs @@ -15,7 +15,6 @@ namespace BizHawk.Emulation.Cores public const string Snes9X = "Snes9x"; public const string Bsnes = "BSNES"; public const string Mgba = "mGBA"; - public const string VbaNext = "VBA-Next"; public const string GbHawk = "GBHawk"; public const string Gambatte = "Gambatte"; public const string SubGbHawk = "SubGBHawk"; diff --git a/output/dll/libvbanext.dll b/output/dll/libvbanext.dll deleted file mode 100644 index 3a860e5bb9..0000000000 Binary files a/output/dll/libvbanext.dll and /dev/null differ diff --git a/vbanext/constarrays.h b/vbanext/constarrays.h deleted file mode 100644 index 4e87a6e33e..0000000000 --- a/vbanext/constarrays.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef CONSTARRAYS_H -#define CONSTARRAYS_H - -static float const apu_vols [4] = { -0.25f, -0.5f, -1.0f, -0.25f }; - -static const int daysinmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -static const int table [0x40] = -{ - 0xFF10, 0,0xFF11,0xFF12,0xFF13,0xFF14, 0, 0, - 0xFF16,0xFF17, 0, 0,0xFF18,0xFF19, 0, 0, - 0xFF1A, 0,0xFF1B,0xFF1C,0xFF1D,0xFF1E, 0, 0, - 0xFF20,0xFF21, 0, 0,0xFF22,0xFF23, 0, 0, - 0xFF24,0xFF25, 0, 0,0xFF26, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37, - 0xFF38,0xFF39,0xFF3A,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F, -}; - -static const uint32_t TIMER_TICKS[4] = {0, 6, 8, 10}; - -static const uint8_t gamepakRamWaitState[4] = { 4, 3, 2, 8 }; - -static const uint32_t objTilesAddress [3] = {0x010000, 0x014000, 0x014000}; - -static const u32 AlphaClampLUT[64] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F -}; - -static const u32 map_sizes_rot[] = { 128, 256, 512, 1024 }; - -static const u32 map_widths[] = { 256, 512, 256, 512 }; -static const u32 map_heights[] = { 256, 256, 512, 512 }; - - -static const int coeff[32] = {0,1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16}; - - -static const uint8_t memoryWait_init[16] = - { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0 }; -static const uint8_t memoryWaitSeq_init[16] = - { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4, 0 }; -static const uint8_t memoryWait32_init[16] = - { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 4, 0 }; -static const uint8_t memoryWaitSeq32_init[16] = - { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 4, 0 }; - -#endif diff --git a/vbanext/instance.cpp b/vbanext/instance.cpp deleted file mode 100644 index 14ebc4c208..0000000000 --- a/vbanext/instance.cpp +++ /dev/null @@ -1,13699 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include - -#define LSB_FIRST -#ifdef SPEEDHAX -#error NO SPEEDHAX -#endif -#define HAVE_HLE_BIOS - -#include "port.h" - -#include "instance.h" - -#include "sound_blargg.h" - -#include "constarrays.h" - -#include "newstate.h" - -#define INLINE - -class Gigazoid -{ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// BEGIN MEMORY.CPP -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/*============================================================ - FLASH -============================================================ */ - - -#define FLASH_READ_ARRAY 0 -#define FLASH_CMD_1 1 -#define FLASH_CMD_2 2 -#define FLASH_AUTOSELECT 3 -#define FLASH_CMD_3 4 -#define FLASH_CMD_4 5 -#define FLASH_CMD_5 6 -#define FLASH_ERASE_COMPLETE 7 -#define FLASH_PROGRAM 8 -#define FLASH_SETBANK 9 - -uint8_t flashSaveMemory[FLASH_128K_SZ]; - -int flashState; // = FLASH_READ_ARRAY; -int flashReadState; // = FLASH_READ_ARRAY; -int flashSize; // = 0x10000; -int flashDeviceID; // = 0x1b; -int flashManufacturerID; // = 0x32; -int flashBank; // = 0; - -void flashInit (void) -{ - memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory)); -} - -void flashReset() -{ - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - flashBank = 0; -} - -uint8_t flashRead(uint32_t address) -{ - address &= 0xFFFF; - - switch(flashReadState) { - case FLASH_READ_ARRAY: - return flashSaveMemory[(flashBank << 16) + address]; - case FLASH_AUTOSELECT: - switch(address & 0xFF) - { - case 0: - // manufacturer ID - return flashManufacturerID; - case 1: - // device ID - return flashDeviceID; - } - break; - case FLASH_ERASE_COMPLETE: - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - return 0xFF; - }; - return 0; -} - -void flashSaveDecide(uint32_t address, uint8_t byte) -{ - if (address == 0x0e005555) - cpuSaveGameFunc = &Gigazoid::flashWrite; - else - cpuSaveGameFunc = &Gigazoid::sramWrite; - - (this->*cpuSaveGameFunc)(address, byte); -} - -void flashWrite(uint32_t address, uint8_t byte) -{ - address &= 0xFFFF; - switch(flashState) { - case FLASH_READ_ARRAY: - if(address == 0x5555 && byte == 0xAA) - flashState = FLASH_CMD_1; - break; - case FLASH_CMD_1: - if(address == 0x2AAA && byte == 0x55) - flashState = FLASH_CMD_2; - else - flashState = FLASH_READ_ARRAY; - break; - case FLASH_CMD_2: - if(address == 0x5555) { - if(byte == 0x90) { - flashState = FLASH_AUTOSELECT; - flashReadState = FLASH_AUTOSELECT; - } else if(byte == 0x80) { - flashState = FLASH_CMD_3; - } else if(byte == 0xF0) { - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - } else if(byte == 0xA0) { - flashState = FLASH_PROGRAM; - } else if(byte == 0xB0 && flashSize == 0x20000) { - flashState = FLASH_SETBANK; - } else { - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - } - } else { - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - } - break; - case FLASH_CMD_3: - if(address == 0x5555 && byte == 0xAA) { - flashState = FLASH_CMD_4; - } else { - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - } - break; - case FLASH_CMD_4: - if(address == 0x2AAA && byte == 0x55) { - flashState = FLASH_CMD_5; - } else { - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - } - break; - case FLASH_CMD_5: - if(byte == 0x30) { - // SECTOR ERASE - memset(&flashSaveMemory[(flashBank << 16) + (address & 0xF000)], - 0, - 0x1000); - flashReadState = FLASH_ERASE_COMPLETE; - } else if(byte == 0x10) { - // CHIP ERASE - memset(flashSaveMemory, 0, flashSize); - flashReadState = FLASH_ERASE_COMPLETE; - } else { - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - } - break; - case FLASH_AUTOSELECT: - if(byte == 0xF0) { - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - } else if(address == 0x5555 && byte == 0xAA) - flashState = FLASH_CMD_1; - else { - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - } - break; - case FLASH_PROGRAM: - flashSaveMemory[(flashBank<<16)+address] = byte; - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - break; - case FLASH_SETBANK: - if(address == 0) { - flashBank = (byte & 1); - } - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - break; - } -} - -/*============================================================ - EEPROM -============================================================ */ -int eepromMode; // = EEPROM_IDLE; -int eepromByte; // = 0; -int eepromBits; // = 0; -int eepromAddress; // = 0; - -u8 eepromData[0x2000]; - -u8 eepromBuffer[16]; -bool eepromInUse; // = false; -int eepromSize; // = 512; - -void eepromInit (void) -{ - memset(eepromData, 255, sizeof(eepromData)); -} - -void eepromReset (void) -{ - eepromMode = EEPROM_IDLE; - eepromByte = 0; - eepromBits = 0; - eepromAddress = 0; - eepromInUse = false; - eepromSize = 512; -} - -int eepromRead (void) -{ - switch(eepromMode) - { - case EEPROM_IDLE: - case EEPROM_READADDRESS: - case EEPROM_WRITEDATA: - return 1; - case EEPROM_READDATA: - { - eepromBits++; - if(eepromBits == 4) { - eepromMode = EEPROM_READDATA2; - eepromBits = 0; - eepromByte = 0; - } - return 0; - } - case EEPROM_READDATA2: - { - int data = 0; - int address = eepromAddress << 3; - int mask = 1 << (7 - (eepromBits & 7)); - data = (eepromData[address+eepromByte] & mask) ? 1 : 0; - eepromBits++; - if((eepromBits & 7) == 0) - eepromByte++; - if(eepromBits == 0x40) - eepromMode = EEPROM_IDLE; - return data; - } - default: - return 0; - } - return 1; -} - -void eepromWrite(u8 value) -{ - if(cpuDmaCount == 0) - return; - int bit = value & 1; - switch(eepromMode) { - case EEPROM_IDLE: - eepromByte = 0; - eepromBits = 1; - eepromBuffer[eepromByte] = bit; - eepromMode = EEPROM_READADDRESS; - break; - case EEPROM_READADDRESS: - eepromBuffer[eepromByte] <<= 1; - eepromBuffer[eepromByte] |= bit; - eepromBits++; - if((eepromBits & 7) == 0) { - eepromByte++; - } - if(cpuDmaCount == 0x11 || cpuDmaCount == 0x51) { - if(eepromBits == 0x11) { - eepromInUse = true; - eepromSize = 0x2000; - eepromAddress = ((eepromBuffer[0] & 0x3F) << 8) | - ((eepromBuffer[1] & 0xFF)); - if(!(eepromBuffer[0] & 0x40)) { - eepromBuffer[0] = bit; - eepromBits = 1; - eepromByte = 0; - eepromMode = EEPROM_WRITEDATA; - } else { - eepromMode = EEPROM_READDATA; - eepromByte = 0; - eepromBits = 0; - } - } - } else { - if(eepromBits == 9) { - eepromInUse = true; - eepromAddress = (eepromBuffer[0] & 0x3F); - if(!(eepromBuffer[0] & 0x40)) { - eepromBuffer[0] = bit; - eepromBits = 1; - eepromByte = 0; - eepromMode = EEPROM_WRITEDATA; - } else { - eepromMode = EEPROM_READDATA; - eepromByte = 0; - eepromBits = 0; - } - } - } - break; - case EEPROM_READDATA: - case EEPROM_READDATA2: - // should we reset here? - eepromMode = EEPROM_IDLE; - break; - case EEPROM_WRITEDATA: - eepromBuffer[eepromByte] <<= 1; - eepromBuffer[eepromByte] |= bit; - eepromBits++; - if((eepromBits & 7) == 0) - eepromByte++; - if(eepromBits == 0x40) - { - eepromInUse = true; - // write data; - for(int i = 0; i < 8; i++) - eepromData[(eepromAddress << 3) + i] = eepromBuffer[i]; - } - else if(eepromBits == 0x41) - { - eepromMode = EEPROM_IDLE; - eepromByte = 0; - eepromBits = 0; - } - break; - } -} - -/*============================================================ - SRAM -============================================================ */ - -u8 sramRead(u32 address) -{ - return flashSaveMemory[address & 0xFFFF]; -} - -void sramWrite(u32 address, u8 byte) -{ - flashSaveMemory[address & 0xFFFF] = byte; -} - -void dummyWrite(u32 address, u8 byte) -{ -} - -/*============================================================ - RTC -============================================================ */ - -#define IDLE 0 -#define COMMAND 1 -#define DATA 2 -#define READDATA 3 - -typedef struct -{ - u8 byte0; - u8 byte1; - u8 byte2; - u8 command; - int dataLen; - int bits; - int state; - u8 data[12]; -} RTCCLOCKDATA; - -RTCCLOCKDATA rtcClockData; -bool rtcEnabled; // = false; - -u16 rtcRead(u32 address) -{ - switch(address) - { - case 0x80000c8: - return rtcClockData.byte2; - case 0x80000c6: - return rtcClockData.byte1; - case 0x80000c4: - return rtcClockData.byte0; - default: - return 0; - } -} - -static u8 toBCD(u8 value) -{ - value = value % 100; - int l = value % 10; - int h = value / 10; - return h * 16 + l; -} - -bool rtcWrite(u32 address, u16 value) -{ - if(!rtcEnabled) - return false; - - if(address == 0x80000c8) - rtcClockData.byte2 = (u8)value; // enable ? - else if(address == 0x80000c6) - rtcClockData.byte1 = (u8)value; // read/write - else if(address == 0x80000c4) - { - if(rtcClockData.byte2 & 1) // enable - { - if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) - { - rtcClockData.state = COMMAND; - rtcClockData.bits = 0; - rtcClockData.command = 0; - } - else if(!(rtcClockData.byte0 & 1) && (value & 1)) - { // bit transfer - rtcClockData.byte0 = (u8)value; - switch(rtcClockData.state) - { - case COMMAND: - rtcClockData.command |= ((value & 2) >> 1) << (7-rtcClockData.bits); - rtcClockData.bits++; - if(rtcClockData.bits == 8) - { - rtcClockData.bits = 0; - switch(rtcClockData.command) - { - case 0x60: - // not sure what this command does but it doesn't take parameters - // maybe it is a reset or stop - rtcClockData.state = IDLE; - rtcClockData.bits = 0; - break; - case 0x62: - // this sets the control state but not sure what those values are - rtcClockData.state = READDATA; - rtcClockData.dataLen = 1; - break; - case 0x63: - rtcClockData.dataLen = 1; - rtcClockData.data[0] = 0x40; - rtcClockData.state = DATA; - break; - case 0x64: - break; - case 0x65: - { - tm newtime; - GetTime(newtime); - rtcClockData.dataLen = 7; - rtcClockData.data[0] = toBCD(newtime.tm_year); - rtcClockData.data[1] = toBCD(newtime.tm_mon+1); - rtcClockData.data[2] = toBCD(newtime.tm_mday); - rtcClockData.data[3] = toBCD(newtime.tm_wday); - rtcClockData.data[4] = toBCD(newtime.tm_hour); - rtcClockData.data[5] = toBCD(newtime.tm_min); - rtcClockData.data[6] = toBCD(newtime.tm_sec); - rtcClockData.state = DATA; - } - break; - case 0x67: - { - tm newtime; - GetTime(newtime); - rtcClockData.dataLen = 3; - rtcClockData.data[0] = toBCD(newtime.tm_hour); - rtcClockData.data[1] = toBCD(newtime.tm_min); - rtcClockData.data[2] = toBCD(newtime.tm_sec); - rtcClockData.state = DATA; - } - break; - default: - //systemMessage(0, "Unknown RTC command %02x", rtcClockData.command); - rtcClockData.state = IDLE; - break; - } - } - break; - case DATA: - if(rtcClockData.byte1 & 2) - { - } - else - { - rtcClockData.byte0 = (rtcClockData.byte0 & ~2) | - ((rtcClockData.data[rtcClockData.bits >> 3] >> - (rtcClockData.bits & 7)) & 1)*2; - rtcClockData.bits++; - if(rtcClockData.bits == 8*rtcClockData.dataLen) - { - rtcClockData.bits = 0; - rtcClockData.state = IDLE; - } - } - break; - case READDATA: - if(!(rtcClockData.byte1 & 2)) { - } else { - rtcClockData.data[rtcClockData.bits >> 3] = - (rtcClockData.data[rtcClockData.bits >> 3] >> 1) | - ((value << 6) & 128); - rtcClockData.bits++; - if(rtcClockData.bits == 8*rtcClockData.dataLen) { - rtcClockData.bits = 0; - rtcClockData.state = IDLE; - } - } - break; - default: - break; - } - } else - rtcClockData.byte0 = (u8)value; - } - } - return true; -} - -void rtcReset (void) -{ - memset(&rtcClockData, 0, sizeof(rtcClockData)); - - rtcClockData.byte0 = 0; - rtcClockData.byte1 = 0; - rtcClockData.byte2 = 0; - rtcClockData.command = 0; - rtcClockData.dataLen = 0; - rtcClockData.bits = 0; - rtcClockData.state = IDLE; -} - -// guarantees predictable results regardless of stdlib -// could be modified later to better match internal quirks of -// the RTC chip actually used -struct -{ - int year; // 00..99 - int month; // 00..11 - int mday; // 01..31 - int wday; // 00..06 - int hour; // 00..23 - int min; // 00..59 - int sec; // 00..59 - - templatevoid SyncState(NewState *ns) - { - NSS(year); - NSS(month); - NSS(mday); - NSS(wday); - NSS(hour); - NSS(min); - NSS(sec); - } - -private: - int DaysInMonth() - { - // gba rtc doesn't understand 100/400 exceptions - int result = daysinmonth[month]; - if (month == 1 && year % 4 == 0) - result++; - return result; - } - -public: - void Increment() - { - sec++; - if (sec >= 60) - { - sec = 0; - min++; - if (min >= 60) - { - min = 0; - hour++; - if (hour >= 24) - { - hour = 0; - wday++; - if (wday >= 7) - wday = 0; - mday++; - if (mday >= DaysInMonth()) - { - mday = 1; - month++; - if (month >= 12) - { - month = 0; - year++; - if (year >= 100) - year = 0; - } - } - } - } - } - } - -} rtcInternalTime; - -void GetTime(tm ×) -{ - if (RTCUseRealTime) - { - time_t t = time(nullptr); - #if defined _MSC_VER - gmtime_s(×, &t); - #elif defined __MINGW32__ - tm *tmp = gmtime(&t); - times = *tmp; - #elif defined __GNUC__ - gmtime_r(&t, ×); - #endif - } - else - { - times.tm_hour = rtcInternalTime.hour; - times.tm_mday = rtcInternalTime.mday; - times.tm_min = rtcInternalTime.min; - times.tm_mon = rtcInternalTime.month; - times.tm_sec = rtcInternalTime.sec; - times.tm_wday = rtcInternalTime.wday; - times.tm_year = rtcInternalTime.year; - } -} - -int RTCTicks; -bool RTCUseRealTime; - -void AdvanceRTC(int ticks) -{ - RTCTicks += ticks; - while (RTCTicks >= 16777216) - { - RTCTicks -= 16777216; - rtcInternalTime.Increment(); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// END MEMORY.CPP -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// BEGIN SOUND.CPP -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#define NR10 0x60 -#define NR11 0x62 -#define NR12 0x63 -#define NR13 0x64 -#define NR14 0x65 -#define NR21 0x68 -#define NR22 0x69 -#define NR23 0x6c -#define NR24 0x6d -#define NR30 0x70 -#define NR31 0x72 -#define NR32 0x73 -#define NR33 0x74 -#define NR34 0x75 -#define NR41 0x78 -#define NR42 0x79 -#define NR43 0x7c -#define NR44 0x7d -#define NR50 0x80 -#define NR51 0x81 -#define NR52 0x84 - -/* 1/100th of a second */ -//#define SOUND_CLOCK_TICKS_ 167772 -#define SOUNDVOLUME 0.5f -#define SOUNDVOLUME_ -1 - -/*============================================================ - CLASS DECLS -============================================================ */ - -class Blip_Buffer -{ - public: - templatevoid SyncState(NewState *ns) - { - NSS(clock_rate_); - NSS(length_); - NSS(sample_rate_); - NSS(factor_); - NSS(offset_); - // int32_t *buffer_; shouldn't need to save - NSS(buffer_size_); - NSS(reader_accum_); - - } - - Blip_Buffer::Blip_Buffer() - { - factor_ = INT_MAX; - buffer_ = 0; - buffer_size_ = 0; - sample_rate_ = 0; - clock_rate_ = 0; - length_ = 0; - - clear(); - } - - Blip_Buffer::~Blip_Buffer() - { - free(buffer_); - } - - void Blip_Buffer::clear( void) - { - offset_ = 0; - reader_accum_ = 0; - if (buffer_) - memset( buffer_, 0, (buffer_size_ + BLIP_BUFFER_EXTRA_) * sizeof (int32_t) ); - } - - const char * Blip_Buffer::set_sample_rate( long new_rate, int msec ) - { - /* start with maximum length that resampled time can represent*/ - long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - BLIP_BUFFER_EXTRA_ - 64; - if ( msec != 0) - { - long s = (new_rate * (msec + 1) + 999) / 1000; - if ( s < new_size ) - new_size = s; - } - - if ( buffer_size_ != new_size ) - { - void* p = realloc( buffer_, (new_size + BLIP_BUFFER_EXTRA_) * sizeof *buffer_ ); - if ( !p ) - return "Out of memory"; - buffer_ = (int32_t *) p; - } - - buffer_size_ = new_size; - - /* update things based on the sample rate*/ - sample_rate_ = new_rate; - length_ = new_size * 1000 / new_rate - 1; - - /* update these since they depend on sample rate*/ - if ( clock_rate_ ) - factor_ = clock_rate_factor( clock_rate_); - - clear(); - - return 0; - } - - /* Sets number of source time units per second */ - - uint32_t Blip_Buffer::clock_rate_factor( long rate ) const - { - double ratio = (double) sample_rate_ / rate; - int32_t factor = (int32_t) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 ); - return (uint32_t) factor; - } - long clock_rate_; - int length_; /* Length of buffer in milliseconds*/ - long sample_rate_; /* Current output sample rate*/ - uint32_t factor_; - uint32_t offset_; - int32_t *buffer_; - int32_t buffer_size_; - int32_t reader_accum_; - private: - Blip_Buffer( const Blip_Buffer& ); - Blip_Buffer& operator = ( const Blip_Buffer& ); -}; - -class Blip_Synth -{ - public: - int delta_factor; - - templatevoid SyncState(NewState *ns) - { - NSS(delta_factor); - } - - void volume( double v ) { delta_factor = int ((v * 1.0) * (1L << BLIP_SAMPLE_BITS) + 0.5); } - INLINE void Blip_Synth::offset_resampled( uint32_t time, int delta, Blip_Buffer* blip_buf ) const - { - int32_t left, right, phase; - int32_t *buf; - - delta *= delta_factor; - buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY); - phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & BLIP_RES_MIN_ONE); - - left = buf [0] + delta; - - right = (delta >> BLIP_PHASE_BITS) * phase; - - left -= right; - right += buf [1]; - - buf [0] = left; - buf [1] = right; - } - - INLINE void Blip_Synth::offset( int32_t t, int delta, Blip_Buffer* buf ) const - { - offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); - } - void offset_inline( int32_t t, int delta, Blip_Buffer* buf ) const { - offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); - } -}; - -#define TRIGGER_MASK 0x80 -#define LENGTH_ENABLED 0x40 - -#define VOLUME_SHIFT_PLUS_FOUR 6 -#define SIZE20_MASK 0x20 - - - -#define reload_sweep_timer() \ - sweep_delay = (regs [0] & PERIOD_MASK) >> 4; \ - if ( !sweep_delay ) \ - sweep_delay = 8; - -class Gb_Osc -{ - public: - Blip_Buffer* outputs [4]; /* NULL, right, left, center*/ - Blip_Buffer* output; /* where to output sound*/ - uint8_t * regs; /* osc's 5 registers*/ - int mode; /* mode_dmg, mode_cgb, mode_agb*/ - int dac_off_amp; /* amplitude when DAC is off*/ - int last_amp; /* current amplitude in Blip_Buffer*/ - Blip_Synth const* good_synth; - Blip_Synth const* med_synth; - - int delay; /* clocks until frequency timer expires*/ - int length_ctr; /* length counter*/ - unsigned phase; /* waveform phase (or equivalent)*/ - bool enabled; /* internal enabled flag*/ - - templatevoid SyncState(NewState *ns) - { - EBS(output, -1); - EVS(output, outputs[0], 0); - EVS(output, outputs[1], 1); - EVS(output, outputs[2], 2); - EVS(output, outputs[3], 3); - EES(output, nullptr); - - NSS(mode); - NSS(dac_off_amp); - NSS(last_amp); - - NSS(delay); - NSS(length_ctr); - NSS(phase); - NSS(enabled); - } - - void Gb_Osc::clock_length() - { - if ( (regs [4] & LENGTH_ENABLED) && length_ctr ) - { - if ( --length_ctr <= 0 ) - enabled = false; - } - } - void Gb_Osc::reset() - { - output = 0; - last_amp = 0; - delay = 0; - phase = 0; - enabled = false; - } - protected: - INLINE void Gb_Osc::update_amp( int32_t time, int new_amp ) - { - int delta = new_amp - last_amp; - if ( delta ) - { - last_amp = new_amp; - med_synth->offset( time, delta, output ); - } - } - int Gb_Osc::write_trig( int frame_phase, int max_len, int old_data ) - { - int data = regs [4]; - - if ( (frame_phase & 1) && !(old_data & LENGTH_ENABLED) && length_ctr ) - { - if ( (data & LENGTH_ENABLED)) - length_ctr--; - } - - if ( data & TRIGGER_MASK ) - { - enabled = true; - if ( !length_ctr ) - { - length_ctr = max_len; - if ( (frame_phase & 1) && (data & LENGTH_ENABLED) ) - length_ctr--; - } - } - - if ( !length_ctr ) - enabled = false; - - return data & TRIGGER_MASK; - } -}; - -class Gb_Env : public Gb_Osc -{ - public: - int env_delay; - int volume; - bool env_enabled; - - templatevoid SyncState(NewState *ns) - { - Gb_Osc::SyncState(ns); - NSS(env_delay); - NSS(volume); - NSS(env_enabled); - } - - void Gb_Env::clock_envelope() - { - if ( env_enabled && --env_delay <= 0 && reload_env_timer() ) - { - int v = volume + (regs [2] & 0x08 ? +1 : -1); - if ( 0 <= v && v <= 15 ) - volume = v; - else - env_enabled = false; - } - } - bool Gb_Env::write_register( int frame_phase, int reg, int old, int data ) - { - int const max_len = 64; - - switch ( reg ) - { - case 1: - length_ctr = max_len - (data & (max_len - 1)); - break; - - case 2: - if ( !GB_ENV_DAC_ENABLED() ) - enabled = false; - - zombie_volume( old, data ); - - if ( (data & 7) && env_delay == 8 ) - { - env_delay = 1; - clock_envelope(); // TODO: really happens at next length clock - } - break; - - case 4: - if ( write_trig( frame_phase, max_len, old ) ) - { - volume = regs [2] >> 4; - reload_env_timer(); - env_enabled = true; - if ( frame_phase == 7 ) - env_delay++; - if ( !GB_ENV_DAC_ENABLED() ) - enabled = false; - return true; - } - } - return false; - } - - void reset() - { - env_delay = 0; - volume = 0; - Gb_Osc::reset(); - } - private: - INLINE void Gb_Env::zombie_volume( int old, int data ) - { - int v = volume; - - // CGB-05 behavior, very close to AGB behavior as well - if ( (old ^ data) & 8 ) - { - if ( !(old & 8) ) - { - v++; - if ( old & 7 ) - v++; - } - - v = 16 - v; - } - else if ( (old & 0x0F) == 8 ) - v++; - volume = v & 0x0F; - } - INLINE int Gb_Env::reload_env_timer() - { - int raw = regs [2] & 7; - env_delay = (raw ? raw : 8); - return raw; - } -}; - -class Gb_Square : public Gb_Env -{ -public: - templatevoid SyncState(NewState *ns) - { - Gb_Env::SyncState(ns); - } - - bool Gb_Square::write_register( int frame_phase, int reg, int old_data, int data ) - { - bool result = Gb_Env::write_register( frame_phase, reg, old_data, data ); - if ( result ) - delay = (delay & (CLK_MUL_MUL_4 - 1)) + period(); - return result; - } - void Gb_Square::run( int32_t time, int32_t end_time ) - { - /* Calc duty and phase*/ - static unsigned char const duty_offsets [4] = { 1, 1, 3, 7 }; - static unsigned char const duties [4] = { 1, 2, 4, 6 }; - int const duty_code = regs [1] >> 6; - int32_t duty_offset = duty_offsets [duty_code]; - int32_t duty = duties [duty_code]; - /* AGB uses inverted duty*/ - duty_offset -= duty; - duty = 8 - duty; - int ph = (phase + duty_offset) & 7; - - /* Determine what will be generated*/ - int vol = 0; - Blip_Buffer* const out = output; - if ( out ) - { - int amp = dac_off_amp; - if ( GB_ENV_DAC_ENABLED() ) - { - if ( enabled ) - vol = volume; - - amp = -(vol >> 1); - - /* Play inaudible frequencies as constant amplitude*/ - if ( GB_OSC_FREQUENCY() >= 0x7FA && delay < CLK_MUL_MUL_32 ) - { - amp += (vol * duty) >> 3; - vol = 0; - } - - if ( ph < duty ) - { - amp += vol; - vol = -vol; - } - } - update_amp( time, amp ); - } - - /* Generate wave*/ - time += delay; - if ( time < end_time ) - { - int const per = period(); - if ( !vol ) - { - /* Maintain phase when not playing*/ - int count = (end_time - time + per - 1) / per; - ph += count; /* will be masked below*/ - time += (int32_t) count * per; - } - else - { - /* Output amplitude transitions*/ - int delta = vol; - do - { - ph = (ph + 1) & 7; - if ( ph == 0 || ph == duty ) - { - good_synth->offset_inline( time, delta, out ); - delta = -delta; - } - time += per; - } - while ( time < end_time ); - - if ( delta != vol ) - last_amp -= delta; - } - phase = (ph - duty_offset) & 7; - } - delay = time - end_time; - } - - void reset() - { - Gb_Env::reset(); - delay = 0x40000000; /* TODO: something less hacky (never clocked until first trigger)*/ - } - private: - /* Frequency timer period*/ - int period() const { return (2048 - GB_OSC_FREQUENCY()) * (CLK_MUL_MUL_4); } -}; - -class Gb_Sweep_Square : public Gb_Square -{ - public: - int sweep_freq; - int sweep_delay; - bool sweep_enabled; - bool sweep_neg; - - templatevoid SyncState(NewState *ns) - { - Gb_Square::SyncState(ns); - NSS(sweep_freq); - NSS(sweep_delay); - NSS(sweep_enabled); - NSS(sweep_neg); - } - - void Gb_Sweep_Square::clock_sweep() - { - if ( --sweep_delay <= 0 ) - { - reload_sweep_timer(); - if ( sweep_enabled && (regs [0] & PERIOD_MASK) ) - { - calc_sweep( true ); - calc_sweep( false ); - } - } - } - INLINE void Gb_Sweep_Square::write_register( int frame_phase, int reg, int old_data, int data ) - { - if ( reg == 0 && sweep_enabled && sweep_neg && !(data & 0x08) ) - enabled = false; // sweep negate disabled after used - - if ( Gb_Square::write_register( frame_phase, reg, old_data, data ) ) - { - sweep_freq = GB_OSC_FREQUENCY(); - sweep_neg = false; - reload_sweep_timer(); - sweep_enabled = (regs [0] & (PERIOD_MASK | SHIFT_MASK)) != 0; - if ( regs [0] & SHIFT_MASK ) - calc_sweep( false ); - } - } - - void reset() - { - sweep_freq = 0; - sweep_delay = 0; - sweep_enabled = false; - sweep_neg = false; - Gb_Square::reset(); - } - private: - void Gb_Sweep_Square::calc_sweep( bool update ) - { - int shift, delta, freq; - - shift = regs [0] & SHIFT_MASK; - delta = sweep_freq >> shift; - sweep_neg = (regs [0] & 0x08) != 0; - freq = sweep_freq + (sweep_neg ? -delta : delta); - - if ( freq > 0x7FF ) - enabled = false; - else if ( shift && update ) - { - sweep_freq = freq; - - regs [3] = freq & 0xFF; - regs [4] = (regs [4] & ~0x07) | (freq >> 8 & 0x07); - } - } -}; - -class Gb_Noise : public Gb_Env -{ - public: - int divider; /* noise has more complex frequency divider setup*/ - - templatevoid SyncState(NewState *ns) - { - Gb_Env::SyncState(ns); - NSS(divider); - } - - /* Quickly runs LFSR for a large number of clocks. For use when noise is generating*/ - /* no sound.*/ - unsigned run_lfsr( unsigned s, unsigned mask, int count ) - { - /* optimization used in several places:*/ - /* ((s & (1 << b)) << n) ^ ((s & (1 << b)) << (n + 1)) = (s & (1 << b)) * (3 << n)*/ - - if ( mask == 0x4000 ) - { - if ( count >= 32767 ) - count %= 32767; - - /* Convert from Fibonacci to Galois configuration,*/ - /* shifted left 1 bit*/ - s ^= (s & 1) * 0x8000; - - /* Each iteration is equivalent to clocking LFSR 255 times*/ - while ( (count -= 255) > 0 ) - s ^= ((s & 0xE) << 12) ^ ((s & 0xE) << 11) ^ (s >> 3); - count += 255; - - /* Each iteration is equivalent to clocking LFSR 15 times*/ - /* (interesting similarity to single clocking below)*/ - while ( (count -= 15) > 0 ) - s ^= ((s & 2) * (3 << 13)) ^ (s >> 1); - count += 15; - - /* Remaining singles*/ - do{ - --count; - s = ((s & 2) * (3 << 13)) ^ (s >> 1); - }while(count >= 0); - - /* Convert back to Fibonacci configuration*/ - s &= 0x7FFF; - } - else if ( count < 8) - { - /* won't fully replace upper 8 bits, so have to do the unoptimized way*/ - do{ - --count; - s = (s >> 1 | mask) ^ (mask & -((s - 1) & 2)); - }while(count >= 0); - } - else - { - if ( count > 127 ) - { - count %= 127; - if ( !count ) - count = 127; /* must run at least once*/ - } - - /* Need to keep one extra bit of history*/ - s = s << 1 & 0xFF; - - /* Convert from Fibonacci to Galois configuration,*/ - /* shifted left 2 bits*/ - s ^= (s & 2) << 7; - - /* Each iteration is equivalent to clocking LFSR 7 times*/ - /* (interesting similarity to single clocking below)*/ - while ( (count -= 7) > 0 ) - s ^= ((s & 4) * (3 << 5)) ^ (s >> 1); - count += 7; - - /* Remaining singles*/ - while ( --count >= 0 ) - s = ((s & 4) * (3 << 5)) ^ (s >> 1); - - /* Convert back to Fibonacci configuration and*/ - /* repeat last 8 bits above significant 7*/ - s = (s << 7 & 0x7F80) | (s >> 1 & 0x7F); - } - - return s; - } - - void Gb_Noise::run( int32_t time, int32_t end_time ) - { - /* Determine what will be generated*/ - int vol = 0; - Blip_Buffer* const out = output; - if ( out ) - { - int amp = dac_off_amp; - if ( GB_ENV_DAC_ENABLED() ) - { - if ( enabled ) - vol = volume; - - amp = -(vol >> 1); - - if ( !(phase & 1) ) - { - amp += vol; - vol = -vol; - } - } - - /* AGB negates final output*/ - vol = -vol; - amp = -amp; - - update_amp( time, amp ); - } - - /* Run timer and calculate time of next LFSR clock*/ - static unsigned char const period1s [8] = { 1, 2, 4, 6, 8, 10, 12, 14 }; - int const period1 = period1s [regs [3] & 7] * CLK_MUL; - { - int extra = (end_time - time) - delay; - int const per2 = GB_NOISE_PERIOD2(8); - time += delay + ((divider ^ (per2 >> 1)) & (per2 - 1)) * period1; - - int count = (extra < 0 ? 0 : (extra + period1 - 1) / period1); - divider = (divider - count) & PERIOD2_MASK; - delay = count * period1 - extra; - } - - /* Generate wave*/ - if ( time < end_time ) - { - unsigned const mask = GB_NOISE_LFSR_MASK(); - unsigned bits = phase; - - int per = GB_NOISE_PERIOD2( period1 * 8 ); - if ( GB_NOISE_PERIOD2_INDEX() >= 0xE ) - { - time = end_time; - } - else if ( !vol ) - { - /* Maintain phase when not playing*/ - int count = (end_time - time + per - 1) / per; - time += (int32_t) count * per; - bits = run_lfsr( bits, ~mask, count ); - } - else - { - /* Output amplitude transitions*/ - int delta = -vol; - do - { - unsigned changed = bits + 1; - bits = bits >> 1 & mask; - if ( changed & 2 ) - { - bits |= ~mask; - delta = -delta; - med_synth->offset_inline( time, delta, out ); - } - time += per; - } - while ( time < end_time ); - - if ( delta == vol ) - last_amp += delta; - } - phase = bits; - } - } - INLINE void Gb_Noise::write_register( int frame_phase, int reg, int old_data, int data ) - { - if ( Gb_Env::write_register( frame_phase, reg, old_data, data ) ) - { - phase = 0x7FFF; - delay += CLK_MUL_MUL_8; - } - } - - void reset() - { - divider = 0; - Gb_Env::reset(); - delay = CLK_MUL_MUL_4; /* TODO: remove?*/ - } -}; - -class Gb_Wave : public Gb_Osc -{ - public: - int sample_buf; /* last wave RAM byte read (hardware has this as well)*/ - int agb_mask; /* 0xFF if AGB features enabled, 0 otherwise*/ - uint8_t* wave_ram; /* 32 bytes (64 nybbles), stored in APU*/ - - templatevoid SyncState(NewState *ns) - { - Gb_Osc::SyncState(ns); - NSS(sample_buf); - NSS(agb_mask); - } - - INLINE void Gb_Wave::write_register( int frame_phase, int reg, int old_data, int data ) - { - switch ( reg ) - { - case 0: - if ( !GB_WAVE_DAC_ENABLED() ) - enabled = false; - break; - - case 1: - length_ctr = 256 - data; - break; - - case 4: - bool was_enabled = enabled; - if ( write_trig( frame_phase, 256, old_data ) ) - { - if ( !GB_WAVE_DAC_ENABLED() ) - enabled = false; - phase = 0; - delay = period() + CLK_MUL_MUL_6; - } - } - } - void Gb_Wave::run( int32_t time, int32_t end_time ) - { - /* Calc volume*/ - static unsigned char const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 }; - int const volume_idx = regs [2] >> 5 & (agb_mask | 3); /* 2 bits on DMG/CGB, 3 on AGB*/ - int const volume_mul = volumes [volume_idx]; - - /* Determine what will be generated*/ - int playing = false; - Blip_Buffer* const out = output; - if ( out ) - { - int amp = dac_off_amp; - if ( GB_WAVE_DAC_ENABLED() ) - { - /* Play inaudible frequencies as constant amplitude*/ - amp = 128; /* really depends on average of all samples in wave*/ - - /* if delay is larger, constant amplitude won't start yet*/ - if ( GB_OSC_FREQUENCY() <= 0x7FB || delay > CLK_MUL_MUL_15 ) - { - if ( volume_mul ) - playing = (int) enabled; - - amp = (sample_buf << (phase << 2 & 4) & 0xF0) * playing; - } - - amp = ((amp * volume_mul) >> VOLUME_SHIFT_PLUS_FOUR) - DAC_BIAS; - } - update_amp( time, amp ); - } - - /* Generate wave*/ - time += delay; - if ( time < end_time ) - { - unsigned char const* wave = wave_ram; - - /* wave size and bank*/ - int const flags = regs [0] & agb_mask; - int const wave_mask = (flags & SIZE20_MASK) | 0x1F; - int swap_banks = 0; - if ( flags & BANK40_MASK) - { - swap_banks = flags & SIZE20_MASK; - wave += BANK_SIZE_DIV_TWO - (swap_banks >> 1); - } - - int ph = phase ^ swap_banks; - ph = (ph + 1) & wave_mask; /* pre-advance*/ - - int const per = period(); - if ( !playing ) - { - /* Maintain phase when not playing*/ - int count = (end_time - time + per - 1) / per; - ph += count; /* will be masked below*/ - time += (int32_t) count * per; - } - else - { - /* Output amplitude transitions*/ - int lamp = last_amp + DAC_BIAS; - do - { - /* Extract nybble*/ - int nybble = wave [ph >> 1] << (ph << 2 & 4) & 0xF0; - ph = (ph + 1) & wave_mask; - - /* Scale by volume*/ - int amp = (nybble * volume_mul) >> VOLUME_SHIFT_PLUS_FOUR; - - int delta = amp - lamp; - if ( delta ) - { - lamp = amp; - med_synth->offset_inline( time, delta, out ); - } - time += per; - } - while ( time < end_time ); - last_amp = lamp - DAC_BIAS; - } - ph = (ph - 1) & wave_mask; /* undo pre-advance and mask position*/ - - /* Keep track of last byte read*/ - if ( enabled ) - sample_buf = wave [ph >> 1]; - - phase = ph ^ swap_banks; /* undo swapped banks*/ - } - delay = time - end_time; - } - - /* Reads/writes wave RAM*/ - INLINE int Gb_Wave::read( unsigned addr ) const - { - int index; - - if(enabled) - index = access( addr ); - else - index = addr & 0x0F; - - unsigned char const * wave_bank = &wave_ram[(~regs[0] & BANK40_MASK) >> 2 & agb_mask]; - - return (index < 0 ? 0xFF : wave_bank[index]); - } - - INLINE void Gb_Wave::write( unsigned addr, int data ) - { - int index; - - if(enabled) - index = access( addr ); - else - index = addr & 0x0F; - - unsigned char * wave_bank = &wave_ram[(~regs[0] & BANK40_MASK) >> 2 & agb_mask]; - - if ( index >= 0 ) - wave_bank[index] = data;; - } - - - void reset() - { - sample_buf = 0; - Gb_Osc::reset(); - } - - private: - friend class Gb_Apu; - - /* Frequency timer period*/ - int period() const { return (2048 - GB_OSC_FREQUENCY()) * (CLK_MUL_MUL_2); } - - void Gb_Wave::corrupt_wave() - { - int pos = ((phase + 1) & BANK_SIZE_MIN_ONE) >> 1; - if ( pos < 4 ) - wave_ram [0] = wave_ram [pos]; - else - for ( int i = 4; --i >= 0; ) - wave_ram [i] = wave_ram [(pos & ~3) + i]; - } - - /* Wave index that would be accessed, or -1 if no access would occur*/ - int Gb_Wave::access( unsigned addr ) const - { - //if ( mode != MODE_AGB ) - //{ - // addr = (phase & BANK_SIZE_MIN_ONE) >> 1; - //} - return addr & 0x0F; - } -}; - -/*============================================================ - INLINE CLASS FUNCS -============================================================ */ - -int16_t soundFinalWave [2048]; -static const long soundSampleRate = 44100; // = 22050; -//int SOUND_CLOCK_TICKS; // = SOUND_CLOCK_TICKS_; -//int soundTicks; // = SOUND_CLOCK_TICKS_; -int soundTicksUp; // counts up from 0 being the last time the blips were emptied - -int soundEnableFlag; // = 0x3ff; /* emulator channels enabled*/ - -struct gba_pcm_t -{ - int last_amp; - int last_time; - int shift; - Blip_Buffer* output; - - templatevoid SyncState(NewState *ns, Gigazoid *g) - { - NSS(last_amp); - NSS(last_time); - NSS(shift); - - // tricky - EBS(output, -1); - EVS(output, &g->bufs_buffer[0], 0); - EVS(output, &g->bufs_buffer[1], 1); - EVS(output, &g->bufs_buffer[2], 2); - EES(output, nullptr); - } -}; - -struct gba_pcm_fifo_t -{ - bool enabled; - uint8_t fifo [32]; - int count; - int dac; - int readIndex; - int writeIndex; - int which; - int timer; - gba_pcm_t pcm; - - templatevoid SyncState(NewState *ns, Gigazoid *g) - { - NSS(enabled); - NSS(fifo); - NSS(count); - NSS(dac); - NSS(readIndex); - NSS(writeIndex); - NSS(which); - NSS(timer); - SSS_HACKY(pcm, g); - } -}; - -gba_pcm_fifo_t pcm [2]; - - -Blip_Synth pcm_synth; // 32 kHz, 16 kHz, 8 kHz - -Blip_Buffer bufs_buffer [BUFS_SIZE]; -int mixer_samples_read; - -void gba_pcm_init (void) -{ - pcm[0].pcm.output = 0; - pcm[0].pcm.last_time = 0; - pcm[0].pcm.last_amp = 0; - pcm[0].pcm.shift = 0; - - pcm[1].pcm.output = 0; - pcm[1].pcm.last_time = 0; - pcm[1].pcm.last_amp = 0; - pcm[1].pcm.shift = 0; -} - -void gba_pcm_apply_control( int pcm_idx, int idx ) -{ - int ch = 0; - pcm[pcm_idx].pcm.shift = ~ioMem [SGCNT0_H] >> (2 + idx) & 1; - - if ( (ioMem [NR52] & 0x80) ) - ch = ioMem [SGCNT0_H+1] >> (idx << 2) & 3; - - Blip_Buffer* out = 0; - switch ( ch ) - { - case 1: - out = &bufs_buffer[1]; - break; - case 2: - out = &bufs_buffer[0]; - break; - case 3: - out = &bufs_buffer[2]; - break; - } - - if ( pcm[pcm_idx].pcm.output != out ) - { - if ( pcm[pcm_idx].pcm.output ) - pcm_synth.offset( soundTicksUp, -pcm[pcm_idx].pcm.last_amp, pcm[pcm_idx].pcm.output ); - pcm[pcm_idx].pcm.last_amp = 0; - pcm[pcm_idx].pcm.output = out; - } -} - -/*============================================================ - GB APU -============================================================ */ - -/* 0: Square 1, 1: Square 2, 2: Wave, 3: Noise */ -#define OSC_COUNT 4 - -/* Resets hardware to initial power on state BEFORE boot ROM runs. Mode selects*/ -/* sound hardware. Additional AGB wave features are enabled separately.*/ -#define MODE_AGB 2 - -#define START_ADDR 0xFF10 -#define END_ADDR 0xFF3F - -/* Reads and writes must be within the START_ADDR to END_ADDR range, inclusive.*/ -/* Addresses outside this range are not mapped to the sound hardware.*/ -#define REGISTER_COUNT 48 -#define REGS_SIZE 64 - -/* Clock rate that sound hardware runs at. - * formula: 4194304 * 4 - * */ -#define CLOCK_RATE 16777216 - -struct gb_apu_t -{ - bool reduce_clicks_; - uint8_t regs[REGS_SIZE]; // last values written to registers - int32_t last_time; // time sound emulator has been run to - int32_t frame_time; // time of next frame sequencer action - int32_t frame_period; // clocks between each frame sequencer step - int32_t frame_phase; // phase of next frame sequencer step - double volume_; - Gb_Osc* oscs [OSC_COUNT]; - Gb_Sweep_Square square1; - Gb_Square square2; - Gb_Wave wave; - Gb_Noise noise; - Blip_Synth good_synth; - Blip_Synth med_synth; - - templatevoid SyncState(NewState *ns) - { - NSS(reduce_clicks_); - NSS(regs); - NSS(last_time); - NSS(frame_time); - NSS(frame_period); - NSS(frame_phase); - NSS(volume_); - SSS(square1); - SSS(square2); - SSS(wave); - SSS(noise); - - SSS(good_synth); - SSS(med_synth); - } -} gb_apu; - -#define VOL_REG 0xFF24 -#define STEREO_REG 0xFF25 -#define STATUS_REG 0xFF26 -#define WAVE_RAM 0xFF30 -#define POWER_MASK 0x80 - -#define OSC_COUNT 4 - -void gb_apu_reduce_clicks( bool reduce ) -{ - gb_apu.reduce_clicks_ = reduce; - - /* Click reduction makes DAC off generate same output as volume 0*/ - int dac_off_amp = 0; - - gb_apu.oscs[0]->dac_off_amp = dac_off_amp; - gb_apu.oscs[1]->dac_off_amp = dac_off_amp; - gb_apu.oscs[2]->dac_off_amp = dac_off_amp; - gb_apu.oscs[3]->dac_off_amp = dac_off_amp; - - /* AGB always eliminates clicks on wave channel using same method*/ - gb_apu.wave.dac_off_amp = -DAC_BIAS; -} - -void gb_apu_synth_volume( int iv ) -{ - double v = gb_apu.volume_ * 0.60 / OSC_COUNT / 15 /*steps*/ / 8 /*master vol range*/ * iv; - gb_apu.good_synth.volume( v ); - gb_apu.med_synth .volume( v ); -} - -void gb_apu_apply_volume (void) -{ - int data, left, right, vol_tmp; - data = gb_apu.regs [VOL_REG - START_ADDR]; - left = data >> 4 & 7; - right = data & 7; - vol_tmp = left < right ? right : left; - gb_apu_synth_volume( vol_tmp + 1 ); -} - -void gb_apu_silence_osc( Gb_Osc& o ) -{ - int delta; - - delta = -o.last_amp; - if ( delta ) - { - o.last_amp = 0; - if ( o.output ) - { - gb_apu.med_synth.offset( gb_apu.last_time, delta, o.output ); - } - } -} - -void gb_apu_run_until_( int32_t end_time ) -{ - int32_t time; - - do{ - /* run oscillators*/ - time = end_time; - if ( time > gb_apu.frame_time ) - time = gb_apu.frame_time; - - gb_apu.square1.run( gb_apu.last_time, time ); - gb_apu.square2.run( gb_apu.last_time, time ); - gb_apu.wave .run( gb_apu.last_time, time ); - gb_apu.noise .run( gb_apu.last_time, time ); - gb_apu.last_time = time; - - if ( time == end_time ) - break; - - /* run frame sequencer*/ - gb_apu.frame_time += gb_apu.frame_period * CLK_MUL; - switch ( gb_apu.frame_phase++ ) - { - case 2: - case 6: - /* 128 Hz*/ - gb_apu.square1.clock_sweep(); - case 0: - case 4: - /* 256 Hz*/ - gb_apu.square1.clock_length(); - gb_apu.square2.clock_length(); - gb_apu.wave .clock_length(); - gb_apu.noise .clock_length(); - break; - - case 7: - /* 64 Hz*/ - gb_apu.frame_phase = 0; - gb_apu.square1.clock_envelope(); - gb_apu.square2.clock_envelope(); - gb_apu.noise .clock_envelope(); - } - }while(1); -} - -void gb_apu_write_osc( int index, int reg, int old_data, int data ) -{ - reg -= index * 5; - switch ( index ) - { - case 0: - gb_apu.square1.write_register( gb_apu.frame_phase, reg, old_data, data ); - break; - case 1: - gb_apu.square2.write_register( gb_apu.frame_phase, reg, old_data, data ); - break; - case 2: - gb_apu.wave.write_register( gb_apu.frame_phase, reg, old_data, data ); - break; - case 3: - gb_apu.noise.write_register( gb_apu.frame_phase, reg, old_data, data ); - break; - } -} - -INLINE int gb_apu_calc_output( int osc ) -{ - int bits = gb_apu.regs [STEREO_REG - START_ADDR] >> osc; - return (bits >> 3 & 2) | (bits & 1); -} - -void gb_apu_write_register( int32_t time, unsigned addr, int data ) -{ - int reg = addr - START_ADDR; - if ( (unsigned) reg >= REGISTER_COUNT ) - return; - - if ( addr < STATUS_REG && !(gb_apu.regs [STATUS_REG - START_ADDR] & POWER_MASK) ) - return; /* Power is off*/ - - if ( time > gb_apu.last_time ) - gb_apu_run_until_( time ); - - if ( addr >= WAVE_RAM ) - { - gb_apu.wave.write( addr, data ); - } - else - { - int old_data = gb_apu.regs [reg]; - gb_apu.regs [reg] = data; - - if ( addr < VOL_REG ) - gb_apu_write_osc( reg / 5, reg, old_data, data ); /* Oscillator*/ - else if ( addr == VOL_REG && data != old_data ) - { - /* Master volume*/ - for ( int i = OSC_COUNT; --i >= 0; ) - gb_apu_silence_osc( *gb_apu.oscs [i] ); - - gb_apu_apply_volume(); - } - else if ( addr == STEREO_REG ) - { - /* Stereo panning*/ - for ( int i = OSC_COUNT; --i >= 0; ) - { - Gb_Osc& o = *gb_apu.oscs [i]; - Blip_Buffer* out = o.outputs [gb_apu_calc_output( i )]; - if ( o.output != out ) - { - gb_apu_silence_osc( o ); - o.output = out; - } - } } - else if ( addr == STATUS_REG && (data ^ old_data) & POWER_MASK ) - { - /* Power control*/ - gb_apu.frame_phase = 0; - for ( int i = OSC_COUNT; --i >= 0; ) - gb_apu_silence_osc( *gb_apu.oscs [i] ); - - for ( int i = 0; i < 32; i++ ) - gb_apu.regs [i] = 0; - - gb_apu.square1.reset(); - gb_apu.square2.reset(); - gb_apu.wave .reset(); - gb_apu.noise .reset(); - - gb_apu_apply_volume(); - - gb_apu.square1.length_ctr = 64; - gb_apu.square2.length_ctr = 64; - gb_apu.wave .length_ctr = 256; - gb_apu.noise .length_ctr = 64; - - gb_apu.regs [STATUS_REG - START_ADDR] = data; - } - } -} - -void gb_apu_reset( uint32_t mode, bool agb_wave ) -{ - /* Hardware mode*/ - mode = MODE_AGB; /* using AGB wave features implies AGB hardware*/ - gb_apu.wave.agb_mask = 0xFF; - gb_apu.oscs [0]->mode = mode; - gb_apu.oscs [1]->mode = mode; - gb_apu.oscs [2]->mode = mode; - gb_apu.oscs [3]->mode = mode; - gb_apu_reduce_clicks( gb_apu.reduce_clicks_ ); - - /* Reset state*/ - gb_apu.frame_time = 0; - gb_apu.last_time = 0; - gb_apu.frame_phase = 0; - - for ( int i = 0; i < 32; i++ ) - gb_apu.regs [i] = 0; - - gb_apu.square1.reset(); - gb_apu.square2.reset(); - gb_apu.wave .reset(); - gb_apu.noise .reset(); - - gb_apu_apply_volume(); - - gb_apu.square1.length_ctr = 64; - gb_apu.square2.length_ctr = 64; - gb_apu.wave .length_ctr = 256; - gb_apu.noise .length_ctr = 64; - - /* Load initial wave RAM*/ - static unsigned char const initial_wave [2] [16] = { - {0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C,0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA}, - {0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF}, - }; - for ( int b = 2; --b >= 0; ) - { - /* Init both banks (does nothing if not in AGB mode)*/ - gb_apu_write_register( 0, 0xFF1A, b * 0x40 ); - for ( unsigned i = 0; i < sizeof initial_wave [0]; i++ ) - gb_apu_write_register( 0, i + WAVE_RAM, initial_wave [1] [i] ); - } -} - -void gb_apu_new(void) -{ - int i; - - gb_apu.wave.wave_ram = &gb_apu.regs [WAVE_RAM - START_ADDR]; - - gb_apu.oscs [0] = &gb_apu.square1; - gb_apu.oscs [1] = &gb_apu.square2; - gb_apu.oscs [2] = &gb_apu.wave; - gb_apu.oscs [3] = &gb_apu.noise; - - for ( i = OSC_COUNT; --i >= 0; ) - { - Gb_Osc& o = *gb_apu.oscs [i]; - o.regs = &gb_apu.regs [i * 5]; - o.output = 0; - o.outputs [0] = 0; - o.outputs [1] = 0; - o.outputs [2] = 0; - o.outputs [3] = 0; - o.good_synth = &gb_apu.good_synth; - o.med_synth = &gb_apu.med_synth; - } - - gb_apu.reduce_clicks_ = false; - gb_apu.frame_period = 4194304 / 512; /* 512 Hz*/ - - gb_apu.volume_ = 1.0; - gb_apu_reset(MODE_AGB, false); -} - - - -void gb_apu_set_output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right, int osc ) -{ - int i; - - i = osc; - do - { - Gb_Osc& o = *gb_apu.oscs [i]; - o.outputs [1] = right; - o.outputs [2] = left; - o.outputs [3] = center; - o.output = o.outputs [gb_apu_calc_output( i )]; - ++i; - } - while ( i < osc ); -} - -void gb_apu_volume( double v ) -{ - if ( gb_apu.volume_ != v ) - { - gb_apu.volume_ = v; - gb_apu_apply_volume(); - } -} - -void gb_apu_apply_stereo (void) -{ - int i; - - for ( i = OSC_COUNT; --i >= 0; ) - { - Gb_Osc& o = *gb_apu.oscs [i]; - Blip_Buffer* out = o.outputs [gb_apu_calc_output( i )]; - if ( o.output != out ) - { - gb_apu_silence_osc( o ); - o.output = out; - } - } -} - - -/*============================================================ - GB OSCS -============================================================ */ - - -/*============================================================ - BLIP BUFFER -============================================================ */ - -/* Blip_Buffer 0.4.1. http://www.slack.net/~ant */ - -#define FIXED_SHIFT 12 -#define SAL_FIXED_SHIFT 4096 -#define TO_FIXED( f ) int ((f) * SAL_FIXED_SHIFT) -#define FROM_FIXED( f ) ((f) >> FIXED_SHIFT) - - - -/*============================================================ - STEREO BUFFER -============================================================ */ - -/* Uses three buffers (one for center) and outputs stereo sample pairs. */ - -#define STEREO_BUFFER_SAMPLES_AVAILABLE() ((long)(bufs_buffer[0].offset_ - mixer_samples_read) << 1) -#define stereo_buffer_samples_avail() ((((bufs_buffer [0].offset_ >> BLIP_BUFFER_ACCURACY) - mixer_samples_read) << 1)) - - -const char * stereo_buffer_set_sample_rate( long rate, int msec ) -{ - mixer_samples_read = 0; - for ( int i = BUFS_SIZE; --i >= 0; ) - RETURN_ERR( bufs_buffer [i].set_sample_rate( rate, msec ) ); - return 0; -} - -void stereo_buffer_clock_rate( long rate ) -{ - bufs_buffer[2].factor_ = bufs_buffer [2].clock_rate_factor( rate ); - bufs_buffer[1].factor_ = bufs_buffer [1].clock_rate_factor( rate ); - bufs_buffer[0].factor_ = bufs_buffer [0].clock_rate_factor( rate ); -} - -void stereo_buffer_clear (void) -{ - mixer_samples_read = 0; - bufs_buffer [2].clear(); - bufs_buffer [1].clear(); - bufs_buffer [0].clear(); -} - -/* mixers use a single index value to improve performance on register-challenged processors - * offset goes from negative to zero*/ - -INLINE void stereo_buffer_mixer_read_pairs( int16_t* out, int count ) -{ - /* TODO: if caller never marks buffers as modified, uses mono*/ - /* except that buffer isn't cleared, so caller can encounter*/ - /* subtle problems and not realize the cause.*/ - mixer_samples_read += count; - int16_t* outtemp = out + count * STEREO; - - /* do left + center and right + center separately to reduce register load*/ - Blip_Buffer* buf = &bufs_buffer [2]; - { - --buf; - --outtemp; - - BLIP_READER_BEGIN( side, *buf ); - BLIP_READER_BEGIN( center, bufs_buffer[2] ); - - BLIP_READER_ADJ_( side, mixer_samples_read ); - BLIP_READER_ADJ_( center, mixer_samples_read ); - - int offset = -count; - do - { - int s = (center_reader_accum + side_reader_accum) >> 14; - BLIP_READER_NEXT_IDX_( side, offset ); - BLIP_READER_NEXT_IDX_( center, offset ); - BLIP_CLAMP( s, s ); - - ++offset; /* before write since out is decremented to slightly before end*/ - outtemp [offset * STEREO] = (int16_t) s; - }while ( offset ); - - BLIP_READER_END( side, *buf ); - } - { - --buf; - --outtemp; - - BLIP_READER_BEGIN( side, *buf ); - BLIP_READER_BEGIN( center, bufs_buffer[2] ); - - BLIP_READER_ADJ_( side, mixer_samples_read ); - BLIP_READER_ADJ_( center, mixer_samples_read ); - - int offset = -count; - do - { - int s = (center_reader_accum + side_reader_accum) >> 14; - BLIP_READER_NEXT_IDX_( side, offset ); - BLIP_READER_NEXT_IDX_( center, offset ); - BLIP_CLAMP( s, s ); - - ++offset; /* before write since out is decremented to slightly before end*/ - outtemp [offset * STEREO] = (int16_t) s; - }while ( offset ); - - BLIP_READER_END( side, *buf ); - - /* only end center once*/ - BLIP_READER_END( center, bufs_buffer[2] ); - } -} - -void blip_buffer_remove_all_samples( long count ) -{ - uint32_t new_offset = (uint32_t)count << BLIP_BUFFER_ACCURACY; - /* BLIP BUFFER #1 */ - bufs_buffer[0].offset_ -= new_offset; - bufs_buffer[1].offset_ -= new_offset; - bufs_buffer[2].offset_ -= new_offset; - - /* copy remaining samples to beginning and clear old samples*/ - long remain = (bufs_buffer[0].offset_ >> BLIP_BUFFER_ACCURACY) + BLIP_BUFFER_EXTRA_; - memmove( bufs_buffer[0].buffer_, bufs_buffer[0].buffer_ + count, remain * sizeof *bufs_buffer[0].buffer_ ); - memset( bufs_buffer[0].buffer_ + remain, 0, count * sizeof(*bufs_buffer[0].buffer_)); - - remain = (bufs_buffer[1].offset_ >> BLIP_BUFFER_ACCURACY) + BLIP_BUFFER_EXTRA_; - memmove( bufs_buffer[1].buffer_, bufs_buffer[1].buffer_ + count, remain * sizeof *bufs_buffer[1].buffer_ ); - memset( bufs_buffer[1].buffer_ + remain, 0, count * sizeof(*bufs_buffer[1].buffer_)); - - remain = (bufs_buffer[2].offset_ >> BLIP_BUFFER_ACCURACY) + BLIP_BUFFER_EXTRA_; - memmove( bufs_buffer[2].buffer_, bufs_buffer[2].buffer_ + count, remain * sizeof *bufs_buffer[2].buffer_ ); - memset( bufs_buffer[2].buffer_ + remain, 0, count * sizeof(*bufs_buffer[2].buffer_)); -} - -long stereo_buffer_read_samples( int16_t * out, long out_size ) -{ - int pair_count; - - out_size = (STEREO_BUFFER_SAMPLES_AVAILABLE() < out_size) ? STEREO_BUFFER_SAMPLES_AVAILABLE() : out_size; - - pair_count = int (out_size >> 1); - if ( pair_count ) - { - stereo_buffer_mixer_read_pairs( out, pair_count ); - blip_buffer_remove_all_samples( mixer_samples_read ); - mixer_samples_read = 0; - } - return out_size; -} - -void gba_to_gb_sound_parallel( int * __restrict addr, int * __restrict addr2 ) -{ - uint32_t addr1_table = *addr - 0x60; - uint32_t addr2_table = *addr2 - 0x60; - *addr = table [addr1_table]; - *addr2 = table [addr2_table]; -} - -void pcm_fifo_write_control( int data, int data2) -{ - pcm[0].enabled = (data & 0x0300) ? true : false; - pcm[0].timer = (data & 0x0400) ? 1 : 0; - - if ( data & 0x0800 ) - { - // Reset - pcm[0].writeIndex = 0; - pcm[0].readIndex = 0; - pcm[0].count = 0; - pcm[0].dac = 0; - memset(pcm[0].fifo, 0, sizeof(pcm[0].fifo)); - } - - gba_pcm_apply_control( 0, pcm[0].which ); - - if(pcm[0].pcm.output) - { - int time = soundTicksUp; - - pcm[0].dac = (int8_t)pcm[0].dac >> pcm[0].pcm.shift; - int delta = pcm[0].dac - pcm[0].pcm.last_amp; - if ( delta ) - { - pcm[0].pcm.last_amp = pcm[0].dac; - pcm_synth.offset( time, delta, pcm[0].pcm.output ); - } - pcm[0].pcm.last_time = time; - } - - pcm[1].enabled = (data2 & 0x0300) ? true : false; - pcm[1].timer = (data2 & 0x0400) ? 1 : 0; - - if ( data2 & 0x0800 ) - { - // Reset - pcm[1].writeIndex = 0; - pcm[1].readIndex = 0; - pcm[1].count = 0; - pcm[1].dac = 0; - memset( pcm[1].fifo, 0, sizeof(pcm[1].fifo)); - } - - gba_pcm_apply_control( 1, pcm[1].which ); - - if(pcm[1].pcm.output) - { - int time = soundTicksUp; - - pcm[1].dac = (int8_t)pcm[1].dac >> pcm[1].pcm.shift; - int delta = pcm[1].dac - pcm[1].pcm.last_amp; - if ( delta ) - { - pcm[1].pcm.last_amp = pcm[1].dac; - pcm_synth.offset( time, delta, pcm[1].pcm.output ); - } - pcm[1].pcm.last_time = time; - } -} - -void soundEvent_u16_parallel(uint32_t address[]) -{ - for(int i = 0; i < 8; i++) - { - switch ( address[i] ) - { - case SGCNT0_H: - //Begin of Write SGCNT0_H - WRITE16LE( &ioMem [SGCNT0_H], 0 & 0x770F ); - pcm_fifo_write_control(0, 0); - - gb_apu_volume( apu_vols [ioMem [SGCNT0_H] & 3] ); - //End of SGCNT0_H - break; - - case FIFOA_L: - case FIFOA_H: - pcm[0].fifo [pcm[0].writeIndex ] = 0; - pcm[0].fifo [pcm[0].writeIndex+1] = 0; - pcm[0].count += 2; - pcm[0].writeIndex = (pcm[0].writeIndex + 2) & 31; - WRITE16LE( &ioMem[address[i]], 0 ); - break; - - case FIFOB_L: - case FIFOB_H: - pcm[1].fifo [pcm[1].writeIndex ] = 0; - pcm[1].fifo [pcm[1].writeIndex+1] = 0; - pcm[1].count += 2; - pcm[1].writeIndex = (pcm[1].writeIndex + 2) & 31; - WRITE16LE( &ioMem[address[i]], 0 ); - break; - - case 0x88: - WRITE16LE( &ioMem[address[i]], 0 ); - break; - - default: - { - int gb_addr[2] = {address[i] & ~1, address[i] | 1}; - uint32_t address_array[2] = {address[i] & ~ 1, address[i] | 1}; - uint8_t data_array[2] = {0}; - gba_to_gb_sound_parallel(&gb_addr[0], &gb_addr[1]); - soundEvent_u8_parallel(gb_addr, address_array, data_array); - break; - } - } - } -} - -void gba_pcm_fifo_timer_overflowed( unsigned pcm_idx ) -{ - if ( pcm[pcm_idx].count <= 16 ) - { - // Need to fill FIFO - CPUCheckDMA( 3, pcm[pcm_idx].which ? 4 : 2 ); - - if ( pcm[pcm_idx].count <= 16 ) - { - // Not filled by DMA, so fill with 16 bytes of silence - int reg = pcm[pcm_idx].which ? FIFOB_L : FIFOA_L; - - uint32_t address_array[8] = {reg, reg+2, reg, reg+2, reg, reg+2, reg, reg+2}; - soundEvent_u16_parallel(address_array); - } - } - - // Read next sample from FIFO - pcm[pcm_idx].count--; - pcm[pcm_idx].dac = pcm[pcm_idx].fifo [pcm[pcm_idx].readIndex]; - pcm[pcm_idx].readIndex = (pcm[pcm_idx].readIndex + 1) & 31; - - if(pcm[pcm_idx].pcm.output) - { - int time = soundTicksUp; - - pcm[pcm_idx].dac = (int8_t)pcm[pcm_idx].dac >> pcm[pcm_idx].pcm.shift; - int delta = pcm[pcm_idx].dac - pcm[pcm_idx].pcm.last_amp; - if ( delta ) - { - pcm[pcm_idx].pcm.last_amp = pcm[pcm_idx].dac; - pcm_synth.offset( time, delta, pcm[pcm_idx].pcm.output ); - } - pcm[pcm_idx].pcm.last_time = time; - } -} - -void soundEvent_u8_parallel(int gb_addr[], uint32_t address[], uint8_t data[]) -{ - for(uint32_t i = 0; i < 2; i++) - { - ioMem[address[i]] = data[i]; - gb_apu_write_register( soundTicksUp, gb_addr[i], data[i] ); - - if ( address[i] == NR52 ) - { - gba_pcm_apply_control(0, 0 ); - gba_pcm_apply_control(1, 1 ); - } - // TODO: what about byte writes to SGCNT0_H etc.? - } -} - -void soundEvent_u8(int gb_addr, uint32_t address, uint8_t data) -{ - ioMem[address] = data; - gb_apu_write_register( soundTicksUp, gb_addr, data ); - - if ( address == NR52 ) - { - gba_pcm_apply_control(0, 0 ); - gba_pcm_apply_control(1, 1 ); - } - // TODO: what about byte writes to SGCNT0_H etc.? -} - - -void soundEvent_u16(uint32_t address, uint16_t data) -{ - switch ( address ) - { - case SGCNT0_H: - //Begin of Write SGCNT0_H - WRITE16LE( &ioMem [SGCNT0_H], data & 0x770F ); - pcm_fifo_write_control( data, data >> 4); - - gb_apu_volume( apu_vols [ioMem [SGCNT0_H] & 3] ); - //End of SGCNT0_H - break; - - case FIFOA_L: - case FIFOA_H: - pcm[0].fifo [pcm[0].writeIndex ] = data & 0xFF; - pcm[0].fifo [pcm[0].writeIndex+1] = data >> 8; - pcm[0].count += 2; - pcm[0].writeIndex = (pcm[0].writeIndex + 2) & 31; - WRITE16LE( &ioMem[address], data ); - break; - - case FIFOB_L: - case FIFOB_H: - pcm[1].fifo [pcm[1].writeIndex ] = data & 0xFF; - pcm[1].fifo [pcm[1].writeIndex+1] = data >> 8; - pcm[1].count += 2; - pcm[1].writeIndex = (pcm[1].writeIndex + 2) & 31; - WRITE16LE( &ioMem[address], data ); - break; - - case 0x88: - data &= 0xC3FF; - WRITE16LE( &ioMem[address], data ); - break; - - default: - { - int gb_addr[2] = {address & ~1, address | 1}; - uint32_t address_array[2] = {address & ~ 1, address | 1}; - uint8_t data_array[2] = {(uint8_t)data, (uint8_t)(data >> 8)}; - gba_to_gb_sound_parallel(&gb_addr[0], &gb_addr[1]); - soundEvent_u8_parallel(gb_addr, address_array, data_array); - break; - } - } -} - -void soundTimerOverflow(int timer) -{ - if ( timer == pcm[0].timer && pcm[0].enabled ) - gba_pcm_fifo_timer_overflowed(0); - if ( timer == pcm[1].timer && pcm[1].enabled ) - gba_pcm_fifo_timer_overflowed(1); -} - -void process_sound_tick_fn (void) -{ - // Run sound hardware to present - pcm[0].pcm.last_time -= soundTicksUp; - if ( pcm[0].pcm.last_time < -2048 ) - pcm[0].pcm.last_time = -2048; - - pcm[1].pcm.last_time -= soundTicksUp; - if ( pcm[1].pcm.last_time < -2048 ) - pcm[1].pcm.last_time = -2048; - - /* Emulates sound hardware up to a specified time, ends current time - frame, then starts a new frame at time 0 */ - - if(soundTicksUp > gb_apu.last_time) - gb_apu_run_until_( soundTicksUp ); - - gb_apu.frame_time -= soundTicksUp; - gb_apu.last_time -= soundTicksUp; - - bufs_buffer[2].offset_ += soundTicksUp * bufs_buffer[2].factor_; - bufs_buffer[1].offset_ += soundTicksUp * bufs_buffer[1].factor_; - bufs_buffer[0].offset_ += soundTicksUp * bufs_buffer[0].factor_; - - - // dump all the samples available - // VBA will only ever store 1 frame worth of samples - int numSamples = stereo_buffer_read_samples( (int16_t*) soundFinalWave, stereo_buffer_samples_avail()); - systemOnWriteDataToSoundBuffer(soundFinalWave, numSamples); - - soundTicksUp = 0; -} - -void apply_muting (void) -{ - // PCM - gba_pcm_apply_control(1, 0 ); - gba_pcm_apply_control(1, 1 ); - - // APU - gb_apu_set_output( &bufs_buffer[2], &bufs_buffer[0], &bufs_buffer[1], 0 ); - gb_apu_set_output( &bufs_buffer[2], &bufs_buffer[0], &bufs_buffer[1], 1 ); - gb_apu_set_output( &bufs_buffer[2], &bufs_buffer[0], &bufs_buffer[1], 2 ); - gb_apu_set_output( &bufs_buffer[2], &bufs_buffer[0], &bufs_buffer[1], 3 ); -} - - -void remake_stereo_buffer (void) -{ - if ( !ioMem ) - return; - - // Clears pointers kept to old stereo_buffer - gba_pcm_init(); - - // Stereo_Buffer - - mixer_samples_read = 0; - stereo_buffer_set_sample_rate( soundSampleRate, BLIP_DEFAULT_LENGTH ); - stereo_buffer_clock_rate( CLOCK_RATE ); - - // PCM - pcm [0].which = 0; - pcm [1].which = 1; - - // APU - gb_apu_new(); - gb_apu_reset( MODE_AGB, true ); - - stereo_buffer_clear(); - - soundTicksUp = 0; - - apply_muting(); - - gb_apu_volume(apu_vols [ioMem [SGCNT0_H] & 3] ); - - pcm_synth.volume( 0.66 / 256 * SOUNDVOLUME_ ); -} - -void soundReset (void) -{ - remake_stereo_buffer(); - //Begin of Reset APU - gb_apu_reset( MODE_AGB, true ); - - stereo_buffer_clear(); - - soundTicksUp = 0; - - // Sound Event (NR52) - int gb_addr = table[NR52 - 0x60]; - if ( gb_addr ) - { - ioMem[NR52] = 0x80; - gb_apu_write_register( soundTicksUp, gb_addr, 0x80 ); - - gba_pcm_apply_control(0, 0 ); - gba_pcm_apply_control(1, 1 ); - } - - // TODO: what about byte writes to SGCNT0_H etc.? - // End of Sound Event (NR52) -} -/* -void soundSetSampleRate(long sampleRate) -{ - if ( soundSampleRate != sampleRate ) - { - soundSampleRate = sampleRate; - remake_stereo_buffer(); - } -} -*/ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// END SOUND.CPP -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// BEGIN GBA.CPP -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/*============================================================ - GBA INLINE -============================================================ */ - -#define UPDATE_REG(address, value) WRITE16LE(((u16 *)&ioMem[address]),value); -#define ARM_PREFETCH_NEXT cpuPrefetch[1] = CPUReadMemoryQuick(bus.armNextPC+4); -#define THUMB_PREFETCH_NEXT cpuPrefetch[1] = CPUReadHalfWordQuick(bus.armNextPC+2); - -#define ARM_PREFETCH \ - {\ - cpuPrefetch[0] = CPUReadMemoryQuick(bus.armNextPC);\ - cpuPrefetch[1] = CPUReadMemoryQuick(bus.armNextPC+4);\ - } - -#define THUMB_PREFETCH \ - {\ - cpuPrefetch[0] = CPUReadHalfWordQuick(bus.armNextPC);\ - cpuPrefetch[1] = CPUReadHalfWordQuick(bus.armNextPC+2);\ - } - -int cpuNextEvent; // = 0; -bool holdState; // = false; -uint32_t cpuPrefetch[2]; -int cpuTotalTicks; // = 0; -uint8_t memoryWait[16]; -uint8_t memoryWaitSeq[16]; -uint8_t memoryWait32[16]; -uint8_t memoryWaitSeq32[16]; - -uint8_t biosProtected[4]; -uint8_t cpuBitsSet[256]; - -bool N_FLAG; // = 0; -bool C_FLAG; // = 0; -bool Z_FLAG; // = 0; -bool V_FLAG; // = 0; -bool armState; // = true; -bool armIrqEnable; // = true; -int armMode; // = 0x1f; - -typedef enum -{ - REG_DISPCNT = 0x000, - REG_DISPSTAT = 0x002, - REG_VCOUNT = 0x003, - REG_BG0CNT = 0x004, - REG_BG1CNT = 0x005, - REG_BG2CNT = 0x006, - REG_BG3CNT = 0x007, - REG_BG0HOFS = 0x08, - REG_BG0VOFS = 0x09, - REG_BG1HOFS = 0x0A, - REG_BG1VOFS = 0x0B, - REG_BG2HOFS = 0x0C, - REG_BG2VOFS = 0x0D, - REG_BG3HOFS = 0x0E, - REG_BG3VOFS = 0x0F, - REG_BG2PA = 0x10, - REG_BG2PB = 0x11, - REG_BG2PC = 0x12, - REG_BG2PD = 0x13, - REG_BG2X_L = 0x14, - REG_BG2X_H = 0x15, - REG_BG2Y_L = 0x16, - REG_BG2Y_H = 0x17, - REG_BG3PA = 0x18, - REG_BG3PB = 0x19, - REG_BG3PC = 0x1A, - REG_BG3PD = 0x1B, - REG_BG3X_L = 0x1C, - REG_BG3X_H = 0x1D, - REG_BG3Y_L = 0x1E, - REG_BG3Y_H = 0x1F, - REG_WIN0H = 0x20, - REG_WIN1H = 0x21, - REG_WIN0V = 0x22, - REG_WIN1V = 0x23, - REG_WININ = 0x24, - REG_WINOUT = 0x25, - REG_BLDCNT = 0x28, - REG_BLDALPHA = 0x29, - REG_BLDY = 0x2A, - REG_TM0D = 0x80, - REG_TM0CNT = 0x81, - REG_TM1D = 0x82, - REG_TM1CNT = 0x83, - REG_TM2D = 0x84, - REG_TM2CNT = 0x85, - REG_TM3D = 0x86, - REG_TM3CNT = 0x87, - REG_P1 = 0x098, - REG_P1CNT = 0x099, - REG_RCNT = 0x9A, - REG_IE = 0x100, - REG_IF = 0x101, - REG_IME = 0x104, - REG_HALTCNT = 0x180 -} hardware_register; - -uint16_t io_registers[1024 * 16]; - -u16 MOSAIC; - -uint16_t BG2X_L ; -uint16_t BG2X_H ; -uint16_t BG2Y_L ; -uint16_t BG2Y_H ; -uint16_t BG3X_L ; -uint16_t BG3X_H ; -uint16_t BG3Y_L ; -uint16_t BG3Y_H ; -uint16_t BLDMOD ; -uint16_t COLEV ; -uint16_t COLY ; -uint16_t DM0SAD_L ; -uint16_t DM0SAD_H ; -uint16_t DM0DAD_L ; -uint16_t DM0DAD_H ; -uint16_t DM0CNT_L ; -uint16_t DM0CNT_H ; -uint16_t DM1SAD_L ; -uint16_t DM1SAD_H ; -uint16_t DM1DAD_L ; -uint16_t DM1DAD_H ; -uint16_t DM1CNT_L ; -uint16_t DM1CNT_H ; -uint16_t DM2SAD_L ; -uint16_t DM2SAD_H ; -uint16_t DM2DAD_L ; -uint16_t DM2DAD_H ; -uint16_t DM2CNT_L ; -uint16_t DM2CNT_H ; -uint16_t DM3SAD_L ; -uint16_t DM3SAD_H ; -uint16_t DM3DAD_L ; -uint16_t DM3DAD_H ; -uint16_t DM3CNT_L ; -uint16_t DM3CNT_H ; - -uint8_t timerOnOffDelay ; -uint16_t timer0Value ; -uint32_t dma0Source ; -uint32_t dma0Dest ; -uint32_t dma1Source ; -uint32_t dma1Dest ; -uint32_t dma2Source ; -uint32_t dma2Dest ; -uint32_t dma3Source ; -uint32_t dma3Dest ; -void (Gigazoid::*cpuSaveGameFunc)(uint32_t,uint8_t); -bool fxOn ; -bool windowOn ; - -int cpuDmaTicksToUpdate; - -int IRQTicks; -bool intState; - -bus_t bus; -graphics_t graphics; - -memoryMap map[256]; -int clockTicks; - -int romSize; // = 0x2000000; -uint32_t line[6][240]; -bool gfxInWin[2][240]; -int lineOBJpixleft[128]; -int joy; - -int gfxBG2Changed; -int gfxBG3Changed; - -int gfxBG2X; -int gfxBG2Y; -int gfxBG3X; -int gfxBG3Y; - -bool ioReadable[0x400]; - -//int gfxLastVCOUNT = 0; - -// Waitstates when accessing data - -#define DATATICKS_ACCESS_BUS_PREFETCH(address, value) \ - int addr = (address >> 24) & 15; \ - if ((addr>=0x08) || (addr < 0x02)) \ - { \ - bus.busPrefetchCount=0; \ - bus.busPrefetch=false; \ - } \ - else if (bus.busPrefetch) \ - { \ - int waitState = value; \ - waitState = (1 & ~waitState) | (waitState & waitState); \ - bus.busPrefetchCount = ((bus.busPrefetchCount+1)<> 24) & 15]) -#define DATATICKS_ACCESS_32BIT_SEQ(address) (memoryWaitSeq32[(address >> 24) & 15]) -#define DATATICKS_ACCESS_16BIT(address) (memoryWait[(address >> 24) & 15]) -#define DATATICKS_ACCESS_16BIT_SEQ(address) (memoryWaitSeq[(address >> 24) & 15]) - -// Waitstates when executing opcode -INLINE int codeTicksAccess(u32 address, u8 bit32) // THUMB NON SEQ -{ - int addr, ret; - - addr = (address>>24) & 15; - - if (unsigned(addr - 0x08) <= 5) - { - if (bus.busPrefetchCount&0x1) - { - if (bus.busPrefetchCount&0x2) - { - bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>2) | (bus.busPrefetchCount&0xFFFFFF00); - return 0; - } - bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>1) | (bus.busPrefetchCount&0xFFFFFF00); - return memoryWaitSeq[addr]-1; - } - } - bus.busPrefetchCount = 0; - - if(bit32) /* ARM NON SEQ */ - ret = memoryWait32[addr]; - else /* THUMB NON SEQ */ - ret = memoryWait[addr]; - - return ret; -} - -INLINE int codeTicksAccessSeq16(u32 address) // THUMB SEQ -{ - int addr = (address>>24) & 15; - - if (unsigned(addr - 0x08) <= 5) - { - if (bus.busPrefetchCount&0x1) - { - bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>1) | (bus.busPrefetchCount&0xFFFFFF00); - return 0; - } - else if (bus.busPrefetchCount>0xFF) - { - bus.busPrefetchCount=0; - return memoryWait[addr]; - } - } - else - bus.busPrefetchCount = 0; - - return memoryWaitSeq[addr]; -} - -INLINE int codeTicksAccessSeq32(u32 address) // ARM SEQ -{ - int addr = (address>>24)&15; - - if (unsigned(addr - 0x08) <= 5) - { - if (bus.busPrefetchCount&0x1) - { - if (bus.busPrefetchCount&0x2) - { - bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>2) | (bus.busPrefetchCount&0xFFFFFF00); - return 0; - } - bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>1) | (bus.busPrefetchCount&0xFFFFFF00); - return memoryWaitSeq[addr]; - } - else if (bus.busPrefetchCount > 0xFF) - { - bus.busPrefetchCount=0; - return memoryWait32[addr]; - } - } - return memoryWaitSeq32[addr]; -} - -#define CPUReadByteQuick(addr) map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] -#define CPUReadHalfWordQuick(addr) READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) -#define CPUReadMemoryQuick(addr) READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) - -bool stopState; -#ifdef USE_MOTION_SENSOR -extern bool cpuEEPROMSensorEnabled; -#endif -bool timer0On ; -int timer0Ticks ; -int timer0Reload ; -int timer0ClockReload ; -uint16_t timer1Value ; -bool timer1On ; -int timer1Ticks ; -int timer1Reload ; -int timer1ClockReload ; -uint16_t timer2Value ; -bool timer2On ; -int timer2Ticks ; -int timer2Reload ; -int timer2ClockReload ; -uint16_t timer3Value ; -bool timer3On ; -int timer3Ticks ; -int timer3Reload ; -int timer3ClockReload ; - -INLINE u32 CPUReadMemory(u32 address) -{ - if (readCallback) - readCallback(address); - - u32 value; - switch(address >> 24) - { - case 0: - /* BIOS */ - if(bus.reg[15].I >> 24) - { - if(address < 0x4000) - value = READ32LE(((u32 *)&biosProtected)); - else goto unreadable; - } - else - value = READ32LE(((u32 *)&bios[address & 0x3FFC])); - break; - case 0x02: - /* external work RAM */ - value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC])); - break; - case 0x03: - /* internal work RAM */ - value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC])); - break; - case 0x04: - /* I/O registers */ - if (address == 0x4000130) - { - if (padCallback) - padCallback(); - lagged = false; - } - if((address < 0x4000400) && ioReadable[address & 0x3fc]) - { - if(ioReadable[(address & 0x3fc) + 2]) - value = READ32LE(((u32 *)&ioMem[address & 0x3fC])); - else - value = READ16LE(((u16 *)&ioMem[address & 0x3fc])); - } - else - goto unreadable; - break; - case 0x05: - /* palette RAM */ - value = READ32LE(((u32 *)&graphics.paletteRAM[address & 0x3fC])); - break; - case 0x06: - /* VRAM */ - address = (address & 0x1fffc); - if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000)) - { - value = 0; - break; - } - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - value = READ32LE(((u32 *)&vram[address])); - break; - case 0x07: - /* OAM RAM */ - value = READ32LE(((u32 *)&oam[address & 0x3FC])); - break; - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - /* gamepak ROM */ - value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); - break; - case 0x0D: - value = eepromRead(); - break; - case 14: - case 15: - value = flashRead(address) * 0x01010101; - break; - default: -unreadable: - if(armState) - value = CPUReadHalfWordQuick(bus.reg[15].I + (address & 2)); - else - value = CPUReadHalfWordQuick(bus.reg[15].I); - } - - if(address & 3) { - int shift = (address & 3) << 3; - value = (value >> shift) | (value << (32 - shift)); - } - return value; -} - -INLINE u32 CPUReadHalfWord(u32 address) -{ - if (readCallback) - readCallback(address); - - u32 value; - switch(address >> 24) - { - case 0: - if (bus.reg[15].I >> 24) - { - if(address < 0x4000) - value = READ16LE(((u16 *)&biosProtected[address&2])); - else - goto unreadable; - } - else - value = READ16LE(((u16 *)&bios[address & 0x3FFE])); - break; - case 2: - value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE])); - break; - case 3: - value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe])); - break; - case 4: - if (address == 0x4000130) - { - if (padCallback) - padCallback(); - lagged = false; - } - - if((address < 0x4000400) && ioReadable[address & 0x3fe]) - { - value = READ16LE(((u16 *)&ioMem[address & 0x3fe])); - if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E)) - { - if (((address & 0x3fe) == 0x100) && timer0On) - value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload); - else - if (((address & 0x3fe) == 0x104) && timer1On && !(io_registers[REG_TM1CNT] & 4)) - value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload); - else - if (((address & 0x3fe) == 0x108) && timer2On && !(io_registers[REG_TM2CNT] & 4)) - value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload); - else - if (((address & 0x3fe) == 0x10C) && timer3On && !(io_registers[REG_TM3CNT] & 4)) - value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); - } - } - else goto unreadable; - break; - case 5: - value = READ16LE(((u16 *)&graphics.paletteRAM[address & 0x3fe])); - break; - case 6: - address = (address & 0x1fffe); - if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000)) - { - value = 0; - break; - } - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - value = READ16LE(((u16 *)&vram[address])); - break; - case 7: - value = READ16LE(((u16 *)&oam[address & 0x3fe])); - break; - case 8: - case 9: - case 10: - case 11: - case 12: - if(rtcEnabled && (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)) - value = rtcRead(address); - else - value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); - break; - case 13: - value = eepromRead(); - break; - case 14: - value = flashRead(address) * 0x0101; - break; - default: -unreadable: - { - int param = bus.reg[15].I; - if(armState) - param += (address & 2); - value = CPUReadHalfWordQuick(param); - } - break; - } - - if(address & 1) - value = (value >> 8) | (value << 24); - - return value; -} - -INLINE u16 CPUReadHalfWordSigned(u32 address) -{ - u16 value = CPUReadHalfWord(address); - if((address & 1)) - value = (s8)value; - return value; -} - -INLINE u8 CPUReadByte(u32 address) -{ - if (readCallback) - readCallback(address); - - switch(address >> 24) - { - case 0: - if (bus.reg[15].I >> 24) - { - if(address < 0x4000) - return biosProtected[address & 3]; - else - goto unreadable; - } - return bios[address & 0x3FFF]; - case 2: - return workRAM[address & 0x3FFFF]; - case 3: - return internalRAM[address & 0x7fff]; - case 4: - if (address == 0x4000130 || address == 0x4000131) - { - if (padCallback) - padCallback(); - lagged = false; - } - - if((address < 0x4000400) && ioReadable[address & 0x3ff]) - return ioMem[address & 0x3ff]; - else goto unreadable; - case 5: - return graphics.paletteRAM[address & 0x3ff]; - case 6: - address = (address & 0x1ffff); - if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000)) - return 0; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - return vram[address]; - case 7: - return oam[address & 0x3ff]; - case 8: - case 9: - case 10: - case 11: - case 12: - return rom[address & 0x1FFFFFF]; - case 13: - return eepromRead(); - case 14: -#ifdef USE_MOTION_SENSOR - if(cpuEEPROMSensorEnabled) - { - switch(address & 0x00008f00) - { - case 0x8200: - return systemGetSensorX() & 255; - case 0x8300: - return (systemGetSensorX() >> 8)|0x80; - case 0x8400: - return systemGetSensorY() & 255; - case 0x8500: - return systemGetSensorY() >> 8; - } - } -#endif - return flashRead(address); - default: -unreadable: - if(armState) - return CPUReadByteQuick(bus.reg[15].I+(address & 3)); - else - return CPUReadByteQuick(bus.reg[15].I+(address & 1)); - } -} - -INLINE void CPUWriteMemory(u32 address, u32 value) -{ - if (writeCallback) - writeCallback(address); - - switch(address >> 24) - { - case 0x02: - WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value); - break; - case 0x03: - WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value); - break; - case 0x04: - if(address < 0x4000400) - { - CPUUpdateRegister((address & 0x3FC), value & 0xFFFF); - CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16)); - } - break; - case 0x05: - WRITE32LE(((u32 *)&graphics.paletteRAM[address & 0x3FC]), value); - break; - case 0x06: - address = (address & 0x1fffc); - if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000)) - return; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - - - WRITE32LE(((u32 *)&vram[address]), value); - break; - case 0x07: - WRITE32LE(((u32 *)&oam[address & 0x3fc]), value); - break; - case 0x0D: - if (cpuEEPROMEnabled) - eepromWrite(value); - break; - case 0x0E: - (this->*cpuSaveGameFunc)(address, (u8)value); - break; - default: - break; - } -} - -INLINE void CPUWriteHalfWord(u32 address, u16 value) -{ - if (writeCallback) - writeCallback(address); - - switch(address >> 24) - { - case 2: - WRITE16LE(((u16 *)&workRAM[address & 0x3FFFE]),value); - break; - case 3: - WRITE16LE(((u16 *)&internalRAM[address & 0x7ffe]), value); - break; - case 4: - if(address < 0x4000400) - CPUUpdateRegister(address & 0x3fe, value); - break; - case 5: - WRITE16LE(((u16 *)&graphics.paletteRAM[address & 0x3fe]), value); - break; - case 6: - address = (address & 0x1fffe); - if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000)) - return; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - WRITE16LE(((u16 *)&vram[address]), value); - break; - case 7: - WRITE16LE(((u16 *)&oam[address & 0x3fe]), value); - break; - case 8: - case 9: - if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) - if(!rtcWrite(address, value)) - break; - break; - case 13: - if(cpuEEPROMEnabled) - eepromWrite((u8)value); - break; - case 14: - (this->*cpuSaveGameFunc)(address, (u8)value); - break; - default: - break; - } -} - -INLINE void CPUWriteByte(u32 address, u8 b) -{ - if (writeCallback) - writeCallback(address); - - switch(address >> 24) - { - case 2: - workRAM[address & 0x3FFFF] = b; - break; - case 3: - internalRAM[address & 0x7fff] = b; - break; - case 4: - if(address < 0x4000400) - { - switch(address & 0x3FF) - { - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x68: - case 0x69: - case 0x6c: - case 0x6d: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x78: - case 0x79: - case 0x7c: - case 0x7d: - case 0x80: - case 0x81: - case 0x84: - case 0x85: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9a: - case 0x9b: - case 0x9c: - case 0x9d: - case 0x9e: - case 0x9f: - { - int gb_addr = table[(address & 0xFF) - 0x60]; - soundEvent_u8(gb_addr, address&0xFF, b); - } - break; - case 0x301: // HALTCNT, undocumented - if(b == 0x80) - stopState = true; - holdState = 1; - cpuNextEvent = cpuTotalTicks; - break; - default: // every other register - { - u32 lowerBits = address & 0x3fe; - uint16_t param; - if(address & 1) - param = (READ16LE(&ioMem[lowerBits]) & 0x00FF) | (b << 8); - else - param = (READ16LE(&ioMem[lowerBits]) & 0xFF00) | b; - - CPUUpdateRegister(lowerBits, param); - } - break; - } - } - break; - case 5: - // no need to switch - *((u16 *)&graphics.paletteRAM[address & 0x3FE]) = (b << 8) | b; - break; - case 6: - address = (address & 0x1fffe); - if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000)) - return; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - - // no need to switch - // byte writes to OBJ VRAM are ignored - if ((address) < objTilesAddress[((io_registers[REG_DISPCNT] & 7)+1)>>2]) - *((u16 *)&vram[address]) = (b << 8) | b; - break; - case 7: - // no need to switch - // byte writes to OAM are ignored - // *((u16 *)&oam[address & 0x3FE]) = (b << 8) | b; - break; - case 13: - if(cpuEEPROMEnabled) - eepromWrite(b); - break; - case 14: - (this->*cpuSaveGameFunc)(address, b); - break; - default: - break; - } -} - - -/*============================================================ - BIOS -============================================================ */ - -void BIOS_RegisterRamReset(u32 flags) -{ - // no need to trace here. this is only called directly from GBA.cpp - // to emulate bios initialization - - CPUUpdateRegister(0x0, 0x80); - - if(flags) - { - if(flags & 0x01) - memset(workRAM, 0, 0x40000); // clear work RAM - - if(flags & 0x02) - memset(internalRAM, 0, 0x7e00); // don't clear 0x7e00-0x7fff, clear internal RAM - - if(flags & 0x04) - memset(graphics.paletteRAM, 0, 0x400); // clear palette RAM - - if(flags & 0x08) - memset(vram, 0, 0x18000); // clear VRAM - - if(flags & 0x10) - memset(oam, 0, 0x400); // clean OAM - - if(flags & 0x80) { - int i; - for(i = 0; i < 0x10; i++) - CPUUpdateRegister(0x200+i*2, 0); - - for(i = 0; i < 0xF; i++) - CPUUpdateRegister(0x4+i*2, 0); - - for(i = 0; i < 0x20; i++) - CPUUpdateRegister(0x20+i*2, 0); - - for(i = 0; i < 0x18; i++) - CPUUpdateRegister(0xb0+i*2, 0); - - CPUUpdateRegister(0x130, 0); - CPUUpdateRegister(0x20, 0x100); - CPUUpdateRegister(0x30, 0x100); - CPUUpdateRegister(0x26, 0x100); - CPUUpdateRegister(0x36, 0x100); - } - - if(flags & 0x20) { - int i; - for(i = 0; i < 8; i++) - CPUUpdateRegister(0x110+i*2, 0); - CPUUpdateRegister(0x134, 0x8000); - for(i = 0; i < 7; i++) - CPUUpdateRegister(0x140+i*2, 0); - } - - if(flags & 0x40) { - int i; - CPUWriteByte(0x4000084, 0); - CPUWriteByte(0x4000084, 0x80); - CPUWriteMemory(0x4000080, 0x880e0000); - CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff); - CPUWriteByte(0x4000070, 0x70); - for(i = 0; i < 8; i++) - CPUUpdateRegister(0x90+i*2, 0); - CPUWriteByte(0x4000070, 0); - for(i = 0; i < 8; i++) - CPUUpdateRegister(0x90+i*2, 0); - CPUWriteByte(0x4000084, 0); - } - } -} - -void BIOS_SoftReset (void) -{ - armState = true; - armMode = 0x1F; - armIrqEnable = false; - C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false; - bus.reg[13].I = 0x03007F00; - bus.reg[14].I = 0x00000000; - bus.reg[16].I = 0x00000000; - bus.reg[R13_IRQ].I = 0x03007FA0; - bus.reg[R14_IRQ].I = 0x00000000; - bus.reg[SPSR_IRQ].I = 0x00000000; - bus.reg[R13_SVC].I = 0x03007FE0; - bus.reg[R14_SVC].I = 0x00000000; - bus.reg[SPSR_SVC].I = 0x00000000; - u8 b = internalRAM[0x7ffa]; - - memset(&internalRAM[0x7e00], 0, 0x200); - - if(b) { - bus.armNextPC = 0x02000000; - bus.reg[15].I = 0x02000004; - } else { - bus.armNextPC = 0x08000000; - bus.reg[15].I = 0x08000004; - } -} - -#define BIOS_REGISTER_RAM_RESET() BIOS_RegisterRamReset(bus.reg[0].I); - -#define CPU_UPDATE_CPSR() \ -{ \ - uint32_t CPSR; \ - CPSR = bus.reg[16].I & 0x40; \ - if(N_FLAG) \ - CPSR |= 0x80000000; \ - if(Z_FLAG) \ - CPSR |= 0x40000000; \ - if(C_FLAG) \ - CPSR |= 0x20000000; \ - if(V_FLAG) \ - CPSR |= 0x10000000; \ - if(!armState) \ - CPSR |= 0x00000020; \ - if(!armIrqEnable) \ - CPSR |= 0x80; \ - CPSR |= (armMode & 0x1F); \ - bus.reg[16].I = CPSR; \ -} - -#define CPU_SOFTWARE_INTERRUPT() \ -{ \ - uint32_t PC = bus.reg[15].I; \ - bool savedArmState = armState; \ - if(armMode != 0x13) \ - CPUSwitchMode(0x13, true, false); \ - bus.reg[14].I = PC - (savedArmState ? 4 : 2); \ - bus.reg[15].I = 0x08; \ - armState = true; \ - armIrqEnable = false; \ - bus.armNextPC = 0x08; \ - ARM_PREFETCH; \ - bus.reg[15].I += 4; \ -} - -void CPUUpdateFlags(bool breakLoop) -{ - uint32_t CPSR = bus.reg[16].I; - - N_FLAG = (CPSR & 0x80000000) ? true: false; - Z_FLAG = (CPSR & 0x40000000) ? true: false; - C_FLAG = (CPSR & 0x20000000) ? true: false; - V_FLAG = (CPSR & 0x10000000) ? true: false; - armState = (CPSR & 0x20) ? false : true; - armIrqEnable = (CPSR & 0x80) ? false : true; - if (breakLoop && armIrqEnable && (io_registers[REG_IF] & io_registers[REG_IE]) && (io_registers[REG_IME] & 1)) - cpuNextEvent = cpuTotalTicks; -} - -void CPUSoftwareInterrupt(int comment) -{ - if(armState) - comment >>= 16; - - CPU_SOFTWARE_INTERRUPT(); -} - - -/*============================================================ - GBA ARM CORE -============================================================ */ - -#ifdef _MSC_VER - // Disable "empty statement" warnings - #pragma warning(disable: 4390) - // Visual C's inline assembler treats "offset" as a reserved word, so we - // tell it otherwise. If you want to use it, write "OFFSET" in capitals. - #define offset offset_ -#endif - -void armUnknownInsn(u32 opcode) -{ - u32 PC = bus.reg[15].I; - bool savedArmState = armState; - if(armMode != 0x1b ) - CPUSwitchMode(0x1b, true, false); - bus.reg[14].I = PC - (savedArmState ? 4 : 2); - bus.reg[15].I = 0x04; - armState = true; - armIrqEnable = false; - bus.armNextPC = 0x04; - ARM_PREFETCH; - bus.reg[15].I += 4; -} - -// Common macros ////////////////////////////////////////////////////////// - -#define NEG(i) ((i) >> 31) -#define POS(i) ((~(i)) >> 31) - -// The following macros are used for optimization; any not defined for a -// particular compiler/CPU combination default to the C core versions. -// -// ALU_INIT_C: Used at the beginning of ALU instructions (AND/EOR/...). -// (ALU_INIT_NC) Can consist of variable declarations, like the C core, -// or the start of a continued assembly block, like the -// x86-optimized version. The _C version is used when the -// carry flag from the shift operation is needed (logical -// operations that set condition codes, like ANDS); the -// _NC version is used when the carry result is ignored. -// VALUE_XXX: Retrieve the second operand's value for an ALU instruction. -// The _C and _NC versions are used the same way as ALU_INIT. -// OP_XXX: ALU operations. XXX is the instruction name. -// SETCOND_NONE: Used in multiply instructions in place of SETCOND_MUL -// when the condition codes are not set. Usually empty. -// SETCOND_MUL: Used in multiply instructions to set the condition codes. -// ROR_IMM_MSR: Used to rotate the immediate operand for MSR. -// ROR_OFFSET: Used to rotate the `offset' parameter for LDR and STR -// instructions. -// RRX_OFFSET: Used to rotate (RRX) the `offset' parameter for LDR and -// STR instructions. - -// C core - -#define C_SETCOND_LOGICAL \ - N_FLAG = ((s32)res < 0) ? true : false; \ - Z_FLAG = (res == 0) ? true : false; \ - C_FLAG = C_OUT; -#define C_SETCOND_ADD \ - N_FLAG = ((s32)res < 0) ? true : false; \ - Z_FLAG = (res == 0) ? true : false; \ - V_FLAG = ((NEG(lhs) & NEG(rhs) & POS(res)) | \ - (POS(lhs) & POS(rhs) & NEG(res))) ? true : false;\ - C_FLAG = ((NEG(lhs) & NEG(rhs)) | \ - (NEG(lhs) & POS(res)) | \ - (NEG(rhs) & POS(res))) ? true : false; -#define C_SETCOND_SUB \ - N_FLAG = ((s32)res < 0) ? true : false; \ - Z_FLAG = (res == 0) ? true : false; \ - V_FLAG = ((NEG(lhs) & POS(rhs) & POS(res)) | \ - (POS(lhs) & NEG(rhs) & NEG(res))) ? true : false;\ - C_FLAG = ((NEG(lhs) & POS(rhs)) | \ - (NEG(lhs) & POS(res)) | \ - (POS(rhs) & POS(res))) ? true : false; - -#ifndef ALU_INIT_C - #define ALU_INIT_C \ - int dest = (opcode>>12) & 15; \ - bool C_OUT = C_FLAG; \ - u32 value; -#endif -// OP Rd,Rb,Rm LSL # -#ifndef VALUE_LSL_IMM_C - #define VALUE_LSL_IMM_C \ - unsigned int shift = (opcode >> 7) & 0x1F; \ - if (!shift) { /* LSL #0 most common? */ \ - value = bus.reg[opcode & 0x0F].I; \ - } else { \ - u32 v = bus.reg[opcode & 0x0F].I; \ - C_OUT = (v >> (32 - shift)) & 1 ? true : false; \ - value = v << shift; \ - } -#endif -// OP Rd,Rb,Rm LSL Rs -#ifndef VALUE_LSL_REG_C - #define VALUE_LSL_REG_C \ - unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \ - if (shift) { \ - if (shift == 32) { \ - value = 0; \ - C_OUT = (bus.reg[opcode & 0x0F].I & 1 ? true : false);\ - } else if (shift < 32) { \ - u32 v = bus.reg[opcode & 0x0F].I; \ - C_OUT = (v >> (32 - shift)) & 1 ? true : false;\ - value = v << shift; \ - } else { \ - value = 0; \ - C_OUT = false; \ - } \ - } else { \ - value = bus.reg[opcode & 0x0F].I; \ - } -#endif -// OP Rd,Rb,Rm LSR # -#ifndef VALUE_LSR_IMM_C - #define VALUE_LSR_IMM_C \ - unsigned int shift = (opcode >> 7) & 0x1F; \ - if (shift) { \ - u32 v = bus.reg[opcode & 0x0F].I; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ - value = v >> shift; \ - } else { \ - value = 0; \ - C_OUT = (bus.reg[opcode & 0x0F].I & 0x80000000) ? true : false;\ - } -#endif -// OP Rd,Rb,Rm LSR Rs -#ifndef VALUE_LSR_REG_C - #define VALUE_LSR_REG_C \ - unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \ - if (shift) { \ - if (shift == 32) { \ - value = 0; \ - C_OUT = (bus.reg[opcode & 0x0F].I & 0x80000000 ? true : false);\ - } else if (shift < 32) { \ - u32 v = bus.reg[opcode & 0x0F].I; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false;\ - value = v >> shift; \ - } else { \ - value = 0; \ - C_OUT = false; \ - } \ - } else { \ - value = bus.reg[opcode & 0x0F].I; \ - } -#endif -// OP Rd,Rb,Rm ASR # -#ifndef VALUE_ASR_IMM_C - #define VALUE_ASR_IMM_C \ - unsigned int shift = (opcode >> 7) & 0x1F; \ - if (shift) { \ - s32 v = bus.reg[opcode & 0x0F].I; \ - C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\ - value = v >> (int)shift; \ - } else { \ - if (bus.reg[opcode & 0x0F].I & 0x80000000) { \ - value = 0xFFFFFFFF; \ - C_OUT = true; \ - } else { \ - value = 0; \ - C_OUT = false; \ - } \ - } -#endif -// OP Rd,Rb,Rm ASR Rs -#ifndef VALUE_ASR_REG_C - #define VALUE_ASR_REG_C \ - unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \ - if (shift < 32) { \ - if (shift) { \ - s32 v = bus.reg[opcode & 0x0F].I; \ - C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\ - value = v >> (int)shift; \ - } else { \ - value = bus.reg[opcode & 0x0F].I; \ - } \ - } else { \ - if (bus.reg[opcode & 0x0F].I & 0x80000000) { \ - value = 0xFFFFFFFF; \ - C_OUT = true; \ - } else { \ - value = 0; \ - C_OUT = false; \ - } \ - } -#endif -// OP Rd,Rb,Rm ROR # -#ifndef VALUE_ROR_IMM_C - #define VALUE_ROR_IMM_C \ - unsigned int shift = (opcode >> 7) & 0x1F; \ - if (shift) { \ - u32 v = bus.reg[opcode & 0x0F].I; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ - value = ((v << (32 - shift)) | \ - (v >> shift)); \ - } else { \ - u32 v = bus.reg[opcode & 0x0F].I; \ - C_OUT = (v & 1) ? true : false; \ - value = ((v >> 1) | \ - (C_FLAG << 31)); \ - } -#endif -// OP Rd,Rb,Rm ROR Rs -#ifndef VALUE_ROR_REG_C - #define VALUE_ROR_REG_C \ - unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \ - if (shift & 0x1F) { \ - u32 v = bus.reg[opcode & 0x0F].I; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ - value = ((v << (32 - shift)) | \ - (v >> shift)); \ - } else { \ - value = bus.reg[opcode & 0x0F].I; \ - if (shift) \ - C_OUT = (value & 0x80000000 ? true : false);\ - } -#endif -// OP Rd,Rb,# ROR # -#ifndef VALUE_IMM_C - #define VALUE_IMM_C \ - int shift = (opcode & 0xF00) >> 7; \ - if (shift) { \ - u32 v = opcode & 0xFF; \ - C_OUT = (v >> (shift - 1)) & 1 ? true : false; \ - value = ((v << (32 - shift)) | \ - (v >> shift)); \ - } else { \ - value = opcode & 0xFF; \ - } -#endif - -// Make the non-carry versions default to the carry versions -// (this is fine for C--the compiler will optimize the dead code out) -#ifndef ALU_INIT_NC - #define ALU_INIT_NC ALU_INIT_C -#endif -#ifndef VALUE_LSL_IMM_NC - #define VALUE_LSL_IMM_NC VALUE_LSL_IMM_C -#endif -#ifndef VALUE_LSL_REG_NC - #define VALUE_LSL_REG_NC VALUE_LSL_REG_C -#endif -#ifndef VALUE_LSR_IMM_NC - #define VALUE_LSR_IMM_NC VALUE_LSR_IMM_C -#endif -#ifndef VALUE_LSR_REG_NC - #define VALUE_LSR_REG_NC VALUE_LSR_REG_C -#endif -#ifndef VALUE_ASR_IMM_NC - #define VALUE_ASR_IMM_NC VALUE_ASR_IMM_C -#endif -#ifndef VALUE_ASR_REG_NC - #define VALUE_ASR_REG_NC VALUE_ASR_REG_C -#endif -#ifndef VALUE_ROR_IMM_NC - #define VALUE_ROR_IMM_NC VALUE_ROR_IMM_C -#endif -#ifndef VALUE_ROR_REG_NC - #define VALUE_ROR_REG_NC VALUE_ROR_REG_C -#endif -#ifndef VALUE_IMM_NC - #define VALUE_IMM_NC VALUE_IMM_C -#endif - -#define C_CHECK_PC(SETCOND) if (dest != 15) { SETCOND } -#ifndef OP_AND - #define OP_AND \ - u32 res = bus.reg[(opcode>>16)&15].I & value; \ - bus.reg[dest].I = res; -#endif -#ifndef OP_ANDS - #define OP_ANDS OP_AND C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_EOR - #define OP_EOR \ - u32 res = bus.reg[(opcode>>16)&15].I ^ value; \ - bus.reg[dest].I = res; -#endif -#ifndef OP_EORS - #define OP_EORS OP_EOR C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_SUB - #define OP_SUB \ - u32 lhs = bus.reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs - rhs; \ - bus.reg[dest].I = res; -#endif -#ifndef OP_SUBS - #define OP_SUBS OP_SUB C_CHECK_PC(C_SETCOND_SUB) -#endif -#ifndef OP_RSB - #define OP_RSB \ - u32 lhs = bus.reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = rhs - lhs; \ - bus.reg[dest].I = res; -#endif -#ifndef OP_RSBS - #define OP_RSBS OP_RSB C_CHECK_PC(C_SETCOND_SUB) -#endif -#ifndef OP_ADD - #define OP_ADD \ - u32 lhs = bus.reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs + rhs; \ - bus.reg[dest].I = res; -#endif -#ifndef OP_ADDS - #define OP_ADDS OP_ADD C_CHECK_PC(C_SETCOND_ADD) -#endif -#ifndef OP_ADC - #define OP_ADC \ - u32 lhs = bus.reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs + rhs + (u32)C_FLAG; \ - bus.reg[dest].I = res; -#endif -#ifndef OP_ADCS - #define OP_ADCS OP_ADC C_CHECK_PC(C_SETCOND_ADD) -#endif -#ifndef OP_SBC - #define OP_SBC \ - u32 lhs = bus.reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs - rhs - !((u32)C_FLAG); \ - bus.reg[dest].I = res; -#endif -#ifndef OP_SBCS - #define OP_SBCS OP_SBC C_CHECK_PC(C_SETCOND_SUB) -#endif -#ifndef OP_RSC - #define OP_RSC \ - u32 lhs = bus.reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = rhs - lhs - !((u32)C_FLAG); \ - bus.reg[dest].I = res; -#endif -#ifndef OP_RSCS - #define OP_RSCS OP_RSC C_CHECK_PC(C_SETCOND_SUB) -#endif -#ifndef OP_TST - #define OP_TST \ - u32 res = bus.reg[(opcode >> 16) & 0x0F].I & value; \ - C_SETCOND_LOGICAL; -#endif -#ifndef OP_TEQ - #define OP_TEQ \ - u32 res = bus.reg[(opcode >> 16) & 0x0F].I ^ value; \ - C_SETCOND_LOGICAL; -#endif -#ifndef OP_CMP - #define OP_CMP \ - u32 lhs = bus.reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs - rhs; \ - C_SETCOND_SUB; -#endif -#ifndef OP_CMN - #define OP_CMN \ - u32 lhs = bus.reg[(opcode>>16)&15].I; \ - u32 rhs = value; \ - u32 res = lhs + rhs; \ - C_SETCOND_ADD; -#endif -#ifndef OP_ORR - #define OP_ORR \ - u32 res = bus.reg[(opcode >> 16) & 0x0F].I | value; \ - bus.reg[dest].I = res; -#endif -#ifndef OP_ORRS - #define OP_ORRS OP_ORR C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_MOV - #define OP_MOV \ - u32 res = value; \ - bus.reg[dest].I = res; -#endif -#ifndef OP_MOVS - #define OP_MOVS OP_MOV C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_BIC - #define OP_BIC \ - u32 res = bus.reg[(opcode >> 16) & 0x0F].I & (~value); \ - bus.reg[dest].I = res; -#endif -#ifndef OP_BICS - #define OP_BICS OP_BIC C_CHECK_PC(C_SETCOND_LOGICAL) -#endif -#ifndef OP_MVN - #define OP_MVN \ - u32 res = ~value; \ - bus.reg[dest].I = res; -#endif -#ifndef OP_MVNS - #define OP_MVNS OP_MVN C_CHECK_PC(C_SETCOND_LOGICAL) -#endif - -#ifndef SETCOND_NONE - #define SETCOND_NONE /*nothing*/ -#endif -#ifndef SETCOND_MUL - #define SETCOND_MUL \ - N_FLAG = ((s32)bus.reg[dest].I < 0) ? true : false; \ - Z_FLAG = bus.reg[dest].I ? false : true; -#endif -#ifndef SETCOND_MULL - #define SETCOND_MULL \ - N_FLAG = (bus.reg[dest].I & 0x80000000) ? true : false;\ - Z_FLAG = bus.reg[dest].I || bus.reg[acc].I ? false : true; -#endif - -#ifndef ROR_IMM_MSR - #define ROR_IMM_MSR \ - u32 v = opcode & 0xff; \ - value = ((v << (32 - shift)) | (v >> shift)); -#endif -#ifndef ROR_OFFSET - #define ROR_OFFSET \ - offset = ((offset << (32 - shift)) | (offset >> shift)); -#endif -#ifndef RRX_OFFSET - #define RRX_OFFSET \ - offset = ((offset >> 1) | ((int)C_FLAG << 31)); -#endif - -// ALU ops (except multiply) ////////////////////////////////////////////// - -// ALU_INIT: init code (ALU_INIT_C or ALU_INIT_NC) -// GETVALUE: load value and shift/rotate (VALUE_XXX) -// OP: ALU operation (OP_XXX) -// MODECHANGE: MODECHANGE_NO or MODECHANGE_YES -// ISREGSHIFT: 1 for insns of the form ...,Rn LSL/etc Rs; 0 otherwise -// ALU_INIT, GETVALUE and OP are concatenated in order. -#define ALU_INSN(ALU_INIT, GETVALUE, OP, MODECHANGE, ISREGSHIFT) \ - ALU_INIT GETVALUE OP; \ - if ((opcode & 0x0000F000) != 0x0000F000) { \ - clockTicks = 1 + ISREGSHIFT \ - + codeTicksAccessSeq32(bus.armNextPC); \ - } else { \ - MODECHANGE; \ - if (armState) { \ - bus.reg[15].I &= 0xFFFFFFFC; \ - bus.armNextPC = bus.reg[15].I; \ - bus.reg[15].I += 4; \ - ARM_PREFETCH; \ - } else { \ - bus.reg[15].I &= 0xFFFFFFFE; \ - bus.armNextPC = bus.reg[15].I; \ - bus.reg[15].I += 2; \ - THUMB_PREFETCH; \ - } \ - clockTicks = 3 + ISREGSHIFT \ - + codeTicksAccess(bus.armNextPC, BITS_32) \ - + ((codeTicksAccessSeq32(bus.armNextPC)) << 1); \ - } - -#define MODECHANGE_NO /*nothing*/ -#define MODECHANGE_YES if(armMode != (bus.reg[17].I & 0x1f)) CPUSwitchMode(bus.reg[17].I & 0x1f, false, true); - -#define DEFINE_ALU_INSN_C(CODE1, CODE2, OP, MODECHANGE) \ - void arm##CODE1##0(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - void arm##CODE1##1(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - void arm##CODE1##2(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - void arm##CODE1##3(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - void arm##CODE1##4(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - void arm##CODE1##5(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - void arm##CODE1##6(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - void arm##CODE1##7(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - void arm##CODE2##0(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); } -#define DEFINE_ALU_INSN_NC(CODE1, CODE2, OP, MODECHANGE) \ - void arm##CODE1##0(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - void arm##CODE1##1(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - void arm##CODE1##2(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - void arm##CODE1##3(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - void arm##CODE1##4(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - void arm##CODE1##5(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - void arm##CODE1##6(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\ - void arm##CODE1##7(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\ - void arm##CODE2##0(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); } - -// AND -DEFINE_ALU_INSN_NC(00, 20, AND, NO) -// ANDS -DEFINE_ALU_INSN_C (01, 21, ANDS, YES) - -// EOR -DEFINE_ALU_INSN_NC(02, 22, EOR, NO) -// EORS -DEFINE_ALU_INSN_C (03, 23, EORS, YES) - -// SUB -DEFINE_ALU_INSN_NC(04, 24, SUB, NO) -// SUBS -DEFINE_ALU_INSN_NC(05, 25, SUBS, YES) - -// RSB -DEFINE_ALU_INSN_NC(06, 26, RSB, NO) -// RSBS -DEFINE_ALU_INSN_NC(07, 27, RSBS, YES) - -// ADD -DEFINE_ALU_INSN_NC(08, 28, ADD, NO) -// ADDS -DEFINE_ALU_INSN_NC(09, 29, ADDS, YES) - -// ADC -DEFINE_ALU_INSN_NC(0A, 2A, ADC, NO) -// ADCS -DEFINE_ALU_INSN_NC(0B, 2B, ADCS, YES) - -// SBC -DEFINE_ALU_INSN_NC(0C, 2C, SBC, NO) -// SBCS -DEFINE_ALU_INSN_NC(0D, 2D, SBCS, YES) - -// RSC -DEFINE_ALU_INSN_NC(0E, 2E, RSC, NO) -// RSCS -DEFINE_ALU_INSN_NC(0F, 2F, RSCS, YES) - -// TST -DEFINE_ALU_INSN_C (11, 31, TST, NO) - -// TEQ -DEFINE_ALU_INSN_C (13, 33, TEQ, NO) - -// CMP -DEFINE_ALU_INSN_NC(15, 35, CMP, NO) - -// CMN -DEFINE_ALU_INSN_NC(17, 37, CMN, NO) - -// ORR -DEFINE_ALU_INSN_NC(18, 38, ORR, NO) -// ORRS -DEFINE_ALU_INSN_C (19, 39, ORRS, YES) - -// MOV -DEFINE_ALU_INSN_NC(1A, 3A, MOV, NO) -// MOVS -DEFINE_ALU_INSN_C (1B, 3B, MOVS, YES) - -// BIC -DEFINE_ALU_INSN_NC(1C, 3C, BIC, NO) -// BICS -DEFINE_ALU_INSN_C (1D, 3D, BICS, YES) - -// MVN -DEFINE_ALU_INSN_NC(1E, 3E, MVN, NO) -// MVNS -DEFINE_ALU_INSN_C (1F, 3F, MVNS, YES) - -// Multiply instructions ////////////////////////////////////////////////// - -// OP: OP_MUL, OP_MLA etc. -// SETCOND: SETCOND_NONE, SETCOND_MUL, or SETCOND_MULL -// CYCLES: base cycle count (1, 2, or 3) -#define MUL_INSN(OP, SETCOND, CYCLES) \ - int mult = (opcode & 0x0F); \ - u32 rs = bus.reg[(opcode >> 8) & 0x0F].I; \ - int acc = (opcode >> 12) & 0x0F; /* or destLo */ \ - int dest = (opcode >> 16) & 0x0F; /* or destHi */ \ - OP; \ - SETCOND; \ - if ((s32)rs < 0) \ - rs = ~rs; \ - if ((rs & 0xFFFF0000) == 0) \ - clockTicks += 1; \ - else if ((rs & 0xFF000000) == 0) \ - clockTicks += 2; \ - else \ - clockTicks += 3; \ - if (bus.busPrefetchCount == 0) \ - bus.busPrefetchCount = ((bus.busPrefetchCount+1)<> 32); -#define OP_MLAL(SIGN) \ - SIGN##64 res = ((SIGN##64)bus.reg[dest].I<<32 | bus.reg[acc].I)\ - + ((SIGN##64)(SIGN##32)bus.reg[mult].I \ - * (SIGN##64)(SIGN##32)rs); \ - bus.reg[acc].I = (u32)res; \ - bus.reg[dest].I = (u32)(res >> 32); -#define OP_UMULL OP_MULL(u) -#define OP_UMLAL OP_MLAL(u) -#define OP_SMULL OP_MULL(s) -#define OP_SMLAL OP_MLAL(s) - -// MUL Rd, Rm, Rs - void arm009(u32 opcode) { MUL_INSN(OP_MUL, SETCOND_NONE, 1); } -// MULS Rd, Rm, Rs - void arm019(u32 opcode) { MUL_INSN(OP_MUL, SETCOND_MUL, 1); } - -// MLA Rd, Rm, Rs, Rn - void arm029(u32 opcode) { MUL_INSN(OP_MLA, SETCOND_NONE, 2); } -// MLAS Rd, Rm, Rs, Rn - void arm039(u32 opcode) { MUL_INSN(OP_MLA, SETCOND_MUL, 2); } - -// UMULL RdLo, RdHi, Rn, Rs - void arm089(u32 opcode) { MUL_INSN(OP_UMULL, SETCOND_NONE, 2); } -// UMULLS RdLo, RdHi, Rn, Rs - void arm099(u32 opcode) { MUL_INSN(OP_UMULL, SETCOND_MULL, 2); } - -// UMLAL RdLo, RdHi, Rn, Rs - void arm0A9(u32 opcode) { MUL_INSN(OP_UMLAL, SETCOND_NONE, 3); } -// UMLALS RdLo, RdHi, Rn, Rs - void arm0B9(u32 opcode) { MUL_INSN(OP_UMLAL, SETCOND_MULL, 3); } - -// SMULL RdLo, RdHi, Rm, Rs - void arm0C9(u32 opcode) { MUL_INSN(OP_SMULL, SETCOND_NONE, 2); } -// SMULLS RdLo, RdHi, Rm, Rs - void arm0D9(u32 opcode) { MUL_INSN(OP_SMULL, SETCOND_MULL, 2); } - -// SMLAL RdLo, RdHi, Rm, Rs - void arm0E9(u32 opcode) { MUL_INSN(OP_SMLAL, SETCOND_NONE, 3); } -// SMLALS RdLo, RdHi, Rm, Rs - void arm0F9(u32 opcode) { MUL_INSN(OP_SMLAL, SETCOND_MULL, 3); } - -// Misc instructions ////////////////////////////////////////////////////// - -// SWP Rd, Rm, [Rn] - void arm109(u32 opcode) -{ - u32 address = bus.reg[(opcode >> 16) & 15].I; - u32 temp = CPUReadMemory(address); - CPUWriteMemory(address, bus.reg[opcode&15].I); - bus.reg[(opcode >> 12) & 15].I = temp; - int dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 4 + (dataticks_value << 1) + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// SWPB Rd, Rm, [Rn] - void arm149(u32 opcode) -{ - u32 address = bus.reg[(opcode >> 16) & 15].I; - u32 temp = CPUReadByte(address); - CPUWriteByte(address, bus.reg[opcode&15].B.B0); - bus.reg[(opcode>>12)&15].I = temp; - u32 dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 4 + (dataticks_value << 1) + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// MRS Rd, CPSR - void arm100(u32 opcode) -{ - if ((opcode & 0x0FFF0FFF) == 0x010F0000) - { - CPU_UPDATE_CPSR(); - bus.reg[(opcode >> 12) & 0x0F].I = bus.reg[16].I; - } - else - armUnknownInsn(opcode); -} - -// MRS Rd, SPSR - void arm140(u32 opcode) -{ - if ((opcode & 0x0FFF0FFF) == 0x014F0000) - bus.reg[(opcode >> 12) & 0x0F].I = bus.reg[17].I; - else - armUnknownInsn(opcode); -} - -// MSR CPSR_fields, Rm - void arm120(u32 opcode) -{ - if ((opcode & 0x0FF0FFF0) == 0x0120F000) - { - CPU_UPDATE_CPSR(); - u32 value = bus.reg[opcode & 15].I; - u32 newValue = bus.reg[16].I; - if (armMode > 0x10) { - if (opcode & 0x00010000) - newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF); - if (opcode & 0x00020000) - newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00); - if (opcode & 0x00040000) - newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000); - } - if (opcode & 0x00080000) - newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000); - newValue |= 0x10; - if(armMode != (newValue & 0x1F)) - CPUSwitchMode(newValue & 0x1F, false, true); - bus.reg[16].I = newValue; - CPUUpdateFlags(1); - if (!armState) { // this should not be allowed, but it seems to work - THUMB_PREFETCH; - bus.reg[15].I = bus.armNextPC + 2; - } - } - else - armUnknownInsn(opcode); -} - -// MSR SPSR_fields, Rm - void arm160(u32 opcode) -{ - if ((opcode & 0x0FF0FFF0) == 0x0160F000) - { - u32 value = bus.reg[opcode & 15].I; - if (armMode > 0x10 && armMode < 0x1F) - { - if (opcode & 0x00010000) - bus.reg[17].I = (bus.reg[17].I & 0xFFFFFF00) | (value & 0x000000FF); - if (opcode & 0x00020000) - bus.reg[17].I = (bus.reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00); - if (opcode & 0x00040000) - bus.reg[17].I = (bus.reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000); - if (opcode & 0x00080000) - bus.reg[17].I = (bus.reg[17].I & 0x00FFFFFF) | (value & 0xFF000000); - } - } - else - armUnknownInsn(opcode); -} - -// MSR CPSR_fields, # - void arm320(u32 opcode) -{ - if ((opcode & 0x0FF0F000) == 0x0320F000) - { - CPU_UPDATE_CPSR(); - u32 value = opcode & 0xFF; - int shift = (opcode & 0xF00) >> 7; - if (shift) { - ROR_IMM_MSR; - } - u32 newValue = bus.reg[16].I; - if (armMode > 0x10) { - if (opcode & 0x00010000) - newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF); - if (opcode & 0x00020000) - newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00); - if (opcode & 0x00040000) - newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000); - } - if (opcode & 0x00080000) - newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000); - - newValue |= 0x10; - - if(armMode != (newValue & 0x1F)) - CPUSwitchMode(newValue & 0x1F, false, true); - bus.reg[16].I = newValue; - CPUUpdateFlags(1); - if (!armState) { // this should not be allowed, but it seems to work - THUMB_PREFETCH; - bus.reg[15].I = bus.armNextPC + 2; - } - } - else - armUnknownInsn(opcode); -} - -// MSR SPSR_fields, # - void arm360(u32 opcode) -{ - if ((opcode & 0x0FF0F000) == 0x0360F000) { - if (armMode > 0x10 && armMode < 0x1F) { - u32 value = opcode & 0xFF; - int shift = (opcode & 0xF00) >> 7; - if (shift) { - ROR_IMM_MSR; - } - if (opcode & 0x00010000) - bus.reg[17].I = (bus.reg[17].I & 0xFFFFFF00) | (value & 0x000000FF); - if (opcode & 0x00020000) - bus.reg[17].I = (bus.reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00); - if (opcode & 0x00040000) - bus.reg[17].I = (bus.reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000); - if (opcode & 0x00080000) - bus.reg[17].I = (bus.reg[17].I & 0x00FFFFFF) | (value & 0xFF000000); - } - } - else - armUnknownInsn(opcode); -} - -// BX Rm - void arm121(u32 opcode) -{ - if ((opcode & 0x0FFFFFF0) == 0x012FFF10) { - int base = opcode & 0x0F; - bus.busPrefetchCount = 0; - armState = bus.reg[base].I & 1 ? false : true; - if (armState) { - bus.reg[15].I = bus.reg[base].I & 0xFFFFFFFC; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 4; - ARM_PREFETCH; - clockTicks = 3 + (codeTicksAccessSeq32(bus.armNextPC)<<1) - + codeTicksAccess(bus.armNextPC, BITS_32); - } else { - bus.reg[15].I = bus.reg[base].I & 0xFFFFFFFE; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = 3 + (codeTicksAccessSeq16(bus.armNextPC)<<1) - + codeTicksAccess(bus.armNextPC, BITS_16); - } - } - else - armUnknownInsn(opcode); -} - -// Load/store ///////////////////////////////////////////////////////////// - -#define OFFSET_IMM \ - int offset = opcode & 0xFFF; -#define OFFSET_IMM8 \ - int offset = ((opcode & 0x0F) | ((opcode>>4) & 0xF0)); -#define OFFSET_REG \ - int offset = bus.reg[opcode & 15].I; -#define OFFSET_LSL \ - int offset = bus.reg[opcode & 15].I << ((opcode>>7) & 31); -#define OFFSET_LSR \ - int shift = (opcode >> 7) & 31; \ - int offset = shift ? bus.reg[opcode & 15].I >> shift : 0; -#define OFFSET_ASR \ - int shift = (opcode >> 7) & 31; \ - int offset; \ - if (shift) \ - offset = (int)((s32)bus.reg[opcode & 15].I >> shift);\ - else if (bus.reg[opcode & 15].I & 0x80000000) \ - offset = 0xFFFFFFFF; \ - else \ - offset = 0; -#define OFFSET_ROR \ - int shift = (opcode >> 7) & 31; \ - u32 offset = bus.reg[opcode & 15].I; \ - if (shift) { \ - ROR_OFFSET; \ - } else { \ - RRX_OFFSET; \ - } - -#define ADDRESS_POST (bus.reg[base].I) -#define ADDRESS_PREDEC (bus.reg[base].I - offset) -#define ADDRESS_PREINC (bus.reg[base].I + offset) - -#define OP_STR CPUWriteMemory(address, bus.reg[dest].I) -#define OP_STRH CPUWriteHalfWord(address, bus.reg[dest].W.W0) -#define OP_STRB CPUWriteByte(address, bus.reg[dest].B.B0) -#define OP_LDR bus.reg[dest].I = CPUReadMemory(address) -#define OP_LDRH bus.reg[dest].I = CPUReadHalfWord(address) -#define OP_LDRB bus.reg[dest].I = CPUReadByte(address) -#define OP_LDRSH bus.reg[dest].I = (s16)CPUReadHalfWordSigned(address) -#define OP_LDRSB bus.reg[dest].I = (s8)CPUReadByte(address) - -#define WRITEBACK_NONE /*nothing*/ -#define WRITEBACK_PRE bus.reg[base].I = address -#define WRITEBACK_POSTDEC bus.reg[base].I = address - offset -#define WRITEBACK_POSTINC bus.reg[base].I = address + offset - -#define LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS) \ - if (bus.busPrefetchCount == 0) \ - bus.busPrefetch = bus.busPrefetchEnable; \ - int dest = (opcode >> 12) & 15; \ - int base = (opcode >> 16) & 15; \ - CALC_OFFSET; \ - u32 address = CALC_ADDRESS; - -#define STR(CALC_OFFSET, CALC_ADDRESS, STORE_DATA, WRITEBACK1, WRITEBACK2, SIZE) \ - LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \ - WRITEBACK1; \ - STORE_DATA; \ - WRITEBACK2; \ - int dataticks_val; \ - if(SIZE == 32) \ - dataticks_val = DATATICKS_ACCESS_32BIT(address); \ - else \ - dataticks_val = DATATICKS_ACCESS_16BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_val); \ - clockTicks = 2 + dataticks_val + codeTicksAccess(bus.armNextPC, BITS_32); - -#define LDR(CALC_OFFSET, CALC_ADDRESS, LOAD_DATA, WRITEBACK, SIZE) \ - LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \ - LOAD_DATA; \ - if (dest != base) \ - { \ - WRITEBACK; \ - } \ - clockTicks = 0; \ - int dataticks_value; \ - if (dest == 15) { \ - bus.reg[15].I &= 0xFFFFFFFC; \ - bus.armNextPC = bus.reg[15].I; \ - bus.reg[15].I += 4; \ - ARM_PREFETCH; \ - dataticks_value = DATATICKS_ACCESS_32BIT_SEQ(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 2 + (dataticks_value << 1);\ - } \ - if(SIZE == 32) \ - dataticks_value = DATATICKS_ACCESS_32BIT(address); \ - else \ - dataticks_value = DATATICKS_ACCESS_16BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_32); -#define STR_POSTDEC(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTDEC, SIZE) -#define STR_POSTINC(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTINC, SIZE) -#define STR_PREDEC(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE) -#define STR_PREDEC_WB(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE) -#define STR_PREINC(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE) -#define STR_PREINC_WB(CALC_OFFSET, STORE_DATA, SIZE) \ - STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE) -#define LDR_POSTDEC(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTDEC, SIZE) -#define LDR_POSTINC(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTINC, SIZE) -#define LDR_PREDEC(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_NONE, SIZE) -#define LDR_PREDEC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_PRE, SIZE) -#define LDR_PREINC(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_NONE, SIZE) -#define LDR_PREINC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \ - LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_PRE, SIZE) - -// STRH Rd, [Rn], -Rm - void arm00B(u32 opcode) { STR_POSTDEC(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn], #-offset - void arm04B(u32 opcode) { STR_POSTDEC(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn], Rm - void arm08B(u32 opcode) { STR_POSTINC(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn], #offset - void arm0CB(u32 opcode) { STR_POSTINC(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn, -Rm] - void arm10B(u32 opcode) { STR_PREDEC(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn, -Rm]! - void arm12B(u32 opcode) { STR_PREDEC_WB(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn, -#offset] - void arm14B(u32 opcode) { STR_PREDEC(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn, -#offset]! - void arm16B(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn, Rm] - void arm18B(u32 opcode) { STR_PREINC(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn, Rm]! - void arm1AB(u32 opcode) { STR_PREINC_WB(OFFSET_REG, OP_STRH, 16); } -// STRH Rd, [Rn, #offset] - void arm1CB(u32 opcode) { STR_PREINC(OFFSET_IMM8, OP_STRH, 16); } -// STRH Rd, [Rn, #offset]! - void arm1EB(u32 opcode) { STR_PREINC_WB(OFFSET_IMM8, OP_STRH, 16); } - -// LDRH Rd, [Rn], -Rm - void arm01B(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn], #-offset - void arm05B(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn], Rm - void arm09B(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn], #offset - void arm0DB(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn, -Rm] - void arm11B(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn, -Rm]! - void arm13B(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn, -#offset] - void arm15B(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn, -#offset]! - void arm17B(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn, Rm] - void arm19B(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn, Rm]! - void arm1BB(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRH, 16); } -// LDRH Rd, [Rn, #offset] - void arm1DB(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRH, 16); } -// LDRH Rd, [Rn, #offset]! - void arm1FB(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRH, 16); } - -// LDRSB Rd, [Rn], -Rm - void arm01D(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn], #-offset - void arm05D(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn], Rm - void arm09D(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn], #offset - void arm0DD(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, -Rm] - void arm11D(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, -Rm]! - void arm13D(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, -#offset] - void arm15D(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, -#offset]! - void arm17D(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, Rm] - void arm19D(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, Rm]! - void arm1BD(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, #offset] - void arm1DD(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRSB, 16); } -// LDRSB Rd, [Rn, #offset]! - void arm1FD(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRSB, 16); } - -// LDRSH Rd, [Rn], -Rm - void arm01F(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn], #-offset - void arm05F(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn], Rm - void arm09F(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn], #offset - void arm0DF(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, -Rm] - void arm11F(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, -Rm]! - void arm13F(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, -#offset] - void arm15F(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, -#offset]! - void arm17F(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, Rm] - void arm19F(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, Rm]! - void arm1BF(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, #offset] - void arm1DF(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRSH, 16); } -// LDRSH Rd, [Rn, #offset]! - void arm1FF(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRSH, 16); } - -// STR[T] Rd, [Rn], -# -// Note: STR and STRT do the same thing on the GBA (likewise for LDR/LDRT etc) - void arm400(u32 opcode) { STR_POSTDEC(OFFSET_IMM, OP_STR, 32); } -// LDR[T] Rd, [Rn], -# - void arm410(u32 opcode) { LDR_POSTDEC(OFFSET_IMM, OP_LDR, 32); } -// STRB[T] Rd, [Rn], -# - void arm440(u32 opcode) { STR_POSTDEC(OFFSET_IMM, OP_STRB, 16); } -// LDRB[T] Rd, [Rn], -# - void arm450(u32 opcode) { LDR_POSTDEC(OFFSET_IMM, OP_LDRB, 16); } -// STR[T] Rd, [Rn], # - void arm480(u32 opcode) { STR_POSTINC(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn], # - void arm490(u32 opcode) { LDR_POSTINC(OFFSET_IMM, OP_LDR, 32); } -// STRB[T] Rd, [Rn], # - void arm4C0(u32 opcode) { STR_POSTINC(OFFSET_IMM, OP_STRB, 16); } -// LDRB[T] Rd, [Rn], # - void arm4D0(u32 opcode) { LDR_POSTINC(OFFSET_IMM, OP_LDRB, 16); } -// STR Rd, [Rn, -#] - void arm500(u32 opcode) { STR_PREDEC(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn, -#] - void arm510(u32 opcode) { LDR_PREDEC(OFFSET_IMM, OP_LDR, 32); } -// STR Rd, [Rn, -#]! - void arm520(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn, -#]! - void arm530(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM, OP_LDR, 32); } -// STRB Rd, [Rn, -#] - void arm540(u32 opcode) { STR_PREDEC(OFFSET_IMM, OP_STRB, 16); } -// LDRB Rd, [Rn, -#] - void arm550(u32 opcode) { LDR_PREDEC(OFFSET_IMM, OP_LDRB, 16); } -// STRB Rd, [Rn, -#]! - void arm560(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM, OP_STRB, 16); } -// LDRB Rd, [Rn, -#]! - void arm570(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM, OP_LDRB, 16); } -// STR Rd, [Rn, #] - void arm580(u32 opcode) { STR_PREINC(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn, #] - void arm590(u32 opcode) { LDR_PREINC(OFFSET_IMM, OP_LDR, 32); } -// STR Rd, [Rn, #]! - void arm5A0(u32 opcode) { STR_PREINC_WB(OFFSET_IMM, OP_STR, 32); } -// LDR Rd, [Rn, #]! - void arm5B0(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM, OP_LDR, 32); } -// STRB Rd, [Rn, #] - void arm5C0(u32 opcode) { STR_PREINC(OFFSET_IMM, OP_STRB, 16); } -// LDRB Rd, [Rn, #] - void arm5D0(u32 opcode) { LDR_PREINC(OFFSET_IMM, OP_LDRB, 16); } -// STRB Rd, [Rn, #]! - void arm5E0(u32 opcode) { STR_PREINC_WB(OFFSET_IMM, OP_STRB, 16); } -// LDRB Rd, [Rn, #]! - void arm5F0(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM, OP_LDRB, 16); } - -// STR[T] Rd, [Rn], -Rm, LSL # - void arm600(u32 opcode) { STR_POSTDEC(OFFSET_LSL, OP_STR, 32); } -// STR[T] Rd, [Rn], -Rm, LSR # - void arm602(u32 opcode) { STR_POSTDEC(OFFSET_LSR, OP_STR, 32); } -// STR[T] Rd, [Rn], -Rm, ASR # - void arm604(u32 opcode) { STR_POSTDEC(OFFSET_ASR, OP_STR, 32); } -// STR[T] Rd, [Rn], -Rm, ROR # - void arm606(u32 opcode) { STR_POSTDEC(OFFSET_ROR, OP_STR, 32); } -// LDR[T] Rd, [Rn], -Rm, LSL # - void arm610(u32 opcode) { LDR_POSTDEC(OFFSET_LSL, OP_LDR, 32); } -// LDR[T] Rd, [Rn], -Rm, LSR # - void arm612(u32 opcode) { LDR_POSTDEC(OFFSET_LSR, OP_LDR, 32); } -// LDR[T] Rd, [Rn], -Rm, ASR # - void arm614(u32 opcode) { LDR_POSTDEC(OFFSET_ASR, OP_LDR, 32); } -// LDR[T] Rd, [Rn], -Rm, ROR # - void arm616(u32 opcode) { LDR_POSTDEC(OFFSET_ROR, OP_LDR, 32); } -// STRB[T] Rd, [Rn], -Rm, LSL # - void arm640(u32 opcode) { STR_POSTDEC(OFFSET_LSL, OP_STRB, 16); } -// STRB[T] Rd, [Rn], -Rm, LSR # - void arm642(u32 opcode) { STR_POSTDEC(OFFSET_LSR, OP_STRB, 16); } -// STRB[T] Rd, [Rn], -Rm, ASR # - void arm644(u32 opcode) { STR_POSTDEC(OFFSET_ASR, OP_STRB, 16); } -// STRB[T] Rd, [Rn], -Rm, ROR # - void arm646(u32 opcode) { STR_POSTDEC(OFFSET_ROR, OP_STRB, 16); } -// LDRB[T] Rd, [Rn], -Rm, LSL # - void arm650(u32 opcode) { LDR_POSTDEC(OFFSET_LSL, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], -Rm, LSR # - void arm652(u32 opcode) { LDR_POSTDEC(OFFSET_LSR, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], -Rm, ASR # - void arm654(u32 opcode) { LDR_POSTDEC(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn], -Rm, ROR # - void arm656(u32 opcode) { LDR_POSTDEC(OFFSET_ROR, OP_LDRB, 16); } -// STR[T] Rd, [Rn], Rm, LSL # - void arm680(u32 opcode) { STR_POSTINC(OFFSET_LSL, OP_STR, 32); } -// STR[T] Rd, [Rn], Rm, LSR # - void arm682(u32 opcode) { STR_POSTINC(OFFSET_LSR, OP_STR, 32); } -// STR[T] Rd, [Rn], Rm, ASR # - void arm684(u32 opcode) { STR_POSTINC(OFFSET_ASR, OP_STR, 32); } -// STR[T] Rd, [Rn], Rm, ROR # - void arm686(u32 opcode) { STR_POSTINC(OFFSET_ROR, OP_STR, 32); } -// LDR[T] Rd, [Rn], Rm, LSL # - void arm690(u32 opcode) { LDR_POSTINC(OFFSET_LSL, OP_LDR, 32); } -// LDR[T] Rd, [Rn], Rm, LSR # - void arm692(u32 opcode) { LDR_POSTINC(OFFSET_LSR, OP_LDR, 32); } -// LDR[T] Rd, [Rn], Rm, ASR # - void arm694(u32 opcode) { LDR_POSTINC(OFFSET_ASR, OP_LDR, 32); } -// LDR[T] Rd, [Rn], Rm, ROR # - void arm696(u32 opcode) { LDR_POSTINC(OFFSET_ROR, OP_LDR, 32); } -// STRB[T] Rd, [Rn], Rm, LSL # - void arm6C0(u32 opcode) { STR_POSTINC(OFFSET_LSL, OP_STRB, 16); } -// STRB[T] Rd, [Rn], Rm, LSR # - void arm6C2(u32 opcode) { STR_POSTINC(OFFSET_LSR, OP_STRB, 16); } -// STRB[T] Rd, [Rn], Rm, ASR # - void arm6C4(u32 opcode) { STR_POSTINC(OFFSET_ASR, OP_STRB, 16); } -// STRB[T] Rd, [Rn], Rm, ROR # - void arm6C6(u32 opcode) { STR_POSTINC(OFFSET_ROR, OP_STRB, 16); } -// LDRB[T] Rd, [Rn], Rm, LSL # - void arm6D0(u32 opcode) { LDR_POSTINC(OFFSET_LSL, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], Rm, LSR # - void arm6D2(u32 opcode) { LDR_POSTINC(OFFSET_LSR, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], Rm, ASR # - void arm6D4(u32 opcode) { LDR_POSTINC(OFFSET_ASR, OP_LDRB, 16); } -// LDRB[T] Rd, [Rn], Rm, ROR # - void arm6D6(u32 opcode) { LDR_POSTINC(OFFSET_ROR, OP_LDRB, 16); } -// STR Rd, [Rn, -Rm, LSL #] - void arm700(u32 opcode) { STR_PREDEC(OFFSET_LSL, OP_STR, 32); } -// STR Rd, [Rn, -Rm, LSR #] - void arm702(u32 opcode) { STR_PREDEC(OFFSET_LSR, OP_STR, 32); } -// STR Rd, [Rn, -Rm, ASR #] - void arm704(u32 opcode) { STR_PREDEC(OFFSET_ASR, OP_STR, 32); } -// STR Rd, [Rn, -Rm, ROR #] - void arm706(u32 opcode) { STR_PREDEC(OFFSET_ROR, OP_STR, 32); } -// LDR Rd, [Rn, -Rm, LSL #] - void arm710(u32 opcode) { LDR_PREDEC(OFFSET_LSL, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, LSR #] - void arm712(u32 opcode) { LDR_PREDEC(OFFSET_LSR, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, ASR #] - void arm714(u32 opcode) { LDR_PREDEC(OFFSET_ASR, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, ROR #] - void arm716(u32 opcode) { LDR_PREDEC(OFFSET_ROR, OP_LDR, 32); } -// STR Rd, [Rn, -Rm, LSL #]! - void arm720(u32 opcode) { STR_PREDEC_WB(OFFSET_LSL, OP_STR, 32); } -// STR Rd, [Rn, -Rm, LSR #]! - void arm722(u32 opcode) { STR_PREDEC_WB(OFFSET_LSR, OP_STR, 32); } -// STR Rd, [Rn, -Rm, ASR #]! - void arm724(u32 opcode) { STR_PREDEC_WB(OFFSET_ASR, OP_STR, 32); } -// STR Rd, [Rn, -Rm, ROR #]! - void arm726(u32 opcode) { STR_PREDEC_WB(OFFSET_ROR, OP_STR, 32); } -// LDR Rd, [Rn, -Rm, LSL #]! - void arm730(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSL, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, LSR #]! - void arm732(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSR, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, ASR #]! - void arm734(u32 opcode) { LDR_PREDEC_WB(OFFSET_ASR, OP_LDR, 32); } -// LDR Rd, [Rn, -Rm, ROR #]! - void arm736(u32 opcode) { LDR_PREDEC_WB(OFFSET_ROR, OP_LDR, 32); } -// STRB Rd, [Rn, -Rm, LSL #] - void arm740(u32 opcode) { STR_PREDEC(OFFSET_LSL, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, LSR #] - void arm742(u32 opcode) { STR_PREDEC(OFFSET_LSR, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, ASR #] - void arm744(u32 opcode) { STR_PREDEC(OFFSET_ASR, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, ROR #] - void arm746(u32 opcode) { STR_PREDEC(OFFSET_ROR, OP_STRB, 16); } -// LDRB Rd, [Rn, -Rm, LSL #] - void arm750(u32 opcode) { LDR_PREDEC(OFFSET_LSL, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, LSR #] - void arm752(u32 opcode) { LDR_PREDEC(OFFSET_LSR, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, ASR #] - void arm754(u32 opcode) { LDR_PREDEC(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, ROR #] - void arm756(u32 opcode) { LDR_PREDEC(OFFSET_ROR, OP_LDRB, 16); } -// STRB Rd, [Rn, -Rm, LSL #]! - void arm760(u32 opcode) { STR_PREDEC_WB(OFFSET_LSL, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, LSR #]! - void arm762(u32 opcode) { STR_PREDEC_WB(OFFSET_LSR, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, ASR #]! - void arm764(u32 opcode) { STR_PREDEC_WB(OFFSET_ASR, OP_STRB, 16); } -// STRB Rd, [Rn, -Rm, ROR #]! - void arm766(u32 opcode) { STR_PREDEC_WB(OFFSET_ROR, OP_STRB, 16); } -// LDRB Rd, [Rn, -Rm, LSL #]! - void arm770(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSL, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, LSR #]! - void arm772(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSR, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, ASR #]! - void arm774(u32 opcode) { LDR_PREDEC_WB(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn, -Rm, ROR #]! - void arm776(u32 opcode) { LDR_PREDEC_WB(OFFSET_ROR, OP_LDRB, 16); } -// STR Rd, [Rn, Rm, LSL #] - void arm780(u32 opcode) { STR_PREINC(OFFSET_LSL, OP_STR, 32); } -// STR Rd, [Rn, Rm, LSR #] - void arm782(u32 opcode) { STR_PREINC(OFFSET_LSR, OP_STR, 32); } -// STR Rd, [Rn, Rm, ASR #] - void arm784(u32 opcode) { STR_PREINC(OFFSET_ASR, OP_STR, 32); } -// STR Rd, [Rn, Rm, ROR #] - void arm786(u32 opcode) { STR_PREINC(OFFSET_ROR, OP_STR, 32); } -// LDR Rd, [Rn, Rm, LSL #] - void arm790(u32 opcode) { LDR_PREINC(OFFSET_LSL, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, LSR #] - void arm792(u32 opcode) { LDR_PREINC(OFFSET_LSR, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, ASR #] - void arm794(u32 opcode) { LDR_PREINC(OFFSET_ASR, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, ROR #] - void arm796(u32 opcode) { LDR_PREINC(OFFSET_ROR, OP_LDR, 32); } -// STR Rd, [Rn, Rm, LSL #]! - void arm7A0(u32 opcode) { STR_PREINC_WB(OFFSET_LSL, OP_STR, 32); } -// STR Rd, [Rn, Rm, LSR #]! - void arm7A2(u32 opcode) { STR_PREINC_WB(OFFSET_LSR, OP_STR, 32); } -// STR Rd, [Rn, Rm, ASR #]! - void arm7A4(u32 opcode) { STR_PREINC_WB(OFFSET_ASR, OP_STR, 32); } -// STR Rd, [Rn, Rm, ROR #]! - void arm7A6(u32 opcode) { STR_PREINC_WB(OFFSET_ROR, OP_STR, 32); } -// LDR Rd, [Rn, Rm, LSL #]! - void arm7B0(u32 opcode) { LDR_PREINC_WB(OFFSET_LSL, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, LSR #]! - void arm7B2(u32 opcode) { LDR_PREINC_WB(OFFSET_LSR, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, ASR #]! - void arm7B4(u32 opcode) { LDR_PREINC_WB(OFFSET_ASR, OP_LDR, 32); } -// LDR Rd, [Rn, Rm, ROR #]! - void arm7B6(u32 opcode) { LDR_PREINC_WB(OFFSET_ROR, OP_LDR, 32); } -// STRB Rd, [Rn, Rm, LSL #] - void arm7C0(u32 opcode) { STR_PREINC(OFFSET_LSL, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, LSR #] - void arm7C2(u32 opcode) { STR_PREINC(OFFSET_LSR, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, ASR #] - void arm7C4(u32 opcode) { STR_PREINC(OFFSET_ASR, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, ROR #] - void arm7C6(u32 opcode) { STR_PREINC(OFFSET_ROR, OP_STRB, 16); } -// LDRB Rd, [Rn, Rm, LSL #] - void arm7D0(u32 opcode) { LDR_PREINC(OFFSET_LSL, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, LSR #] - void arm7D2(u32 opcode) { LDR_PREINC(OFFSET_LSR, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, ASR #] - void arm7D4(u32 opcode) { LDR_PREINC(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, ROR #] - void arm7D6(u32 opcode) { LDR_PREINC(OFFSET_ROR, OP_LDRB, 16); } -// STRB Rd, [Rn, Rm, LSL #]! - void arm7E0(u32 opcode) { STR_PREINC_WB(OFFSET_LSL, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, LSR #]! - void arm7E2(u32 opcode) { STR_PREINC_WB(OFFSET_LSR, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, ASR #]! - void arm7E4(u32 opcode) { STR_PREINC_WB(OFFSET_ASR, OP_STRB, 16); } -// STRB Rd, [Rn, Rm, ROR #]! - void arm7E6(u32 opcode) { STR_PREINC_WB(OFFSET_ROR, OP_STRB, 16); } -// LDRB Rd, [Rn, Rm, LSL #]! - void arm7F0(u32 opcode) { LDR_PREINC_WB(OFFSET_LSL, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, LSR #]! - void arm7F2(u32 opcode) { LDR_PREINC_WB(OFFSET_LSR, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, ASR #]! - void arm7F4(u32 opcode) { LDR_PREINC_WB(OFFSET_ASR, OP_LDRB, 16); } -// LDRB Rd, [Rn, Rm, ROR #]! - void arm7F6(u32 opcode) { LDR_PREINC_WB(OFFSET_ROR, OP_LDRB, 16); } - -// STM/LDM //////////////////////////////////////////////////////////////// - -#define STM_REG(bit,num) \ - if (opcode & (1U<<(bit))) { \ - CPUWriteMemory(address, bus.reg[(num)].I); \ - int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 1 + dataticks_value; \ - count++; \ - address += 4; \ - } -#define STMW_REG(bit,num) \ - if (opcode & (1U<<(bit))) { \ - CPUWriteMemory(address, bus.reg[(num)].I); \ - int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 1 + dataticks_value; \ - bus.reg[base].I = temp; \ - count++; \ - address += 4; \ - } -#define LDM_REG(bit,num) \ - if (opcode & (1U<<(bit))) { \ - int dataticks_value; \ - bus.reg[(num)].I = CPUReadMemory(address); \ - dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 1 + dataticks_value; \ - count++; \ - address += 4; \ - } -#define STM_LOW(STORE_REG) \ - STORE_REG(0, 0); \ - STORE_REG(1, 1); \ - STORE_REG(2, 2); \ - STORE_REG(3, 3); \ - STORE_REG(4, 4); \ - STORE_REG(5, 5); \ - STORE_REG(6, 6); \ - STORE_REG(7, 7); -#define STM_HIGH(STORE_REG) \ - STORE_REG(8, 8); \ - STORE_REG(9, 9); \ - STORE_REG(10, 10); \ - STORE_REG(11, 11); \ - STORE_REG(12, 12); \ - STORE_REG(13, 13); \ - STORE_REG(14, 14); -#define STM_HIGH_2(STORE_REG) \ - if (armMode == 0x11) { \ - STORE_REG(8, R8_FIQ); \ - STORE_REG(9, R9_FIQ); \ - STORE_REG(10, R10_FIQ); \ - STORE_REG(11, R11_FIQ); \ - STORE_REG(12, R12_FIQ); \ - } else { \ - STORE_REG(8, 8); \ - STORE_REG(9, 9); \ - STORE_REG(10, 10); \ - STORE_REG(11, 11); \ - STORE_REG(12, 12); \ - } \ - if (armMode != 0x10 && armMode != 0x1F) { \ - STORE_REG(13, R13_USR); \ - STORE_REG(14, R14_USR); \ - } else { \ - STORE_REG(13, 13); \ - STORE_REG(14, 14); \ - } -#define STM_PC \ - if (opcode & (1U<<15)) { \ - CPUWriteMemory(address, bus.reg[15].I+4); \ - int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 1 + dataticks_value; \ - count++; \ - } -#define STMW_PC \ - if (opcode & (1U<<15)) { \ - CPUWriteMemory(address, bus.reg[15].I+4); \ - int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 1 + dataticks_value; \ - bus.reg[base].I = temp; \ - count++; \ - } -#define LDM_LOW \ - LDM_REG(0, 0); \ - LDM_REG(1, 1); \ - LDM_REG(2, 2); \ - LDM_REG(3, 3); \ - LDM_REG(4, 4); \ - LDM_REG(5, 5); \ - LDM_REG(6, 6); \ - LDM_REG(7, 7); -#define LDM_HIGH \ - LDM_REG(8, 8); \ - LDM_REG(9, 9); \ - LDM_REG(10, 10); \ - LDM_REG(11, 11); \ - LDM_REG(12, 12); \ - LDM_REG(13, 13); \ - LDM_REG(14, 14); -#define LDM_HIGH_2 \ - if (armMode == 0x11) { \ - LDM_REG(8, R8_FIQ); \ - LDM_REG(9, R9_FIQ); \ - LDM_REG(10, R10_FIQ); \ - LDM_REG(11, R11_FIQ); \ - LDM_REG(12, R12_FIQ); \ - } else { \ - LDM_REG(8, 8); \ - LDM_REG(9, 9); \ - LDM_REG(10, 10); \ - LDM_REG(11, 11); \ - LDM_REG(12, 12); \ - } \ - if (armMode != 0x10 && armMode != 0x1F) { \ - LDM_REG(13, R13_USR); \ - LDM_REG(14, R14_USR); \ - } else { \ - LDM_REG(13, 13); \ - LDM_REG(14, 14); \ - } -#define STM_ALL \ - STM_LOW(STM_REG); \ - STM_HIGH(STM_REG); \ - STM_PC; -#define STMW_ALL \ - STM_LOW(STMW_REG); \ - STM_HIGH(STMW_REG); \ - STMW_PC; -#define LDM_ALL \ - LDM_LOW; \ - LDM_HIGH; \ - if (opcode & (1U<<15)) { \ - bus.reg[15].I = CPUReadMemory(address); \ - int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 1 + dataticks_value; \ - count++; \ - } \ - if (opcode & (1U<<15)) { \ - bus.armNextPC = bus.reg[15].I; \ - bus.reg[15].I += 4; \ - ARM_PREFETCH; \ - clockTicks += 1 + codeTicksAccessSeq32(bus.armNextPC);\ - } -#define STM_ALL_2 \ - STM_LOW(STM_REG); \ - STM_HIGH_2(STM_REG); \ - STM_PC; -#define STMW_ALL_2 \ - STM_LOW(STMW_REG); \ - STM_HIGH_2(STMW_REG); \ - STMW_PC; -#define LDM_ALL_2 \ - LDM_LOW; \ - if (opcode & (1U<<15)) { \ - LDM_HIGH; \ - bus.reg[15].I = CPUReadMemory(address); \ - int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 1 + dataticks_value; \ - count++; \ - } else { \ - LDM_HIGH_2; \ - } -#define LDM_ALL_2B \ - if (opcode & (1U<<15)) { \ - if(armMode != (bus.reg[17].I & 0x1F)) \ - CPUSwitchMode(bus.reg[17].I & 0x1F, false, true); \ - if (armState) { \ - bus.armNextPC = bus.reg[15].I & 0xFFFFFFFC; \ - bus.reg[15].I = bus.armNextPC + 4; \ - ARM_PREFETCH; \ - } else { \ - bus.armNextPC = bus.reg[15].I & 0xFFFFFFFE; \ - bus.reg[15].I = bus.armNextPC + 2; \ - THUMB_PREFETCH; \ - } \ - clockTicks += 1 + codeTicksAccessSeq32(bus.armNextPC);\ - } - - -// STMDA Rn, {Rlist} - void arm800(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - STM_ALL; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMDA Rn, {Rlist} - void arm810(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMDA Rn!, {Rlist} - void arm820(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp+4) & 0xFFFFFFFC; - int count = 0; - STMW_ALL; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMDA Rn!, {Rlist} - void arm830(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); - if (!(opcode & (1U << base))) - bus.reg[base].I = temp; -} - -// STMDA Rn, {Rlist}^ - void arm840(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp+4) & 0xFFFFFFFC; - int count = 0; - STM_ALL_2; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMDA Rn, {Rlist}^ - void arm850(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMDA Rn!, {Rlist}^ - void arm860(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp+4) & 0xFFFFFFFC; - int count = 0; - STMW_ALL_2; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMDA Rn!, {Rlist}^ - void arm870(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (temp + 4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - if (!(opcode & (1U << base))) - bus.reg[base].I = temp; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMIA Rn, {Rlist} - void arm880(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = bus.reg[base].I & 0xFFFFFFFC; - int count = 0; - STM_ALL; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMIA Rn, {Rlist} - void arm890(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = bus.reg[base].I & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMIA Rn!, {Rlist} - void arm8A0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = bus.reg[base].I & 0xFFFFFFFC; - int count = 0; - u32 temp = bus.reg[base].I + - 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); - STMW_ALL; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMIA Rn!, {Rlist} - void arm8B0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I + - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = bus.reg[base].I & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); - if (!(opcode & (1U << base))) - bus.reg[base].I = temp; -} - -// STMIA Rn, {Rlist}^ - void arm8C0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = bus.reg[base].I & 0xFFFFFFFC; - int count = 0; - STM_ALL_2; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMIA Rn, {Rlist}^ - void arm8D0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = bus.reg[base].I & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMIA Rn!, {Rlist}^ - void arm8E0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = bus.reg[base].I & 0xFFFFFFFC; - int count = 0; - u32 temp = bus.reg[base].I + - 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); - STMW_ALL_2; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMIA Rn!, {Rlist}^ - void arm8F0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I + - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = bus.reg[base].I & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - if (!(opcode & (1U << base))) - bus.reg[base].I = temp; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMDB Rn, {Rlist} - void arm900(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - STM_ALL; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMDB Rn, {Rlist} - void arm910(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMDB Rn!, {Rlist} - void arm920(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - STMW_ALL; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMDB Rn!, {Rlist} - void arm930(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); - if (!(opcode & (1U << base))) - bus.reg[base].I = temp; -} - -// STMDB Rn, {Rlist}^ - void arm940(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - STM_ALL_2; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMDB Rn, {Rlist}^ - void arm950(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMDB Rn!, {Rlist}^ - void arm960(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - STMW_ALL_2; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMDB Rn!, {Rlist}^ - void arm970(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I - - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = temp & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - if (!(opcode & (1U << base))) - bus.reg[base].I = temp; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMIB Rn, {Rlist} - void arm980(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - STM_ALL; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMIB Rn, {Rlist} - void arm990(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMIB Rn!, {Rlist} - void arm9A0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - u32 temp = bus.reg[base].I + - 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); - STMW_ALL; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMIB Rn!, {Rlist} - void arm9B0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I + - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); - if (!(opcode & (1U << base))) - bus.reg[base].I = temp; -} - -// STMIB Rn, {Rlist}^ - void arm9C0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - STM_ALL_2; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMIB Rn, {Rlist}^ - void arm9D0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// STMIB Rn!, {Rlist}^ - void arm9E0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - u32 temp = bus.reg[base].I + - 4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]); - STMW_ALL_2; - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// LDMIB Rn!, {Rlist}^ - void arm9F0(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int base = (opcode & 0x000F0000) >> 16; - u32 temp = bus.reg[base].I + - 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); - u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC; - int count = 0; - LDM_ALL_2; - if (!(opcode & (1U << base))) - bus.reg[base].I = temp; - LDM_ALL_2B; - clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32); -} - -// B/BL/SWI and (unimplemented) coproc support //////////////////////////// - -// B - void armA00(u32 opcode) -{ - int codeTicksVal = 0; - int ct = 0; - int offset = opcode & 0x00FFFFFF; - if (offset & 0x00800000) - offset |= 0xFF000000; // negative offset - bus.reg[15].I += offset<<2; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 4; - ARM_PREFETCH; - - codeTicksVal = codeTicksAccessSeq32(bus.armNextPC); - ct = codeTicksVal + 3; - ct += 2 + codeTicksAccess(bus.armNextPC, BITS_32) + codeTicksVal; - - bus.busPrefetchCount = 0; - clockTicks = ct; -} - -// BL - void armB00(u32 opcode) -{ - int codeTicksVal = 0; - int ct = 0; - - int offset = opcode & 0x00FFFFFF; - if (offset & 0x00800000) - offset |= 0xFF000000; // negative offset - bus.reg[14].I = bus.reg[15].I - 4; - bus.reg[15].I += offset<<2; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 4; - ARM_PREFETCH; - - codeTicksVal = codeTicksAccessSeq32(bus.armNextPC); - ct = codeTicksVal + 3; - ct += 2 + codeTicksAccess(bus.armNextPC, BITS_32) + codeTicksVal; - - bus.busPrefetchCount = 0; - clockTicks = ct; -} - -#define armE01 armUnknownInsn - -// SWI - void armF00(u32 opcode) -{ - int codeTicksVal = 0; - int ct = 0; - - codeTicksVal = codeTicksAccessSeq32(bus.armNextPC); - ct = codeTicksVal + 3; - ct += 2 + codeTicksAccess(bus.armNextPC, BITS_32) + codeTicksVal; - - bus.busPrefetchCount = 0; - - clockTicks = ct; - CPUSoftwareInterrupt(opcode & 0x00FFFFFF); - -} - -// Instruction table ////////////////////////////////////////////////////// - -static void (Gigazoid::*const armInsnTable[4096])(u32 opcode); - -// Wrapper routine (execution loop) /////////////////////////////////////// -int armExecute (void) -{ - CACHE_PREFETCH(clockTicks); - - u32 cond1; - u32 cond2; - - int ct = 0; - - do - { - - clockTicks = 0; - - if ((bus.armNextPC & 0x0803FFFF) == 0x08020000) - bus.busPrefetchCount = 0x100; - - u32 opcode = cpuPrefetch[0]; - cpuPrefetch[0] = cpuPrefetch[1]; - - bus.busPrefetch = false; - int32_t busprefetch_mask = ((bus.busPrefetchCount & 0xFFFFFE00) | -(bus.busPrefetchCount & 0xFFFFFE00)) >> 31; - bus.busPrefetchCount = (0x100 | (bus.busPrefetchCount & 0xFF) & busprefetch_mask) | (bus.busPrefetchCount & ~busprefetch_mask); -#if 0 - if (bus.busPrefetchCount & 0xFFFFFE00) - bus.busPrefetchCount = 0x100 | (bus.busPrefetchCount & 0xFF); -#endif - - - int oldArmNextPC = bus.armNextPC; - - bus.armNextPC = bus.reg[15].I; - if (traceCallback) - traceCallback(bus.armNextPC, opcode); - if (fetchCallback) - fetchCallback(bus.armNextPC); - bus.reg[15].I += 4; - ARM_PREFETCH_NEXT; - - int cond = opcode >> 28; - bool cond_res = true; - if (cond != 0x0E) { // most opcodes are AL (always) - switch(cond) { - case 0x00: // EQ - cond_res = Z_FLAG; - break; - case 0x01: // NE - cond_res = !Z_FLAG; - break; - case 0x02: // CS - cond_res = C_FLAG; - break; - case 0x03: // CC - cond_res = !C_FLAG; - break; - case 0x04: // MI - cond_res = N_FLAG; - break; - case 0x05: // PL - cond_res = !N_FLAG; - break; - case 0x06: // VS - cond_res = V_FLAG; - break; - case 0x07: // VC - cond_res = !V_FLAG; - break; - case 0x08: // HI - cond_res = C_FLAG && !Z_FLAG; - break; - case 0x09: // LS - cond_res = !C_FLAG || Z_FLAG; - break; - case 0x0A: // GE - cond_res = N_FLAG == V_FLAG; - break; - case 0x0B: // LT - cond_res = N_FLAG != V_FLAG; - break; - case 0x0C: // GT - cond_res = !Z_FLAG &&(N_FLAG == V_FLAG); - break; - case 0x0D: // LE - cond_res = Z_FLAG || (N_FLAG != V_FLAG); - break; - case 0x0E: // AL (impossible, checked above) - cond_res = true; - break; - case 0x0F: - default: - // ??? - cond_res = false; - break; - } - } - - if (cond_res) - { - cond1 = (opcode>>16)&0xFF0; - cond2 = (opcode>>4)&0x0F; - - (this->*armInsnTable[(cond1| cond2)])(opcode); - - } - ct = clockTicks; - - if (ct < 0) - return 0; - - /// better pipelining - - if (ct == 0) - clockTicks = 1 + codeTicksAccessSeq32(oldArmNextPC); - - cpuTotalTicks += clockTicks; - -} while ((cpuTotalTicks < cpuNextEvent) & armState & ~holdState); - return 1; -} - - -/*============================================================ - GBA THUMB CORE -============================================================ */ - - void thumbUnknownInsn(u32 opcode) -{ - u32 PC = bus.reg[15].I; - bool savedArmState = armState; - if(armMode != 0x1b) - CPUSwitchMode(0x1b, true, false); - bus.reg[14].I = PC - (savedArmState ? 4 : 2); - bus.reg[15].I = 0x04; - armState = true; - armIrqEnable = false; - bus.armNextPC = 0x04; - ARM_PREFETCH; - bus.reg[15].I += 4; -} - -#define NEG(i) ((i) >> 31) -#define POS(i) ((~(i)) >> 31) - -// C core -#ifndef ADDCARRY - #define ADDCARRY(a, b, c) \ - C_FLAG = ((NEG(a) & NEG(b)) |\ - (NEG(a) & POS(c)) |\ - (NEG(b) & POS(c))) ? true : false; -#endif - -#ifndef ADDOVERFLOW - #define ADDOVERFLOW(a, b, c) \ - V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\ - (POS(a) & POS(b) & NEG(c))) ? true : false; -#endif - -#ifndef SUBCARRY - #define SUBCARRY(a, b, c) \ - C_FLAG = ((NEG(a) & POS(b)) |\ - (NEG(a) & POS(c)) |\ - (POS(b) & POS(c))) ? true : false; -#endif - -#ifndef SUBOVERFLOW - #define SUBOVERFLOW(a, b, c)\ - V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\ - (POS(a) & NEG(b) & NEG(c))) ? true : false; -#endif - -#ifndef ADD_RD_RS_RN - #define ADD_RD_RS_RN(N) \ - {\ - u32 lhs = bus.reg[source].I;\ - u32 rhs = bus.reg[N].I;\ - u32 res = lhs + rhs;\ - bus.reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif - -#ifndef ADD_RD_RS_O3 - #define ADD_RD_RS_O3(N) \ - {\ - u32 lhs = bus.reg[source].I;\ - u32 rhs = N;\ - u32 res = lhs + rhs;\ - bus.reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif - -#ifndef ADD_RD_RS_O3_0 -# define ADD_RD_RS_O3_0 ADD_RD_RS_O3 -#endif - -#ifndef ADD_RN_O8 - #define ADD_RN_O8(d) \ - {\ - u32 lhs = bus.reg[(d)].I;\ - u32 rhs = (opcode & 255);\ - u32 res = lhs + rhs;\ - bus.reg[(d)].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif - -#ifndef CMN_RD_RS - #define CMN_RD_RS \ - {\ - u32 lhs = bus.reg[dest].I;\ - u32 rhs = value;\ - u32 res = lhs + rhs;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif - -#ifndef ADC_RD_RS - #define ADC_RD_RS \ - {\ - u32 lhs = bus.reg[dest].I;\ - u32 rhs = value;\ - u32 res = lhs + rhs + (u32)C_FLAG;\ - bus.reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - ADDCARRY(lhs, rhs, res);\ - ADDOVERFLOW(lhs, rhs, res);\ - } -#endif - -#ifndef SUB_RD_RS_RN - #define SUB_RD_RS_RN(N) \ - {\ - u32 lhs = bus.reg[source].I;\ - u32 rhs = bus.reg[N].I;\ - u32 res = lhs - rhs;\ - bus.reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif - -#ifndef SUB_RD_RS_O3 - #define SUB_RD_RS_O3(N) \ - {\ - u32 lhs = bus.reg[source].I;\ - u32 rhs = N;\ - u32 res = lhs - rhs;\ - bus.reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif - -#ifndef SUB_RD_RS_O3_0 -# define SUB_RD_RS_O3_0 SUB_RD_RS_O3 -#endif -#ifndef SUB_RN_O8 - #define SUB_RN_O8(d) \ - {\ - u32 lhs = bus.reg[(d)].I;\ - u32 rhs = (opcode & 255);\ - u32 res = lhs - rhs;\ - bus.reg[(d)].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef MOV_RN_O8 - #define MOV_RN_O8(d) \ - {\ - u32 val;\ - val = (opcode & 255);\ - bus.reg[d].I = val;\ - N_FLAG = false;\ - Z_FLAG = (val ? false : true);\ - } -#endif -#ifndef CMP_RN_O8 - #define CMP_RN_O8(d) \ - {\ - u32 lhs = bus.reg[(d)].I;\ - u32 rhs = (opcode & 255);\ - u32 res = lhs - rhs;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef SBC_RD_RS - #define SBC_RD_RS \ - {\ - u32 lhs = bus.reg[dest].I;\ - u32 rhs = value;\ - u32 res = lhs - rhs - !((u32)C_FLAG);\ - bus.reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef LSL_RD_RM_I5 - #define LSL_RD_RM_I5 \ - {\ - C_FLAG = (bus.reg[source].I >> (32 - shift)) & 1 ? true : false;\ - value = bus.reg[source].I << shift;\ - } -#endif -#ifndef LSL_RD_RS - #define LSL_RD_RS \ - {\ - C_FLAG = (bus.reg[dest].I >> (32 - value)) & 1 ? true : false;\ - value = bus.reg[dest].I << value;\ - } -#endif -#ifndef LSR_RD_RM_I5 - #define LSR_RD_RM_I5 \ - {\ - C_FLAG = (bus.reg[source].I >> (shift - 1)) & 1 ? true : false;\ - value = bus.reg[source].I >> shift;\ - } -#endif -#ifndef LSR_RD_RS - #define LSR_RD_RS \ - {\ - C_FLAG = (bus.reg[dest].I >> (value - 1)) & 1 ? true : false;\ - value = bus.reg[dest].I >> value;\ - } -#endif -#ifndef ASR_RD_RM_I5 - #define ASR_RD_RM_I5 \ - {\ - C_FLAG = ((s32)bus.reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\ - value = (s32)bus.reg[source].I >> (int)shift;\ - } -#endif -#ifndef ASR_RD_RS - #define ASR_RD_RS \ - {\ - C_FLAG = ((s32)bus.reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\ - value = (s32)bus.reg[dest].I >> (int)value;\ - } -#endif -#ifndef ROR_RD_RS - #define ROR_RD_RS \ - {\ - C_FLAG = (bus.reg[dest].I >> (value - 1)) & 1 ? true : false;\ - value = ((bus.reg[dest].I << (32 - value)) |\ - (bus.reg[dest].I >> value));\ - } -#endif -#ifndef NEG_RD_RS - #define NEG_RD_RS \ - {\ - u32 lhs = bus.reg[source].I;\ - u32 rhs = 0;\ - u32 res = rhs - lhs;\ - bus.reg[dest].I = res;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(rhs, lhs, res);\ - SUBOVERFLOW(rhs, lhs, res);\ - } -#endif -#ifndef CMP_RD_RS - #define CMP_RD_RS \ - {\ - u32 lhs = bus.reg[dest].I;\ - u32 rhs = value;\ - u32 res = lhs - rhs;\ - Z_FLAG = (res == 0) ? true : false;\ - N_FLAG = NEG(res) ? true : false;\ - SUBCARRY(lhs, rhs, res);\ - SUBOVERFLOW(lhs, rhs, res);\ - } -#endif -#ifndef IMM5_INSN - #define IMM5_INSN(OP,N) \ - int dest = opcode & 0x07;\ - int source = (opcode >> 3) & 0x07;\ - u32 value;\ - OP(N);\ - bus.reg[dest].I = value;\ - N_FLAG = (value & 0x80000000 ? true : false);\ - Z_FLAG = (value ? false : true); - #define IMM5_INSN_0(OP) \ - int dest = opcode & 0x07;\ - int source = (opcode >> 3) & 0x07;\ - u32 value;\ - OP;\ - bus.reg[dest].I = value;\ - N_FLAG = (value & 0x80000000 ? true : false);\ - Z_FLAG = (value ? false : true); - #define IMM5_LSL(N) \ - int shift = N;\ - LSL_RD_RM_I5; - #define IMM5_LSL_0 \ - value = bus.reg[source].I; - #define IMM5_LSR(N) \ - int shift = N;\ - LSR_RD_RM_I5; - #define IMM5_LSR_0 \ - C_FLAG = bus.reg[source].I & 0x80000000 ? true : false;\ - value = 0; - #define IMM5_ASR(N) \ - int shift = N;\ - ASR_RD_RM_I5; - #define IMM5_ASR_0 \ - if(bus.reg[source].I & 0x80000000) {\ - value = 0xFFFFFFFF;\ - C_FLAG = true;\ - } else {\ - value = 0;\ - C_FLAG = false;\ - } -#endif -#ifndef THREEARG_INSN - #define THREEARG_INSN(OP,N) \ - int dest = opcode & 0x07; \ - int source = (opcode >> 3) & 0x07; \ - OP(N); -#endif - -// Shift instructions ///////////////////////////////////////////////////// - -#define DEFINE_IMM5_INSN(OP,BASE) \ - void thumb##BASE##_00(u32 opcode) { IMM5_INSN_0(OP##_0); } \ - void thumb##BASE##_01(u32 opcode) { IMM5_INSN(OP, 1); } \ - void thumb##BASE##_02(u32 opcode) { IMM5_INSN(OP, 2); } \ - void thumb##BASE##_03(u32 opcode) { IMM5_INSN(OP, 3); } \ - void thumb##BASE##_04(u32 opcode) { IMM5_INSN(OP, 4); } \ - void thumb##BASE##_05(u32 opcode) { IMM5_INSN(OP, 5); } \ - void thumb##BASE##_06(u32 opcode) { IMM5_INSN(OP, 6); } \ - void thumb##BASE##_07(u32 opcode) { IMM5_INSN(OP, 7); } \ - void thumb##BASE##_08(u32 opcode) { IMM5_INSN(OP, 8); } \ - void thumb##BASE##_09(u32 opcode) { IMM5_INSN(OP, 9); } \ - void thumb##BASE##_0A(u32 opcode) { IMM5_INSN(OP,10); } \ - void thumb##BASE##_0B(u32 opcode) { IMM5_INSN(OP,11); } \ - void thumb##BASE##_0C(u32 opcode) { IMM5_INSN(OP,12); } \ - void thumb##BASE##_0D(u32 opcode) { IMM5_INSN(OP,13); } \ - void thumb##BASE##_0E(u32 opcode) { IMM5_INSN(OP,14); } \ - void thumb##BASE##_0F(u32 opcode) { IMM5_INSN(OP,15); } \ - void thumb##BASE##_10(u32 opcode) { IMM5_INSN(OP,16); } \ - void thumb##BASE##_11(u32 opcode) { IMM5_INSN(OP,17); } \ - void thumb##BASE##_12(u32 opcode) { IMM5_INSN(OP,18); } \ - void thumb##BASE##_13(u32 opcode) { IMM5_INSN(OP,19); } \ - void thumb##BASE##_14(u32 opcode) { IMM5_INSN(OP,20); } \ - void thumb##BASE##_15(u32 opcode) { IMM5_INSN(OP,21); } \ - void thumb##BASE##_16(u32 opcode) { IMM5_INSN(OP,22); } \ - void thumb##BASE##_17(u32 opcode) { IMM5_INSN(OP,23); } \ - void thumb##BASE##_18(u32 opcode) { IMM5_INSN(OP,24); } \ - void thumb##BASE##_19(u32 opcode) { IMM5_INSN(OP,25); } \ - void thumb##BASE##_1A(u32 opcode) { IMM5_INSN(OP,26); } \ - void thumb##BASE##_1B(u32 opcode) { IMM5_INSN(OP,27); } \ - void thumb##BASE##_1C(u32 opcode) { IMM5_INSN(OP,28); } \ - void thumb##BASE##_1D(u32 opcode) { IMM5_INSN(OP,29); } \ - void thumb##BASE##_1E(u32 opcode) { IMM5_INSN(OP,30); } \ - void thumb##BASE##_1F(u32 opcode) { IMM5_INSN(OP,31); } - -// LSL Rd, Rm, #Imm 5 -DEFINE_IMM5_INSN(IMM5_LSL,00) -// LSR Rd, Rm, #Imm 5 -DEFINE_IMM5_INSN(IMM5_LSR,08) -// ASR Rd, Rm, #Imm 5 -DEFINE_IMM5_INSN(IMM5_ASR,10) - -// 3-argument ADD/SUB ///////////////////////////////////////////////////// - -#define DEFINE_REG3_INSN(OP,BASE) \ - void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP,0); } \ - void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \ - void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \ - void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \ - void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \ - void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \ - void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \ - void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); } - -#define DEFINE_IMM3_INSN(OP,BASE) \ - void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP##_0,0); } \ - void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \ - void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \ - void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \ - void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \ - void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \ - void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \ - void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); } - -// ADD Rd, Rs, Rn -DEFINE_REG3_INSN(ADD_RD_RS_RN,18) -// SUB Rd, Rs, Rn -DEFINE_REG3_INSN(SUB_RD_RS_RN,1A) -// ADD Rd, Rs, #Offset3 -DEFINE_IMM3_INSN(ADD_RD_RS_O3,1C) -// SUB Rd, Rs, #Offset3 -DEFINE_IMM3_INSN(SUB_RD_RS_O3,1E) - -// MOV/CMP/ADD/SUB immediate ////////////////////////////////////////////// - -// MOV R0, #Offset8 - void thumb20(u32 opcode) { MOV_RN_O8(0); } -// MOV R1, #Offset8 - void thumb21(u32 opcode) { MOV_RN_O8(1); } -// MOV R2, #Offset8 - void thumb22(u32 opcode) { MOV_RN_O8(2); } -// MOV R3, #Offset8 - void thumb23(u32 opcode) { MOV_RN_O8(3); } -// MOV R4, #Offset8 - void thumb24(u32 opcode) { MOV_RN_O8(4); } -// MOV R5, #Offset8 - void thumb25(u32 opcode) { MOV_RN_O8(5); } -// MOV R6, #Offset8 - void thumb26(u32 opcode) { MOV_RN_O8(6); } -// MOV R7, #Offset8 - void thumb27(u32 opcode) { MOV_RN_O8(7); } - -// CMP R0, #Offset8 - void thumb28(u32 opcode) { CMP_RN_O8(0); } -// CMP R1, #Offset8 - void thumb29(u32 opcode) { CMP_RN_O8(1); } -// CMP R2, #Offset8 - void thumb2A(u32 opcode) { CMP_RN_O8(2); } -// CMP R3, #Offset8 - void thumb2B(u32 opcode) { CMP_RN_O8(3); } -// CMP R4, #Offset8 - void thumb2C(u32 opcode) { CMP_RN_O8(4); } -// CMP R5, #Offset8 - void thumb2D(u32 opcode) { CMP_RN_O8(5); } -// CMP R6, #Offset8 - void thumb2E(u32 opcode) { CMP_RN_O8(6); } -// CMP R7, #Offset8 - void thumb2F(u32 opcode) { CMP_RN_O8(7); } - -// ADD R0,#Offset8 - void thumb30(u32 opcode) { ADD_RN_O8(0); } -// ADD R1,#Offset8 - void thumb31(u32 opcode) { ADD_RN_O8(1); } -// ADD R2,#Offset8 - void thumb32(u32 opcode) { ADD_RN_O8(2); } -// ADD R3,#Offset8 - void thumb33(u32 opcode) { ADD_RN_O8(3); } -// ADD R4,#Offset8 - void thumb34(u32 opcode) { ADD_RN_O8(4); } -// ADD R5,#Offset8 - void thumb35(u32 opcode) { ADD_RN_O8(5); } -// ADD R6,#Offset8 - void thumb36(u32 opcode) { ADD_RN_O8(6); } -// ADD R7,#Offset8 - void thumb37(u32 opcode) { ADD_RN_O8(7); } - -// SUB R0,#Offset8 - void thumb38(u32 opcode) { SUB_RN_O8(0); } -// SUB R1,#Offset8 - void thumb39(u32 opcode) { SUB_RN_O8(1); } -// SUB R2,#Offset8 - void thumb3A(u32 opcode) { SUB_RN_O8(2); } -// SUB R3,#Offset8 - void thumb3B(u32 opcode) { SUB_RN_O8(3); } -// SUB R4,#Offset8 - void thumb3C(u32 opcode) { SUB_RN_O8(4); } -// SUB R5,#Offset8 - void thumb3D(u32 opcode) { SUB_RN_O8(5); } -// SUB R6,#Offset8 - void thumb3E(u32 opcode) { SUB_RN_O8(6); } -// SUB R7,#Offset8 - void thumb3F(u32 opcode) { SUB_RN_O8(7); } - -// ALU operations ///////////////////////////////////////////////////////// - -// AND Rd, Rs - void thumb40_0(u32 opcode) -{ - int dest = opcode & 7; - u32 val = (bus.reg[dest].I & bus.reg[(opcode >> 3)&7].I); - - //bus.reg[dest].I &= bus.reg[(opcode >> 3)&7].I; - N_FLAG = val & 0x80000000 ? true : false; - Z_FLAG = val ? false : true; - - bus.reg[dest].I = val; - -} - -// EOR Rd, Rs - void thumb40_1(u32 opcode) -{ - int dest = opcode & 7; - bus.reg[dest].I ^= bus.reg[(opcode >> 3)&7].I; - N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = bus.reg[dest].I ? false : true; -} - -// LSL Rd, Rs - void thumb40_2(u32 opcode) -{ - int dest = opcode & 7; - u32 value = bus.reg[(opcode >> 3)&7].B.B0; - u32 val = value; - if(val) { - if(val == 32) { - value = 0; - C_FLAG = (bus.reg[dest].I & 1 ? true : false); - } else if(val < 32) { - LSL_RD_RS; - } else { - value = 0; - C_FLAG = false; - } - bus.reg[dest].I = value; - } - N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = bus.reg[dest].I ? false : true; - clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2; -} - -// LSR Rd, Rs - void thumb40_3(u32 opcode) -{ - int dest = opcode & 7; - u32 value = bus.reg[(opcode >> 3)&7].B.B0; - u32 val = value; - if(val) { - if(val == 32) { - value = 0; - C_FLAG = (bus.reg[dest].I & 0x80000000 ? true : false); - } else if(val < 32) { - LSR_RD_RS; - } else { - value = 0; - C_FLAG = false; - } - bus.reg[dest].I = value; - } - N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = bus.reg[dest].I ? false : true; - clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2; -} - -// ASR Rd, Rs - void thumb41_0(u32 opcode) -{ - int dest = opcode & 7; - u32 value = bus.reg[(opcode >> 3)&7].B.B0; - - if(value) { - if(value < 32) { - ASR_RD_RS; - bus.reg[dest].I = value; - } else { - if(bus.reg[dest].I & 0x80000000){ - bus.reg[dest].I = 0xFFFFFFFF; - C_FLAG = true; - } else { - bus.reg[dest].I = 0x00000000; - C_FLAG = false; - } - } - } - N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = bus.reg[dest].I ? false : true; - clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2; -} - -// ADC Rd, Rs - void thumb41_1(u32 opcode) -{ - int dest = opcode & 0x07; - u32 value = bus.reg[(opcode >> 3)&7].I; - ADC_RD_RS; -} - -// SBC Rd, Rs - void thumb41_2(u32 opcode) -{ - int dest = opcode & 0x07; - u32 value = bus.reg[(opcode >> 3)&7].I; - SBC_RD_RS; -} - -// ROR Rd, Rs - void thumb41_3(u32 opcode) -{ - int dest = opcode & 7; - u32 value = bus.reg[(opcode >> 3)&7].B.B0; - u32 val = value; - if(val) { - value = value & 0x1f; - if(val == 0) { - C_FLAG = (bus.reg[dest].I & 0x80000000 ? true : false); - } else { - ROR_RD_RS; - bus.reg[dest].I = value; - } - } - clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2; - N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false; - Z_FLAG = bus.reg[dest].I ? false : true; -} - -// TST Rd, Rs - void thumb42_0(u32 opcode) -{ - u32 value = bus.reg[opcode & 7].I & bus.reg[(opcode >> 3) & 7].I; - N_FLAG = value & 0x80000000 ? true : false; - Z_FLAG = value ? false : true; -} - -// NEG Rd, Rs - void thumb42_1(u32 opcode) -{ - int dest = opcode & 7; - int source = (opcode >> 3) & 7; - NEG_RD_RS; -} - -// CMP Rd, Rs - void thumb42_2(u32 opcode) -{ - int dest = opcode & 7; - u32 value = bus.reg[(opcode >> 3)&7].I; - CMP_RD_RS; -} - -// CMN Rd, Rs - void thumb42_3(u32 opcode) -{ - int dest = opcode & 7; - u32 value = bus.reg[(opcode >> 3)&7].I; - CMN_RD_RS; -} - -// ORR Rd, Rs - void thumb43_0(u32 opcode) -{ - int dest = opcode & 7; - bus.reg[dest].I |= bus.reg[(opcode >> 3) & 7].I; - Z_FLAG = bus.reg[dest].I ? false : true; - N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false; -} - -// MUL Rd, Rs - void thumb43_1(u32 opcode) -{ - clockTicks = 1; - int dest = opcode & 7; - u32 rm = bus.reg[dest].I; - bus.reg[dest].I = bus.reg[(opcode >> 3) & 7].I * rm; - if (((s32)rm) < 0) - rm = ~rm; - if ((rm & 0xFFFF0000) == 0) - clockTicks += 1; - else if ((rm & 0xFF000000) == 0) - clockTicks += 2; - else - clockTicks += 3; - bus.busPrefetchCount = (bus.busPrefetchCount<>(8-clockTicks)); - clockTicks += codeTicksAccess(bus.armNextPC, BITS_16) + 1; - Z_FLAG = bus.reg[dest].I ? false : true; - N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false; -} - -// BIC Rd, Rs - void thumb43_2(u32 opcode) -{ - int dest = opcode & 7; - bus.reg[dest].I &= (~bus.reg[(opcode >> 3) & 7].I); - Z_FLAG = bus.reg[dest].I ? false : true; - N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false; -} - -// MVN Rd, Rs - void thumb43_3(u32 opcode) -{ - int dest = opcode & 7; - bus.reg[dest].I = ~bus.reg[(opcode >> 3) & 7].I; - Z_FLAG = bus.reg[dest].I ? false : true; - N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false; -} - -// High-register instructions and BX ////////////////////////////////////// - -// ADD Rd, Hs - void thumb44_1(u32 opcode) -{ - bus.reg[opcode&7].I += bus.reg[((opcode>>3)&7)+8].I; -} - -// ADD Hd, Rs - void thumb44_2(u32 opcode) -{ - bus.reg[(opcode&7)+8].I += bus.reg[(opcode>>3)&7].I; - if((opcode&7) == 7) { - bus.reg[15].I &= 0xFFFFFFFE; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(bus.armNextPC)<<1 - + codeTicksAccess(bus.armNextPC, BITS_16) + 3; - } -} - -// ADD Hd, Hs - void thumb44_3(u32 opcode) -{ - bus.reg[(opcode&7)+8].I += bus.reg[((opcode>>3)&7)+8].I; - if((opcode&7) == 7) { - bus.reg[15].I &= 0xFFFFFFFE; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(bus.armNextPC)<<1 - + codeTicksAccess(bus.armNextPC, BITS_16) + 3; - } -} - -// CMP Rd, Hs - void thumb45_1(u32 opcode) -{ - int dest = opcode & 7; - u32 value = bus.reg[((opcode>>3)&7)+8].I; - CMP_RD_RS; -} - -// CMP Hd, Rs - void thumb45_2(u32 opcode) -{ - int dest = (opcode & 7) + 8; - u32 value = bus.reg[(opcode>>3)&7].I; - CMP_RD_RS; -} - -// CMP Hd, Hs - void thumb45_3(u32 opcode) -{ - int dest = (opcode & 7) + 8; - u32 value = bus.reg[((opcode>>3)&7)+8].I; - CMP_RD_RS; -} - -// MOV Rd, Hs - void thumb46_1(u32 opcode) -{ - bus.reg[opcode&7].I = bus.reg[((opcode>>3)&7)+8].I; -} - -// MOV Hd, Rs - void thumb46_2(u32 opcode) -{ - bus.reg[(opcode&7)+8].I = bus.reg[(opcode>>3)&7].I; - if((opcode&7) == 7) { - bus.reg[15].I &= 0xFFFFFFFE; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(bus.armNextPC)<<1 - + codeTicksAccess(bus.armNextPC, BITS_16) + 3; - } -} - -// MOV Hd, Hs - void thumb46_3(u32 opcode) -{ - bus.reg[(opcode&7)+8].I = bus.reg[((opcode>>3)&7)+8].I; - if((opcode&7) == 7) { - bus.reg[15].I &= 0xFFFFFFFE; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = codeTicksAccessSeq16(bus.armNextPC)<<1 - + codeTicksAccess(bus.armNextPC, BITS_16) + 3; - } -} - - -// BX Rs - void thumb47(u32 opcode) -{ - int base = (opcode >> 3) & 15; - bus.busPrefetchCount=0; - bus.reg[15].I = bus.reg[base].I; - if(bus.reg[base].I & 1) { - armState = false; - bus.reg[15].I &= 0xFFFFFFFE; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 2; - THUMB_PREFETCH; - clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) - + codeTicksAccess(bus.armNextPC, BITS_16) + 3; - } else { - armState = true; - bus.reg[15].I &= 0xFFFFFFFC; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 4; - ARM_PREFETCH; - clockTicks = ((codeTicksAccessSeq32(bus.armNextPC)) << 1) - + codeTicksAccess(bus.armNextPC, BITS_32) + 3; - } -} - -// Load/store instructions //////////////////////////////////////////////// - -// LDR R0~R7,[PC, #Imm] - void thumb48(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = (bus.reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); - // why quick? - // bus.reg[regist].I = CPUReadMemoryQuick(address); - bus.reg[regist].I = CPUReadMemory(address); - bus.busPrefetchCount=0; - int dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// STR Rd, [Rs, Rn] - void thumb50(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I; - CPUWriteMemory(address, bus.reg[opcode & 7].I); - int dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2; -} - -// STRH Rd, [Rs, Rn] - void thumb52(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I; - CPUWriteHalfWord(address, bus.reg[opcode&7].W.W0); - int dataticks_value = DATATICKS_ACCESS_16BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2; -} - -// STRB Rd, [Rs, Rn] - void thumb54(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode >>6)&7].I; - CPUWriteByte(address, bus.reg[opcode & 7].B.B0); - int dataticks_value = DATATICKS_ACCESS_16BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2; -} - -// LDSB Rd, [Rs, Rn] - void thumb56(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I; - bus.reg[opcode&7].I = (s8)CPUReadByte(address); - int dataticks_value = DATATICKS_ACCESS_16BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// LDR Rd, [Rs, Rn] - void thumb58(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I; - bus.reg[opcode&7].I = CPUReadMemory(address); - int dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// LDRH Rd, [Rs, Rn] - void thumb5A(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I; - bus.reg[opcode&7].I = CPUReadHalfWord(address); - int dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// LDRB Rd, [Rs, Rn] - void thumb5C(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I; - bus.reg[opcode&7].I = CPUReadByte(address); - int dataticks_value = DATATICKS_ACCESS_16BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// LDSH Rd, [Rs, Rn] - void thumb5E(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I; - bus.reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address); - int dataticks_value = DATATICKS_ACCESS_16BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// STR Rd, [Rs, #Imm] - void thumb60(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2); - CPUWriteMemory(address, bus.reg[opcode&7].I); - int dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2; -} - -// LDR Rd, [Rs, #Imm] - void thumb68(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2); - bus.reg[opcode&7].I = CPUReadMemory(address); - int dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// STRB Rd, [Rs, #Imm] - void thumb70(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)); - CPUWriteByte(address, bus.reg[opcode&7].B.B0); - int dataticks_value = DATATICKS_ACCESS_16BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2; -} - -// LDRB Rd, [Rs, #Imm] - void thumb78(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)); - bus.reg[opcode&7].I = CPUReadByte(address); - int dataticks_value = DATATICKS_ACCESS_16BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// STRH Rd, [Rs, #Imm] - void thumb80(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1); - CPUWriteHalfWord(address, bus.reg[opcode&7].W.W0); - int dataticks_value = DATATICKS_ACCESS_16BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2; -} - -// LDRH Rd, [Rs, #Imm] - void thumb88(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1); - bus.reg[opcode&7].I = CPUReadHalfWord(address); - int dataticks_value = DATATICKS_ACCESS_16BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// STR R0~R7, [SP, #Imm] - void thumb90(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[13].I + ((opcode&255)<<2); - CPUWriteMemory(address, bus.reg[regist].I); - int dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2; -} - -// LDR R0~R7, [SP, #Imm] - void thumb98(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[13].I + ((opcode&255)<<2); - // why quick? - // bus.reg[regist].I = CPUReadMemoryQuick(address); - bus.reg[regist].I = CPUReadMemory(address); - int dataticks_value = DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// PC/stack-related /////////////////////////////////////////////////////// - -// ADD R0~R7, PC, Imm - void thumbA0(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - bus.reg[regist].I = (bus.reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); -} - -// ADD R0~R7, SP, Imm - void thumbA8(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - bus.reg[regist].I = bus.reg[13].I + ((opcode&255)<<2); -} - -// ADD SP, Imm - void thumbB0(u32 opcode) -{ - int offset = (opcode & 127) << 2; - if(opcode & 0x80) - offset = -offset; - bus.reg[13].I += offset; -} - -// Push and pop /////////////////////////////////////////////////////////// - -#define PUSH_REG(val, r) \ - if (opcode & (val)) { \ - CPUWriteMemory(address, bus.reg[(r)].I); \ - int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 1 + dataticks_value; \ - count++; \ - address += 4; \ - } - -#define POP_REG(val, r) \ - if (opcode & (val)) { \ - bus.reg[(r)].I = CPUReadMemory(address); \ -int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \ - clockTicks += 1 + dataticks_value; \ - count++; \ - address += 4; \ - } - -// PUSH {Rlist} - void thumbB4(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int count = 0; - u32 temp = bus.reg[13].I - 4 * cpuBitsSet[opcode & 0xff]; - u32 address = temp & 0xFFFFFFFC; - PUSH_REG(1, 0); - PUSH_REG(2, 1); - PUSH_REG(4, 2); - PUSH_REG(8, 3); - PUSH_REG(16, 4); - PUSH_REG(32, 5); - PUSH_REG(64, 6); - PUSH_REG(128, 7); - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_16); - bus.reg[13].I = temp; -} - -// PUSH {Rlist, LR} - void thumbB5(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int count = 0; - u32 temp = bus.reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff]; - u32 address = temp & 0xFFFFFFFC; - PUSH_REG(1, 0); - PUSH_REG(2, 1); - PUSH_REG(4, 2); - PUSH_REG(8, 3); - PUSH_REG(16, 4); - PUSH_REG(32, 5); - PUSH_REG(64, 6); - PUSH_REG(128, 7); - PUSH_REG(256, 14); - clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_16); - bus.reg[13].I = temp; -} - -// POP {Rlist} - void thumbBC(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int count = 0; - u32 address = bus.reg[13].I & 0xFFFFFFFC; - u32 temp = bus.reg[13].I + 4*cpuBitsSet[opcode & 0xFF]; - POP_REG(1, 0); - POP_REG(2, 1); - POP_REG(4, 2); - POP_REG(8, 3); - POP_REG(16, 4); - POP_REG(32, 5); - POP_REG(64, 6); - POP_REG(128, 7); - bus.reg[13].I = temp; - clockTicks = 2 + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// POP {Rlist, PC} - void thumbBD(u32 opcode) -{ - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - int count = 0; - u32 address = bus.reg[13].I & 0xFFFFFFFC; - u32 temp = bus.reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF]; - POP_REG(1, 0); - POP_REG(2, 1); - POP_REG(4, 2); - POP_REG(8, 3); - POP_REG(16, 4); - POP_REG(32, 5); - POP_REG(64, 6); - POP_REG(128, 7); - bus.reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE); - int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); - clockTicks += 1 + dataticks_value; - count++; - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 2; - bus.reg[13].I = temp; - THUMB_PREFETCH; - bus.busPrefetchCount = 0; - clockTicks += 3 + ((codeTicksAccess(bus.armNextPC, BITS_16)) << 1); -} - -// Load/store multiple //////////////////////////////////////////////////// - -#define THUMB_STM_REG(val,r,b) \ - if(opcode & (val)) { \ - CPUWriteMemory(address, bus.reg[(r)].I); \ - bus.reg[(b)].I = temp; \ - int dataticks_val = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_val); \ - clockTicks += 1 + dataticks_val; \ - count++; \ - address += 4; \ - } - -#define THUMB_LDM_REG(val,r) \ - if(opcode & (val)) { \ - bus.reg[(r)].I = CPUReadMemory(address); \ - int dataticks_val = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \ - DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_val); \ - clockTicks += 1 + dataticks_val; \ - count++; \ - address += 4; \ - } - -// STM R0~7!, {Rlist} - void thumbC0(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[regist].I & 0xFFFFFFFC; - u32 temp = bus.reg[regist].I + 4*cpuBitsSet[opcode & 0xff]; - int count = 0; - // store - THUMB_STM_REG(1, 0, regist); - THUMB_STM_REG(2, 1, regist); - THUMB_STM_REG(4, 2, regist); - THUMB_STM_REG(8, 3, regist); - THUMB_STM_REG(16, 4, regist); - THUMB_STM_REG(32, 5, regist); - THUMB_STM_REG(64, 6, regist); - THUMB_STM_REG(128, 7, regist); - clockTicks = 1 + codeTicksAccess(bus.armNextPC, BITS_16); -} - -// LDM R0~R7!, {Rlist} - void thumbC8(u32 opcode) -{ - u8 regist = (opcode >> 8) & 7; - if (bus.busPrefetchCount == 0) - bus.busPrefetch = bus.busPrefetchEnable; - u32 address = bus.reg[regist].I & 0xFFFFFFFC; - u32 temp = bus.reg[regist].I + 4*cpuBitsSet[opcode & 0xFF]; - int count = 0; - // load - THUMB_LDM_REG(1, 0); - THUMB_LDM_REG(2, 1); - THUMB_LDM_REG(4, 2); - THUMB_LDM_REG(8, 3); - THUMB_LDM_REG(16, 4); - THUMB_LDM_REG(32, 5); - THUMB_LDM_REG(64, 6); - THUMB_LDM_REG(128, 7); - clockTicks = 2 + codeTicksAccess(bus.armNextPC, BITS_16); - if(!(opcode & (1<*thumbInsnTable[opcode>>6])(opcode); - - ct = clockTicks; - - if (ct < 0) - return 0; - - /// better pipelining - if (ct==0) - clockTicks = codeTicksAccessSeq16(oldArmNextPC) + 1; - - cpuTotalTicks += clockTicks; - -} while ((cpuTotalTicks < cpuNextEvent) & ~armState & ~holdState); - return 1; -} - - -/*============================================================ - GBA GFX -============================================================ */ - -#ifdef TILED_RENDERING -#ifdef _MSC_VER -union u8h -{ - __pragma( pack(push, 1)); - struct -#ifdef LSB_FIRST - { - /* 0*/ unsigned char lo:4; - /* 4*/ unsigned char hi:4; -#else - { - /* 4*/ unsigned char hi:4; - /* 0*/ unsigned char lo:4; -#endif - } - __pragma(pack(pop)); - u8 val; -}; -#else -union u8h -{ - struct -#ifdef LSB_FIRST - { - /* 0*/ unsigned char lo:4; - /* 4*/ unsigned char hi:4; -#else - { - /* 4*/ unsigned char hi:4; - /* 0*/ unsigned char lo:4; -#endif - } __attribute__ ((packed)); - u8 val; -}; -#endif - -union TileEntry -{ -#ifdef LSB_FIRST - struct - { - /* 0*/ unsigned tileNum:10; - /*12*/ unsigned hFlip:1; - /*13*/ unsigned vFlip:1; - /*14*/ unsigned palette:4; - }; -#else - struct - { - /*14*/ unsigned palette:4; - /*13*/ unsigned vFlip:1; - /*12*/ unsigned hFlip:1; - /* 0*/ unsigned tileNum:10; - }; -#endif - u16 val; -}; - -struct TileLine -{ - u32 pixels[8]; -}; - -typedef const TileLine (*TileReader) (const u16 *, const int, const u8 *, u16 *, const u32); - -static inline void gfxDrawPixel(u32 *dest, const u8 color, const u16 *palette, const u32 prio) -{ - *dest = color ? (READ16LE(&palette[color]) | prio): 0x80000000; -} - -static inline const TileLine gfxReadTile(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio) -{ - TileEntry tile; - tile.val = READ16LE(screenSource); - - int tileY = yyy & 7; - if (tile.vFlip) tileY = 7 - tileY; - TileLine tileLine; - - const u8 *tileBase = &charBase[tile.tileNum * 64 + tileY * 8]; - - if (!tile.hFlip) - { - gfxDrawPixel(&tileLine.pixels[0], tileBase[0], palette, prio); - gfxDrawPixel(&tileLine.pixels[1], tileBase[1], palette, prio); - gfxDrawPixel(&tileLine.pixels[2], tileBase[2], palette, prio); - gfxDrawPixel(&tileLine.pixels[3], tileBase[3], palette, prio); - gfxDrawPixel(&tileLine.pixels[4], tileBase[4], palette, prio); - gfxDrawPixel(&tileLine.pixels[5], tileBase[5], palette, prio); - gfxDrawPixel(&tileLine.pixels[6], tileBase[6], palette, prio); - gfxDrawPixel(&tileLine.pixels[7], tileBase[7], palette, prio); - } - else - { - gfxDrawPixel(&tileLine.pixels[0], tileBase[7], palette, prio); - gfxDrawPixel(&tileLine.pixels[1], tileBase[6], palette, prio); - gfxDrawPixel(&tileLine.pixels[2], tileBase[5], palette, prio); - gfxDrawPixel(&tileLine.pixels[3], tileBase[4], palette, prio); - gfxDrawPixel(&tileLine.pixels[4], tileBase[3], palette, prio); - gfxDrawPixel(&tileLine.pixels[5], tileBase[2], palette, prio); - gfxDrawPixel(&tileLine.pixels[6], tileBase[1], palette, prio); - gfxDrawPixel(&tileLine.pixels[7], tileBase[0], palette, prio); - } - - return tileLine; -} - -static inline const TileLine gfxReadTilePal(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio) -{ - TileEntry tile; - tile.val = READ16LE(screenSource); - - int tileY = yyy & 7; - if (tile.vFlip) tileY = 7 - tileY; - palette += tile.palette * 16; - TileLine tileLine; - - const u8h *tileBase = (u8h*) &charBase[tile.tileNum * 32 + tileY * 4]; - - if (!tile.hFlip) - { - gfxDrawPixel(&tileLine.pixels[0], tileBase[0].lo, palette, prio); - gfxDrawPixel(&tileLine.pixels[1], tileBase[0].hi, palette, prio); - gfxDrawPixel(&tileLine.pixels[2], tileBase[1].lo, palette, prio); - gfxDrawPixel(&tileLine.pixels[3], tileBase[1].hi, palette, prio); - gfxDrawPixel(&tileLine.pixels[4], tileBase[2].lo, palette, prio); - gfxDrawPixel(&tileLine.pixels[5], tileBase[2].hi, palette, prio); - gfxDrawPixel(&tileLine.pixels[6], tileBase[3].lo, palette, prio); - gfxDrawPixel(&tileLine.pixels[7], tileBase[3].hi, palette, prio); - } - else - { - gfxDrawPixel(&tileLine.pixels[0], tileBase[3].hi, palette, prio); - gfxDrawPixel(&tileLine.pixels[1], tileBase[3].lo, palette, prio); - gfxDrawPixel(&tileLine.pixels[2], tileBase[2].hi, palette, prio); - gfxDrawPixel(&tileLine.pixels[3], tileBase[2].lo, palette, prio); - gfxDrawPixel(&tileLine.pixels[4], tileBase[1].hi, palette, prio); - gfxDrawPixel(&tileLine.pixels[5], tileBase[1].lo, palette, prio); - gfxDrawPixel(&tileLine.pixels[6], tileBase[0].hi, palette, prio); - gfxDrawPixel(&tileLine.pixels[7], tileBase[0].lo, palette, prio); - } - - return tileLine; -} - -static inline void gfxDrawTile(const TileLine &tileLine, u32 *line) -{ - memcpy(line, tileLine.pixels, sizeof(tileLine.pixels)); -} - -static inline void gfxDrawTileClipped(const TileLine &tileLine, u32 *line, const int start, int w) -{ - memcpy(line, tileLine.pixels + start, w * sizeof(u32)); -} - -template -void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, - u32 *line) -{ - u16 *palette = (u16 *)graphics.paletteRAM; - u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000]; - u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800]; - u32 prio = ((control & 3)<<25) + 0x1000000; - int sizeX = 256; - int sizeY = 256; - switch ((control >> 14) & 3) - { - case 0: - break; - case 1: - sizeX = 512; - break; - case 2: - sizeY = 512; - break; - case 3: - sizeX = 512; - sizeY = 512; - break; - } - - int maskX = sizeX-1; - int maskY = sizeY-1; - - bool mosaicOn = (control & 0x40) ? true : false; - - int xxx = hofs & maskX; - int yyy = (vofs + io_registers[REG_VCOUNT]) & maskY; - int mosaicX = (MOSAIC & 0x000F)+1; - int mosaicY = ((MOSAIC & 0x00F0)>>4)+1; - - if (mosaicOn) - { - if ((io_registers[REG_VCOUNT] % mosaicY) != 0) - { - mosaicY = io_registers[REG_VCOUNT] - (io_registers[REG_VCOUNT] % mosaicY); - yyy = (vofs + mosaicY) & maskY; - } - } - - if (yyy > 255 && sizeY > 256) - { - yyy &= 255; - screenBase += 0x400; - if (sizeX > 256) - screenBase += 0x400; - } - - int yshift = ((yyy>>3)<<5); - - u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift; - int x = 0; - const int firstTileX = xxx & 7; - - // First tile, if clipped - if (firstTileX) - { - gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], firstTileX, 8 - firstTileX); - screenSource++; - x += 8 - firstTileX; - xxx += 8 - firstTileX; - - if (xxx == 256 && sizeX > 256) - { - screenSource = screenBase + 0x400 + yshift; - } - else if (xxx >= sizeX) - { - xxx = 0; - screenSource = screenBase + yshift; - } - } - - // Middle tiles, full - while (x < 240 - firstTileX) - { - gfxDrawTile(readTile(screenSource, yyy, charBase, palette, prio), &line[x]); - screenSource++; - xxx += 8; - x += 8; - - if (xxx == 256 && sizeX > 256) - { - screenSource = screenBase + 0x400 + yshift; - } - else if (xxx >= sizeX) - { - xxx = 0; - screenSource = screenBase + yshift; - } - } - - // Last tile, if clipped - if (firstTileX) - { - gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], 0, firstTileX); - } - - if (mosaicOn) - { - if (mosaicX > 1) - { - int m = 1; - for (int i = 0; i < 239; i++) - { - line[i+1] = line[i]; - m++; - if (m == mosaicX) - { - m = 1; - i++; - } - } - } - } -} - -void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, u32 *line) -{ - if (control & 0x80) // 1 pal / 256 col - gfxDrawTextScreen(control, hofs, vofs, line); - else // 16 pal / 16 col - gfxDrawTextScreen(control, hofs, vofs, line); -} -#else -inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, - u32 *line) -{ - u16 *palette = (u16 *)graphics.paletteRAM; - u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000]; - u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800]; - u32 prio = ((control & 3)<<25) + 0x1000000; - int sizeX = 256; - int sizeY = 256; - switch((control >> 14) & 3) { - case 0: - break; - case 1: - sizeX = 512; - break; - case 2: - sizeY = 512; - break; - case 3: - sizeX = 512; - sizeY = 512; - break; - } - - int maskX = sizeX-1; - int maskY = sizeY-1; - - bool mosaicOn = (control & 0x40) ? true : false; - - int xxx = hofs & maskX; - int yyy = (vofs + io_registers[REG_VCOUNT]) & maskY; - int mosaicX = (MOSAIC & 0x000F)+1; - int mosaicY = ((MOSAIC & 0x00F0)>>4)+1; - - if(mosaicOn) { - if((io_registers[REG_VCOUNT] % mosaicY) != 0) { - mosaicY = io_registers[REG_VCOUNT] - (io_registers[REG_VCOUNT] % mosaicY); - yyy = (vofs + mosaicY) & maskY; - } - } - - if(yyy > 255 && sizeY > 256) { - yyy &= 255; - screenBase += 0x400; - if(sizeX > 256) - screenBase += 0x400; - } - - int yshift = ((yyy>>3)<<5); - if((control) & 0x80) { - u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift; - for(int x = 0; x < 240; x++) { - u16 data = READ16LE(screenSource); - - int tile = data & 0x3FF; - int tileX = (xxx & 7); - int tileY = yyy & 7; - - if(tileX == 7) - screenSource++; - - if(data & 0x0400) - tileX = 7 - tileX; - if(data & 0x0800) - tileY = 7 - tileY; - - u8 color = charBase[tile * 64 + tileY * 8 + tileX]; - - line[x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000; - - xxx++; - if(xxx == 256) { - if(sizeX > 256) - screenSource = screenBase + 0x400 + yshift; - else { - screenSource = screenBase + yshift; - xxx = 0; - } - } else if(xxx >= sizeX) { - xxx = 0; - screenSource = screenBase + yshift; - } - } - } else { - u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) + - yshift; - for(int x = 0; x < 240; x++) { - u16 data = READ16LE(screenSource); - - int tile = data & 0x3FF; - int tileX = (xxx & 7); - int tileY = yyy & 7; - - if(tileX == 7) - screenSource++; - - if(data & 0x0400) - tileX = 7 - tileX; - if(data & 0x0800) - tileY = 7 - tileY; - - u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)]; - - if(tileX & 1) { - color = (color >> 4); - } else { - color &= 0x0F; - } - - int pal = (data>>8) & 0xF0; - line[x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000; - - xxx++; - if(xxx == 256) { - if(sizeX > 256) - screenSource = screenBase + 0x400 + yshift; - else { - screenSource = screenBase + yshift; - xxx = 0; - } - } else if(xxx >= sizeX) { - xxx = 0; - screenSource = screenBase + yshift; - } - } - } - if(mosaicOn) { - if(mosaicX > 1) { - int m = 1; - for(int i = 0; i < 239; i++) { - line[i+1] = line[i]; - m++; - if(m == mosaicX) { - m = 1; - i++; - } - } - } - } -} -#endif - -INLINE void gfxDrawRotScreen(u16 control, u16 x_l, u16 x_h, u16 y_l, u16 y_h, -u16 pa, u16 pb, u16 pc, u16 pd, int& currentX, int& currentY, int changed, u32 *line) -{ - u16 *palette = (u16 *)graphics.paletteRAM; - u8 *charBase = &vram[((control >> 2) & 0x03) << 14]; - u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) << 11]; - int prio = ((control & 3) << 25) + 0x1000000; - - u32 map_size = (control >> 14) & 3; - u32 sizeX = map_sizes_rot[map_size]; - u32 sizeY = map_sizes_rot[map_size]; - - int maskX = sizeX-1; - int maskY = sizeY-1; - - int yshift = ((control >> 14) & 3)+4; - -#ifdef BRANCHLESS_GBA_GFX - int dx = pa & 0x7FFF; - int dmx = pb & 0x7FFF; - int dy = pc & 0x7FFF; - int dmy = pd & 0x7FFF; - - dx |= isel(-(pa & 0x8000), 0, 0xFFFF8000); - - dmx |= isel(-(pb & 0x8000), 0, 0xFFFF8000); - - dy |= isel(-(pc & 0x8000), 0, 0xFFFF8000); - - dmy |= isel(-(pd & 0x8000), 0, 0xFFFF8000); -#else - int dx = pa & 0x7FFF; - if(pa & 0x8000) - dx |= 0xFFFF8000; - int dmx = pb & 0x7FFF; - if(pb & 0x8000) - dmx |= 0xFFFF8000; - int dy = pc & 0x7FFF; - if(pc & 0x8000) - dy |= 0xFFFF8000; - int dmy = pd & 0x7FFF; - if(pd & 0x8000) - dmy |= 0xFFFF8000; -#endif - - if(io_registers[REG_VCOUNT] == 0) - changed = 3; - - currentX += dmx; - currentY += dmy; - - if(changed & 1) - { - currentX = (x_l) | ((x_h & 0x07FF)<<16); - if(x_h & 0x0800) - currentX |= 0xF8000000; - } - - if(changed & 2) - { - currentY = (y_l) | ((y_h & 0x07FF)<<16); - if(y_h & 0x0800) - currentY |= 0xF8000000; - } - - int realX = currentX; - int realY = currentY; - - if(control & 0x40) - { - int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; - int y = (io_registers[REG_VCOUNT] % mosaicY); - realX -= y*dmx; - realY -= y*dmy; - } - - memset(line, -1, 240 * sizeof(u32)); - if(control & 0x2000) - { - for(u32 x = 0; x < 240u; ++x) - { - int xxx = (realX >> 8) & maskX; - int yyy = (realY >> 8) & maskY; - - int tile = screenBase[(xxx>>3) + ((yyy>>3)<> 8); - unsigned yyy = (realY >> 8); - - if(xxx < sizeX && yyy < sizeY) - { - int tile = screenBase[(xxx>>3) + ((yyy>>3)< 1) - { - int m = 1; - for(u32 i = 0; i < 239u; ++i) - { - line[i+1] = line[i]; - if(++m == mosaicX) - { - m = 1; - ++i; - } - } - } - } -} - -INLINE void gfxDrawRotScreen16Bit( int& currentX, int& currentY, int changed) -{ - u16 *screenBase = (u16 *)&vram[0]; - int prio = ((io_registers[REG_BG2CNT] & 3) << 25) + 0x1000000; - - u32 sizeX = 240; - u32 sizeY = 160; - - int startX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16); - if(BG2X_H & 0x0800) - startX |= 0xF8000000; - int startY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16); - if(BG2Y_H & 0x0800) - startY |= 0xF8000000; - -#ifdef BRANCHLESS_GBA_GFX - int dx = io_registers[REG_BG2PA] & 0x7FFF; - dx |= isel(-(io_registers[REG_BG2PA] & 0x8000), 0, 0xFFFF8000); - - int dmx = io_registers[REG_BG2PB] & 0x7FFF; - dmx |= isel(-(io_registers[REG_BG2PB] & 0x8000), 0, 0xFFFF8000); - - int dy = io_registers[REG_BG2PC] & 0x7FFF; - dy |= isel(-(io_registers[REG_BG2PC] & 0x8000), 0, 0xFFFF8000); - - int dmy = io_registers[REG_BG2PD] & 0x7FFF; - dmy |= isel(-(io_registers[REG_BG2PD] & 0x8000), 0, 0xFFFF8000); -#else - int dx = io_registers[REG_BG2PA] & 0x7FFF; - if(io_registers[REG_BG2PA] & 0x8000) - dx |= 0xFFFF8000; - int dmx = io_registers[REG_BG2PB] & 0x7FFF; - if(io_registers[REG_BG2PB] & 0x8000) - dmx |= 0xFFFF8000; - int dy = io_registers[REG_BG2PC] & 0x7FFF; - if(io_registers[REG_BG2PC] & 0x8000) - dy |= 0xFFFF8000; - int dmy = io_registers[REG_BG2PD] & 0x7FFF; - if(io_registers[REG_BG2PD] & 0x8000) - dmy |= 0xFFFF8000; -#endif - - if(io_registers[REG_VCOUNT] == 0) - changed = 3; - - currentX += dmx; - currentY += dmy; - - if(changed & 1) - { - currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16); - if(BG2X_H & 0x0800) - currentX |= 0xF8000000; - } - - if(changed & 2) - { - currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16); - if(BG2Y_H & 0x0800) - currentY |= 0xF8000000; - } - - int realX = currentX; - int realY = currentY; - - if(io_registers[REG_BG2CNT] & 0x40) { - int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; - int y = (io_registers[REG_VCOUNT] % mosaicY); - realX -= y*dmx; - realY -= y*dmy; - } - - unsigned xxx = (realX >> 8); - unsigned yyy = (realY >> 8); - - memset(line[2], -1, 240 * sizeof(u32)); - for(u32 x = 0; x < 240u; ++x) - { - if(xxx < sizeX && yyy < sizeY) - line[2][x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio); - - realX += dx; - realY += dy; - - xxx = (realX >> 8); - yyy = (realY >> 8); - } - - if(io_registers[REG_BG2CNT] & 0x40) { - int mosaicX = (MOSAIC & 0xF) + 1; - if(mosaicX > 1) { - int m = 1; - for(u32 i = 0; i < 239u; ++i) - { - line[2][i+1] = line[2][i]; - if(++m == mosaicX) - { - m = 1; - ++i; - } - } - } - } -} - -INLINE void gfxDrawRotScreen256(int ¤tX, int& currentY, int changed) -{ - u16 *palette = (u16 *)graphics.paletteRAM; - u8 *screenBase = (io_registers[REG_DISPCNT] & 0x0010) ? &vram[0xA000] : &vram[0x0000]; - int prio = ((io_registers[REG_BG2CNT] & 3) << 25) + 0x1000000; - u32 sizeX = 240; - u32 sizeY = 160; - - int startX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16); - if(BG2X_H & 0x0800) - startX |= 0xF8000000; - int startY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16); - if(BG2Y_H & 0x0800) - startY |= 0xF8000000; - -#ifdef BRANCHLESS_GBA_GFX - int dx = io_registers[REG_BG2PA] & 0x7FFF; - dx |= isel(-(io_registers[REG_BG2PA] & 0x8000), 0, 0xFFFF8000); - - int dmx = io_registers[REG_BG2PB] & 0x7FFF; - dmx |= isel(-(io_registers[REG_BG2PB] & 0x8000), 0, 0xFFFF8000); - - int dy = io_registers[REG_BG2PC] & 0x7FFF; - dy |= isel(-(io_registers[REG_BG2PC] & 0x8000), 0, 0xFFFF8000); - - int dmy = io_registers[REG_BG2PD] & 0x7FFF; - dmy |= isel(-(io_registers[REG_BG2PD] & 0x8000), 0, 0xFFFF8000); -#else - int dx = io_registers[REG_BG2PA] & 0x7FFF; - if(io_registers[REG_BG2PA] & 0x8000) - dx |= 0xFFFF8000; - int dmx = io_registers[REG_BG2PB] & 0x7FFF; - if(io_registers[REG_BG2PB] & 0x8000) - dmx |= 0xFFFF8000; - int dy = io_registers[REG_BG2PC] & 0x7FFF; - if(io_registers[REG_BG2PC] & 0x8000) - dy |= 0xFFFF8000; - int dmy = io_registers[REG_BG2PD] & 0x7FFF; - if(io_registers[REG_BG2PD] & 0x8000) - dmy |= 0xFFFF8000; -#endif - - if(io_registers[REG_VCOUNT] == 0) - changed = 3; - - currentX += dmx; - currentY += dmy; - - if(changed & 1) - { - currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16); - if(BG2X_H & 0x0800) - currentX |= 0xF8000000; - } - - if(changed & 2) - { - currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16); - if(BG2Y_H & 0x0800) - currentY |= 0xF8000000; - } - - int realX = currentX; - int realY = currentY; - - if(io_registers[REG_BG2CNT] & 0x40) { - int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; - int y = io_registers[REG_VCOUNT] - (io_registers[REG_VCOUNT] % mosaicY); - realX = startX + y*dmx; - realY = startY + y*dmy; - } - - int xxx = (realX >> 8); - int yyy = (realY >> 8); - - memset(line[2], -1, 240 * sizeof(u32)); - for(u32 x = 0; x < 240; ++x) - { - u8 color = screenBase[yyy * 240 + xxx]; - if(unsigned(xxx) < sizeX && unsigned(yyy) < sizeY && color) - line[2][x] = (READ16LE(&palette[color])|prio); - realX += dx; - realY += dy; - - xxx = (realX >> 8); - yyy = (realY >> 8); - } - - if(io_registers[REG_BG2CNT] & 0x40) - { - int mosaicX = (MOSAIC & 0xF) + 1; - if(mosaicX > 1) - { - int m = 1; - for(u32 i = 0; i < 239u; ++i) - { - line[2][i+1] = line[2][i]; - if(++m == mosaicX) - { - m = 1; - ++i; - } - } - } - } -} - -INLINE void gfxDrawRotScreen16Bit160(int& currentX, int& currentY, int changed) -{ - u16 *screenBase = (io_registers[REG_DISPCNT] & 0x0010) ? (u16 *)&vram[0xa000] : - (u16 *)&vram[0]; - int prio = ((io_registers[REG_BG2CNT] & 3) << 25) + 0x1000000; - u32 sizeX = 160; - u32 sizeY = 128; - - int startX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16); - if(BG2X_H & 0x0800) - startX |= 0xF8000000; - int startY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16); - if(BG2Y_H & 0x0800) - startY |= 0xF8000000; - -#ifdef BRANCHLESS_GBA_GFX - int dx = io_registers[REG_BG2PA] & 0x7FFF; - dx |= isel(-(io_registers[REG_BG2PA] & 0x8000), 0, 0xFFFF8000); - - int dmx = io_registers[REG_BG2PB] & 0x7FFF; - dmx |= isel(-(io_registers[REG_BG2PB] & 0x8000), 0, 0xFFFF8000); - - int dy = io_registers[REG_BG2PC] & 0x7FFF; - dy |= isel(-(io_registers[REG_BG2PC] & 0x8000), 0, 0xFFFF8000); - - int dmy = io_registers[REG_BG2PD] & 0x7FFF; - dmy |= isel(-(io_registers[REG_BG2PD] & 0x8000), 0, 0xFFFF8000); -#else - int dx = io_registers[REG_BG2PA] & 0x7FFF; - if(io_registers[REG_BG2PA] & 0x8000) - dx |= 0xFFFF8000; - int dmx = io_registers[REG_BG2PB] & 0x7FFF; - if(io_registers[REG_BG2PB] & 0x8000) - dmx |= 0xFFFF8000; - int dy = io_registers[REG_BG2PC] & 0x7FFF; - if(io_registers[REG_BG2PC] & 0x8000) - dy |= 0xFFFF8000; - int dmy = io_registers[REG_BG2PD] & 0x7FFF; - if(io_registers[REG_BG2PD] & 0x8000) - dmy |= 0xFFFF8000; -#endif - - if(io_registers[REG_VCOUNT] == 0) - changed = 3; - - currentX += dmx; - currentY += dmy; - - if(changed & 1) - { - currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16); - if(BG2X_H & 0x0800) - currentX |= 0xF8000000; - } - - if(changed & 2) - { - currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16); - if(BG2Y_H & 0x0800) - currentY |= 0xF8000000; - } - - int realX = currentX; - int realY = currentY; - - if(io_registers[REG_BG2CNT] & 0x40) { - int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; - int y = io_registers[REG_VCOUNT] - (io_registers[REG_VCOUNT] % mosaicY); - realX = startX + y*dmx; - realY = startY + y*dmy; - } - - int xxx = (realX >> 8); - int yyy = (realY >> 8); - - memset(line[2], -1, 240 * sizeof(u32)); - for(u32 x = 0; x < 240u; ++x) - { - if(unsigned(xxx) < sizeX && unsigned(yyy) < sizeY) - line[2][x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio); - - realX += dx; - realY += dy; - - xxx = (realX >> 8); - yyy = (realY >> 8); - } - - - int mosaicX = (MOSAIC & 0xF) + 1; - if(io_registers[REG_BG2CNT] & 0x40 && (mosaicX > 1)) - { - int m = 1; - for(u32 i = 0; i < 239u; ++i) - { - line[2][i+1] = line[2][i]; - if(++m == mosaicX) - { - m = 1; - ++i; - } - } - } -} - -/* lineOBJpix is used to keep track of the drawn OBJs - and to stop drawing them if the 'maximum number of OBJ per line' - has been reached. */ - -INLINE void gfxDrawSprites (void) -{ - unsigned lineOBJpix, m; - - lineOBJpix = (io_registers[REG_DISPCNT] & 0x20) ? 954 : 1226; - m = 0; - - u16 *sprites = (u16 *)oam; - u16 *spritePalette = &((u16 *)graphics.paletteRAM)[256]; - int mosaicY = ((MOSAIC & 0xF000)>>12) + 1; - int mosaicX = ((MOSAIC & 0xF00)>>8) + 1; - for(u32 x = 0; x < 128; x++) - { - u16 a0 = READ16LE(sprites++); - u16 a1 = READ16LE(sprites++); - u16 a2 = READ16LE(sprites++); - ++sprites; - - lineOBJpixleft[x]=lineOBJpix; - - lineOBJpix-=2; - if (lineOBJpix<=0) - return; - - if ((a0 & 0x0c00) == 0x0c00) - a0 &=0xF3FF; - - u16 a0val = a0>>14; - - if (a0val == 3) - { - a0 &= 0x3FFF; - a1 &= 0x3FFF; - } - - u32 sizeX = 8<<(a1>>14); - u32 sizeY = sizeX; - - - if (a0val & 1) - { -#ifdef BRANCHLESS_GBA_GFX - sizeX <<= isel(-(sizeX & (~31u)), 1, 0); - sizeY >>= isel(-(sizeY>8), 0, 1); -#else - if (sizeX<32) - sizeX<<=1; - if (sizeY>8) - sizeY>>=1; -#endif - } - else if (a0val & 2) - { -#ifdef BRANCHLESS_GBA_GFX - sizeX >>= isel(-(sizeX>8), 0, 1); - sizeY <<= isel(-(sizeY & (~31u)), 1, 0); -#else - if (sizeX>8) - sizeX>>=1; - if (sizeY<32) - sizeY<<=1; -#endif - - } - - - int sy = (a0 & 255); - int sx = (a1 & 0x1FF); - - // computes ticks used by OBJ-WIN if OBJWIN is enabled - if (((a0 & 0x0c00) == 0x0800) && (graphics.layerEnable & 0x8000)) - { - if ((a0 & 0x0300) == 0x0300) - { - sizeX<<=1; - sizeY<<=1; - } - -#ifdef BRANCHLESS_GBA_GFX - sy -= isel(256 - sy - sizeY, 0, 256); - sx -= isel(512 - sx - sizeX, 0, 512); -#else - if((sy+sizeY) > 256) - sy -= 256; - if ((sx+sizeX)> 512) - sx -= 512; -#endif - - if (sx < 0) - { - sizeX+=sx; - sx = 0; - } - else if ((sx+sizeX)>240) - sizeX=240-sx; - - if ((io_registers[REG_VCOUNT]>=sy) && (io_registers[REG_VCOUNT] 256) - sy -= 256; - int t = io_registers[REG_VCOUNT] - sy; - if(unsigned(t) < fieldY) - { - u32 startpix = 0; - if ((sx+fieldX)> 512) - startpix=512-sx; - - if (lineOBJpix && ((sx < 240) || startpix)) - { - lineOBJpix-=8; - int rot = (((a1 >> 9) & 0x1F) << 4); - u16 *OAM = (u16 *)oam; - int dx = READ16LE(&OAM[3 + rot]); - if(dx & 0x8000) - dx |= 0xFFFF8000; - int dmx = READ16LE(&OAM[7 + rot]); - if(dmx & 0x8000) - dmx |= 0xFFFF8000; - int dy = READ16LE(&OAM[11 + rot]); - if(dy & 0x8000) - dy |= 0xFFFF8000; - int dmy = READ16LE(&OAM[15 + rot]); - if(dmy & 0x8000) - dmy |= 0xFFFF8000; - - if(a0 & 0x1000) - t -= (t % mosaicY); - - int realX = ((sizeX) << 7) - (fieldX >> 1)*dx + ((t - (fieldY>>1))* dmx); - int realY = ((sizeY) << 7) - (fieldX >> 1)*dy + ((t - (fieldY>>1))* dmy); - - u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - - int c = (a2 & 0x3FF); - if((io_registers[REG_DISPCNT] & 7) > 2 && (c < 512)) - continue; - - if(a0 & 0x2000) - { - int inc = 32; - if(io_registers[REG_DISPCNT] & 0x40) - inc = sizeX >> 2; - else - c &= 0x3FE; - for(u32 x = 0; x < fieldX; x++) - { - if (x >= startpix) - lineOBJpix-=2; - unsigned xxx = realX >> 8; - unsigned yyy = realY >> 8; - if(xxx < sizeX && yyy < sizeY && sx < 240) - { - - u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) - + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + (xxx & 7))&0x7FFF)]; - - if ((color==0) && (((prio >> 25)&3) < ((line[4][sx]>>25)&3))) - { - line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - } - else if((color) && (prio < (line[4][sx]&0xFF000000))) - { - line[4][sx] = READ16LE(&spritePalette[color]) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - } - - if ((a0 & 0x1000) && ((m+1) == mosaicX)) - m = 0; - } - sx = (sx+1)&511; - realX += dx; - realY += dy; - } - } - else - { - int inc = 32; - if(io_registers[REG_DISPCNT] & 0x40) - inc = sizeX >> 3; - int palette = (a2 >> 8) & 0xF0; - for(u32 x = 0; x < fieldX; ++x) - { - if (x >= startpix) - lineOBJpix-=2; - unsigned xxx = realX >> 8; - unsigned yyy = realY >> 8; - if(xxx < sizeX && yyy < sizeY && sx < 240) - { - - u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) - + ((yyy & 7)<<2) + ((xxx >> 3)<<5) - + ((xxx & 7)>>1))&0x7FFF)]; - if(xxx & 1) - color >>= 4; - else - color &= 0x0F; - - if ((color==0) && (((prio >> 25)&3) < - ((line[4][sx]>>25)&3))) - { - line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - } - else if((color) && (prio < (line[4][sx]&0xFF000000))) - { - line[4][sx] = READ16LE(&spritePalette[palette+color]) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - } - } - if((a0 & 0x1000) && m) - { - if (++m==mosaicX) - m=0; - } - - sx = (sx+1)&511; - realX += dx; - realY += dy; - - } - } - } - } - } - else - { - if(sy+sizeY > 256) - sy -= 256; - int t = io_registers[REG_VCOUNT] - sy; - if(unsigned(t) < sizeY) - { - u32 startpix = 0; - if ((sx+sizeX)> 512) - startpix=512-sx; - - if((sx < 240) || startpix) - { - lineOBJpix+=2; - - if(a1 & 0x2000) - t = sizeY - t - 1; - - int c = (a2 & 0x3FF); - if((io_registers[REG_DISPCNT] & 7) > 2 && (c < 512)) - continue; - - int inc = 32; - int xxx = 0; - if(a1 & 0x1000) - xxx = sizeX-1; - - if(a0 & 0x1000) - t -= (t % mosaicY); - - if(a0 & 0x2000) - { - if(io_registers[REG_DISPCNT] & 0x40) - inc = sizeX >> 2; - else - c &= 0x3FE; - - int address = 0x10000 + ((((c+ (t>>3) * inc) << 5) - + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF); - - if(a1 & 0x1000) - xxx = 7; - u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - - for(u32 xx = 0; xx < sizeX; xx++) - { - if (xx >= startpix) - --lineOBJpix; - if(sx < 240) - { - u8 color = vram[address]; - if ((color==0) && (((prio >> 25)&3) < - ((line[4][sx]>>25)&3))) - { - line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - } - else if((color) && (prio < (line[4][sx]&0xFF000000))) - { - line[4][sx] = READ16LE(&spritePalette[color]) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - } - - if ((a0 & 0x1000) && ((m+1) == mosaicX)) - m = 0; - } - - sx = (sx+1) & 511; - if(a1 & 0x1000) - { - --address; - if(--xxx == -1) - { - address -= 56; - xxx = 7; - } - if(address < 0x10000) - address += 0x8000; - } - else - { - ++address; - if(++xxx == 8) - { - address += 56; - xxx = 0; - } - if(address > 0x17fff) - address -= 0x8000; - } - } - } - else - { - if(io_registers[REG_DISPCNT] & 0x40) - inc = sizeX >> 3; - - int address = 0x10000 + ((((c + (t>>3) * inc)<<5) - + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF); - - u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - int palette = (a2 >> 8) & 0xF0; - if(a1 & 0x1000) - { - xxx = 7; - int xx = sizeX - 1; - do - { - if (xx >= (int)(startpix)) - --lineOBJpix; - //if (lineOBJpix<0) - // continue; - if(sx < 240) - { - u8 color = vram[address]; - if(xx & 1) - color >>= 4; - else - color &= 0x0F; - - if ((color==0) && (((prio >> 25)&3) < - ((line[4][sx]>>25)&3))) - { - line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - } - else if((color) && (prio < (line[4][sx]&0xFF000000))) - { - line[4][sx] = READ16LE(&spritePalette[palette + color]) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - } - } - - if ((a0 & 0x1000) && ((m+1) == mosaicX)) - m=0; - - sx = (sx+1) & 511; - if(!(xx & 1)) - --address; - if(--xxx == -1) - { - xxx = 7; - address -= 28; - } - if(address < 0x10000) - address += 0x8000; - }while(--xx >= 0); - } - else - { - for(u32 xx = 0; xx < sizeX; ++xx) - { - if (xx >= startpix) - --lineOBJpix; - //if (lineOBJpix<0) - // continue; - if(sx < 240) - { - u8 color = vram[address]; - if(xx & 1) - color >>= 4; - else - color &= 0x0F; - - if ((color==0) && (((prio >> 25)&3) < - ((line[4][sx]>>25)&3))) - { - line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - } - else if((color) && (prio < (line[4][sx]&0xFF000000))) - { - line[4][sx] = READ16LE(&spritePalette[palette + color]) | prio; - if((a0 & 0x1000) && m) - line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio; - - } - } - if ((a0 & 0x1000) && ((m+1) == mosaicX)) - m=0; - - sx = (sx+1) & 511; - if(xx & 1) - ++address; - if(++xxx == 8) - { - address += 28; - xxx = 0; - } - if(address > 0x17fff) - address -= 0x8000; - } - } - } - } - } - } - } -} - -INLINE void gfxDrawOBJWin (void) -{ - u16 *sprites = (u16 *)oam; - for(int x = 0; x < 128 ; x++) - { - int lineOBJpix = lineOBJpixleft[x]; - u16 a0 = READ16LE(sprites++); - u16 a1 = READ16LE(sprites++); - u16 a2 = READ16LE(sprites++); - sprites++; - - if (lineOBJpix<=0) - return; - - // ignores non OBJ-WIN and disabled OBJ-WIN - if(((a0 & 0x0c00) != 0x0800) || ((a0 & 0x0300) == 0x0200)) - continue; - - u16 a0val = a0>>14; - - if ((a0 & 0x0c00) == 0x0c00) - a0 &=0xF3FF; - - if (a0val == 3) - { - a0 &= 0x3FFF; - a1 &= 0x3FFF; - } - - int sizeX = 8<<(a1>>14); - int sizeY = sizeX; - - if (a0val & 1) - { -#ifdef BRANCHLESS_GBA_GFX - sizeX <<= isel(-(sizeX & (~31u)), 1, 0); - sizeY >>= isel(-(sizeY>8), 0, 1); -#else - if (sizeX<32) - sizeX<<=1; - if (sizeY>8) - sizeY>>=1; -#endif - } - else if (a0val & 2) - { -#ifdef BRANCHLESS_GBA_GFX - sizeX >>= isel(-(sizeX>8), 0, 1); - sizeY <<= isel(-(sizeY & (~31u)), 1, 0); -#else - if (sizeX>8) - sizeX>>=1; - if (sizeY<32) - sizeY<<=1; -#endif - - } - - int sy = (a0 & 255); - - if(a0 & 0x0100) - { - int fieldX = sizeX; - int fieldY = sizeY; - if(a0 & 0x0200) - { - fieldX <<= 1; - fieldY <<= 1; - } - if((sy+fieldY) > 256) - sy -= 256; - int t = io_registers[REG_VCOUNT] - sy; - if((t >= 0) && (t < fieldY)) - { - int sx = (a1 & 0x1FF); - int startpix = 0; - if ((sx+fieldX)> 512) - startpix=512-sx; - - if((sx < 240) || startpix) - { - lineOBJpix-=8; - // int t2 = t - (fieldY >> 1); - int rot = (a1 >> 9) & 0x1F; - u16 *OAM = (u16 *)oam; - int dx = READ16LE(&OAM[3 + (rot << 4)]); - if(dx & 0x8000) - dx |= 0xFFFF8000; - int dmx = READ16LE(&OAM[7 + (rot << 4)]); - if(dmx & 0x8000) - dmx |= 0xFFFF8000; - int dy = READ16LE(&OAM[11 + (rot << 4)]); - if(dy & 0x8000) - dy |= 0xFFFF8000; - int dmy = READ16LE(&OAM[15 + (rot << 4)]); - if(dmy & 0x8000) - dmy |= 0xFFFF8000; - - int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx - + t * dmx; - int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy - + t * dmy; - - int c = (a2 & 0x3FF); - if((io_registers[REG_DISPCNT] & 7) > 2 && (c < 512)) - continue; - - int inc = 32; - bool condition1 = a0 & 0x2000; - - if(io_registers[REG_DISPCNT] & 0x40) - inc = sizeX >> 3; - - for(int x = 0; x < fieldX; x++) - { - bool cont = true; - if (x >= startpix) - lineOBJpix-=2; - if (lineOBJpix<0) - continue; - int xxx = realX >> 8; - int yyy = realY >> 8; - - if(xxx < 0 || xxx >= sizeX || yyy < 0 || yyy >= sizeY || sx >= 240) - cont = false; - - if(cont) - { - u32 color; - if(condition1) - color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) - + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + - (xxx & 7))&0x7fff)]; - else - { - color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) - + ((yyy & 7)<<2) + ((xxx >> 3)<<5) + - ((xxx & 7)>>1))&0x7fff)]; - if(xxx & 1) - color >>= 4; - else - color &= 0x0F; - } - - if(color) - line[5][sx] = 1; - } - sx = (sx+1)&511; - realX += dx; - realY += dy; - } - } - } - } - else - { - if((sy+sizeY) > 256) - sy -= 256; - int t = io_registers[REG_VCOUNT] - sy; - if((t >= 0) && (t < sizeY)) - { - int sx = (a1 & 0x1FF); - int startpix = 0; - if ((sx+sizeX)> 512) - startpix=512-sx; - - if((sx < 240) || startpix) - { - lineOBJpix+=2; - if(a1 & 0x2000) - t = sizeY - t - 1; - int c = (a2 & 0x3FF); - if((io_registers[REG_DISPCNT] & 7) > 2 && (c < 512)) - continue; - if(a0 & 0x2000) - { - - int inc = 32; - if(io_registers[REG_DISPCNT] & 0x40) - inc = sizeX >> 2; - else - c &= 0x3FE; - - int xxx = 0; - if(a1 & 0x1000) - xxx = sizeX-1; - int address = 0x10000 + ((((c+ (t>>3) * inc) << 5) - + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff); - if(a1 & 0x1000) - xxx = 7; - for(int xx = 0; xx < sizeX; xx++) - { - if (xx >= startpix) - lineOBJpix--; - if (lineOBJpix<0) - continue; - if(sx < 240) - { - u8 color = vram[address]; - if(color) - line[5][sx] = 1; - } - - sx = (sx+1) & 511; - if(a1 & 0x1000) { - xxx--; - address--; - if(xxx == -1) { - address -= 56; - xxx = 7; - } - if(address < 0x10000) - address += 0x8000; - } else { - xxx++; - address++; - if(xxx == 8) { - address += 56; - xxx = 0; - } - if(address > 0x17fff) - address -= 0x8000; - } - } - } - else - { - int inc = 32; - if(io_registers[REG_DISPCNT] & 0x40) - inc = sizeX >> 3; - int xxx = 0; - if(a1 & 0x1000) - xxx = sizeX - 1; - int address = 0x10000 + ((((c + (t>>3) * inc)<<5) - + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff); - // u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); - // int palette = (a2 >> 8) & 0xF0; - if(a1 & 0x1000) - { - xxx = 7; - for(int xx = sizeX - 1; xx >= 0; xx--) - { - if (xx >= startpix) - lineOBJpix--; - if (lineOBJpix<0) - continue; - if(sx < 240) - { - u8 color = vram[address]; - if(xx & 1) - color = (color >> 4); - else - color &= 0x0F; - - if(color) - line[5][sx] = 1; - } - sx = (sx+1) & 511; - xxx--; - if(!(xx & 1)) - address--; - if(xxx == -1) { - xxx = 7; - address -= 28; - } - if(address < 0x10000) - address += 0x8000; - } - } - else - { - for(int xx = 0; xx < sizeX; xx++) - { - if (xx >= startpix) - lineOBJpix--; - if (lineOBJpix<0) - continue; - if(sx < 240) - { - u8 color = vram[address]; - if(xx & 1) - color = (color >> 4); - else - color &= 0x0F; - - if(color) - line[5][sx] = 1; - } - sx = (sx+1) & 511; - xxx++; - if(xx & 1) - address++; - if(xxx == 8) { - address += 28; - xxx = 0; - } - if(address > 0x17fff) - address -= 0x8000; - } - } - } - } - } - } - } -} - -INLINE u32 gfxIncreaseBrightness(u32 color, int coeff) -{ - color = (((color & 0xffff) << 16) | (color & 0xffff)) & 0x3E07C1F; - - color += ((((0x3E07C1F - color) * coeff) >> 4) & 0x3E07C1F); - - return (color >> 16) | color; -} - -INLINE u32 gfxDecreaseBrightness(u32 color, int coeff) -{ - color = (((color & 0xffff) << 16) | (color & 0xffff)) & 0x3E07C1F; - - color -= (((color * coeff) >> 4) & 0x3E07C1F); - - return (color >> 16) | color; -} - -#define GFX_ALPHA_BLEND(color, color2, ca, cb) \ - int r = AlphaClampLUT[(((color & 0x1F) * ca) >> 4) + (((color2 & 0x1F) * cb) >> 4)]; \ - int g = AlphaClampLUT[((((color >> 5) & 0x1F) * ca) >> 4) + ((((color2 >> 5) & 0x1F) * cb) >> 4)]; \ - int b = AlphaClampLUT[((((color >> 10) & 0x1F) * ca) >> 4) + ((((color2 >> 10) & 0x1F) * cb) >> 4)]; \ - color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; - -/*============================================================ - GBA.CPP -============================================================ */ -static const bool useBios = true; -bool skipBios; -// it's a few bytes in the linkscript to make a multiboot image work in normal boot as well, -// and most of the ones i've seen have done that, so this is not terribly useful -static const bool cpuIsMultiBoot = false; -int cpuSaveType; // used only in init() to set up function pointers and for save file determination -bool mirroringEnable; - -int cpuDmaCount; - -uint8_t bios[0x4000]; -uint8_t rom[0x2000000]; -uint8_t internalRAM[0x8000]; -uint8_t workRAM[0x40000]; -uint8_t vram[0x20000]; -u16 pix[2 * PIX_BUFFER_SCREEN_WIDTH * 160]; -uint8_t oam[0x400]; -uint8_t ioMem[0x400]; - -bool cpuEEPROMEnabled; // true to process writes to EEPROM at 0dxxxxxx -bool cpuEEPROMSensorEnabled; // eeprom motion sensor? code is mostly disabled - -#ifndef LSB_FIRST -bool cpuBiosSwapped = false; -#endif - -INLINE int CPUUpdateTicks (void) -{ - int cpuLoopTicks = graphics.lcdTicks; - - if(timer0On && (timer0Ticks < cpuLoopTicks)) - cpuLoopTicks = timer0Ticks; - - if(timer1On && !(io_registers[REG_TM1CNT] & 4) && (timer1Ticks < cpuLoopTicks)) - cpuLoopTicks = timer1Ticks; - - if(timer2On && !(io_registers[REG_TM2CNT] & 4) && (timer2Ticks < cpuLoopTicks)) - cpuLoopTicks = timer2Ticks; - - if(timer3On && !(io_registers[REG_TM3CNT] & 4) && (timer3Ticks < cpuLoopTicks)) - cpuLoopTicks = timer3Ticks; - - if (IRQTicks) - { - if (IRQTicks < cpuLoopTicks) - cpuLoopTicks = IRQTicks; - } - - return cpuLoopTicks; -} - -#define CPUUpdateWindow0() \ -{ \ - int x00_window0 = io_registers[REG_WIN0H] >>8; \ - int x01_window0 = io_registers[REG_WIN0H] & 255; \ - int x00_lte_x01 = x00_window0 <= x01_window0; \ - for(int i = 0; i < 240; i++) \ - gfxInWin[0][i] = ((i >= x00_window0 && i < x01_window0) & x00_lte_x01) | ((i >= x00_window0 || i < x01_window0) & ~x00_lte_x01); \ -} - -#define CPUUpdateWindow1() \ -{ \ - int x00_window1 = io_registers[REG_WIN1H]>>8; \ - int x01_window1 = io_registers[REG_WIN1H] & 255; \ - int x00_lte_x01 = x00_window1 <= x01_window1; \ - for(int i = 0; i < 240; i++) \ - gfxInWin[1][i] = ((i >= x00_window1 && i < x01_window1) & x00_lte_x01) | ((i >= x00_window1 || i < x01_window1) & ~x00_lte_x01); \ -} - -#define CPUCompareVCOUNT() \ - if(io_registers[REG_VCOUNT] == (io_registers[REG_DISPSTAT] >> 8)) \ - { \ - io_registers[REG_DISPSTAT] |= 4; \ - UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); \ - if(io_registers[REG_DISPSTAT] & 0x20) \ - { \ - io_registers[REG_IF] |= 4; \ - UPDATE_REG(0x202, io_registers[REG_IF]); \ - } \ - } \ - else \ - { \ - io_registers[REG_DISPSTAT] &= 0xFFFB; \ - UPDATE_REG(0x4, io_registers[REG_DISPSTAT]); \ - } \ - if (graphics.layerEnableDelay > 0) \ - { \ - graphics.layerEnableDelay--; \ - if (graphics.layerEnableDelay == 1) \ - graphics.layerEnable = io_registers[REG_DISPCNT]; \ - } - -int CPULoadRom(const u8 *romfile, const u32 romfilelen) -{ - if (cpuIsMultiBoot) - { - if (romfilelen > 0x40000) - return 0; - } - else - { - if (romfilelen > 0x2000000) - return 0; - } - - uint8_t *whereToLoad = cpuIsMultiBoot ? workRAM : rom; - - memcpy(whereToLoad, romfile, romfilelen); - romSize = romfilelen; - - uint16_t *temp = (uint16_t *)(rom+((romSize+1)&~1)); - int i; - for(i = (romSize+1)&~1; i < 0x2000000; i+=2) { - WRITE16LE(temp, (i >> 1) & 0xFFFF); - temp++; - } - - - flashInit(); - eepromInit(); - - memset(line[0], -1, 240 * sizeof(u32)); - memset(line[1], -1, 240 * sizeof(u32)); - memset(line[2], -1, 240 * sizeof(u32)); - memset(line[3], -1, 240 * sizeof(u32)); - - return romSize; -} - -void doMirroring (bool b) -{ - uint32_t mirroredRomSize = (((romSize)>>20) & 0x3F)<<20; - uint32_t mirroredRomAddress = romSize; - if ((mirroredRomSize <=0x800000) && (b)) - { - mirroredRomAddress = mirroredRomSize; - if (mirroredRomSize==0) - mirroredRomSize=0x100000; - while (mirroredRomAddress<0x01000000) - { - memcpy((uint16_t *)(rom+mirroredRomAddress), (uint16_t *)(rom), mirroredRomSize); - mirroredRomAddress+=mirroredRomSize; - } - } -} - -#define brightness_switch() \ - switch((BLDMOD >> 6) & 3) \ - { \ - case 2: \ - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); \ - break; \ - case 3: \ - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); \ - break; \ - } - -#define alpha_blend_brightness_switch() \ - if(top2 & (BLDMOD>>8)) \ - if(color < 0x80000000) \ - { \ - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); \ - } \ - else if(BLDMOD & top) \ - { \ - brightness_switch(); \ - } - -/* we only use 16bit color depth */ -#define INIT_COLOR_DEPTH_LINE_MIX() uint16_t * lineMix = (pix + PIX_BUFFER_SCREEN_WIDTH * io_registers[REG_VCOUNT]) - -void mode0RenderLine (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 0: Render Line\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0100) { - gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]); - } - - if(graphics.layerEnable & 0x0200) { - gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]); - } - - if(graphics.layerEnable & 0x0400) { - gfxDrawTextScreen(io_registers[REG_BG2CNT], io_registers[REG_BG2HOFS], io_registers[REG_BG2VOFS], line[2]); - } - - if(graphics.layerEnable & 0x0800) { - gfxDrawTextScreen(io_registers[REG_BG3CNT], io_registers[REG_BG3HOFS], io_registers[REG_BG3VOFS], line[3]); - } - - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; x++) - { - uint32_t color = backdrop; - uint8_t top = 0x20; - - if(line[0][x] < color) { - color = line[0][x]; - top = 0x01; - } - - if((uint8_t)(line[1][x]>>24) < (uint8_t)(color >> 24)) { - color = line[1][x]; - top = 0x02; - } - - if((uint8_t)(line[2][x]>>24) < (uint8_t)(color >> 24)) { - color = line[2][x]; - top = 0x04; - } - - if((uint8_t)(line[3][x]>>24) < (uint8_t)(color >> 24)) { - color = line[3][x]; - top = 0x08; - } - - if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) { - color = line[4][x]; - top = 0x10; - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((uint8_t)(line[0][x]>>24) < (uint8_t)(back >> 24)) { - back = line[0][x]; - top2 = 0x01; - } - - if((uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) { - back = line[1][x]; - top2 = 0x02; - } - - if((uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) { - back = line[2][x]; - top2 = 0x04; - } - - if((uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) { - back = line[3][x]; - top2 = 0x08; - } - - alpha_blend_brightness_switch(); - } - } - - - lineMix[x] = CONVERT_COLOR(color); - } -} - -void mode0RenderLineNoWindow (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 0: Render Line No Window\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - if(graphics.layerEnable & 0x0100) { - gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]); - } - - if(graphics.layerEnable & 0x0200) { - gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]); - } - - if(graphics.layerEnable & 0x0400) { - gfxDrawTextScreen(io_registers[REG_BG2CNT], io_registers[REG_BG2HOFS], io_registers[REG_BG2VOFS], line[2]); - } - - if(graphics.layerEnable & 0x0800) { - gfxDrawTextScreen(io_registers[REG_BG3CNT], io_registers[REG_BG3HOFS], io_registers[REG_BG3VOFS], line[3]); - } - - int effect = (BLDMOD >> 6) & 3; - - for(int x = 0; x < 240; x++) { - uint32_t color = backdrop; - uint8_t top = 0x20; - - if(line[0][x] < color) { - color = line[0][x]; - top = 0x01; - } - - if(line[1][x] < (color & 0xFF000000)) { - color = line[1][x]; - top = 0x02; - } - - if(line[2][x] < (color & 0xFF000000)) { - color = line[2][x]; - top = 0x04; - } - - if(line[3][x] < (color & 0xFF000000)) { - color = line[3][x]; - top = 0x08; - } - - if(line[4][x] < (color & 0xFF000000)) { - color = line[4][x]; - top = 0x10; - } - - if(!(color & 0x00010000)) { - switch(effect) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = backdrop; - uint8_t top2 = 0x20; - if((line[0][x] < back) && (top != 0x01)) - { - back = line[0][x]; - top2 = 0x01; - } - - if((line[1][x] < (back & 0xFF000000)) && (top != 0x02)) - { - back = line[1][x]; - top2 = 0x02; - } - - if((line[2][x] < (back & 0xFF000000)) && (top != 0x04)) - { - back = line[2][x]; - top2 = 0x04; - } - - if((line[3][x] < (back & 0xFF000000)) && (top != 0x08)) - { - back = line[3][x]; - top2 = 0x08; - } - - if((line[4][x] < (back & 0xFF000000)) && (top != 0x10)) - { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } else { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if(line[0][x] < back) { - back = line[0][x]; - top2 = 0x01; - } - - if(line[1][x] < (back & 0xFF000000)) { - back = line[1][x]; - top2 = 0x02; - } - - if(line[2][x] < (back & 0xFF000000)) { - back = line[2][x]; - top2 = 0x04; - } - - if(line[3][x] < (back & 0xFF000000)) { - back = line[3][x]; - top2 = 0x08; - } - - alpha_blend_brightness_switch(); - } - - lineMix[x] = CONVERT_COLOR(color); - } -} - -void mode0RenderLineAll (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 0: Render Line All\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - bool inWindow0 = false; - bool inWindow1 = false; - - if(graphics.layerEnable & 0x2000) { - uint8_t v0 = io_registers[REG_WIN0V] >> 8; - uint8_t v1 = io_registers[REG_WIN0V] & 255; - inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); - if(v1 >= v0) - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); - } - if(graphics.layerEnable & 0x4000) { - uint8_t v0 = io_registers[REG_WIN1V] >> 8; - uint8_t v1 = io_registers[REG_WIN1V] & 255; - inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); - if(v1 >= v0) - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); - } - - if((graphics.layerEnable & 0x0100)) { - gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]); - } - - if((graphics.layerEnable & 0x0200)) { - gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]); - } - - if((graphics.layerEnable & 0x0400)) { - gfxDrawTextScreen(io_registers[REG_BG2CNT], io_registers[REG_BG2HOFS], io_registers[REG_BG2VOFS], line[2]); - } - - if((graphics.layerEnable & 0x0800)) { - gfxDrawTextScreen(io_registers[REG_BG3CNT], io_registers[REG_BG3HOFS], io_registers[REG_BG3VOFS], line[3]); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF; - uint8_t inWin1Mask = io_registers[REG_WININ] >> 8; - uint8_t outMask = io_registers[REG_WINOUT] & 0xFF; - - for(int x = 0; x < 240; x++) { - uint32_t color = backdrop; - uint8_t top = 0x20; - uint8_t mask = outMask; - - if(!(line[5][x] & 0x80000000)) { - mask = io_registers[REG_WINOUT] >> 8; - } - - int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31; - int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31; - mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask); - mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask); - - if((mask & 1) && (line[0][x] < color)) { - color = line[0][x]; - top = 0x01; - } - - if((mask & 2) && ((uint8_t)(line[1][x]>>24) < (uint8_t)(color >> 24))) { - color = line[1][x]; - top = 0x02; - } - - if((mask & 4) && ((uint8_t)(line[2][x]>>24) < (uint8_t)(color >> 24))) { - color = line[2][x]; - top = 0x04; - } - - if((mask & 8) && ((uint8_t)(line[3][x]>>24) < (uint8_t)(color >> 24))) { - color = line[3][x]; - top = 0x08; - } - - if((mask & 16) && ((uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24))) { - color = line[4][x]; - top = 0x10; - } - - if(color & 0x00010000) - { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((mask & 1) && ((uint8_t)(line[0][x]>>24) < (uint8_t)(back >> 24))) { - back = line[0][x]; - top2 = 0x01; - } - - if((mask & 2) && ((uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24))) { - back = line[1][x]; - top2 = 0x02; - } - - if((mask & 4) && ((uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24))) { - back = line[2][x]; - top2 = 0x04; - } - - if((mask & 8) && ((uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24))) { - back = line[3][x]; - top2 = 0x08; - } - - alpha_blend_brightness_switch(); - } - else if((mask & 32) && (top & BLDMOD)) - { - // special FX on in the window - switch((BLDMOD >> 6) & 3) - { - case 0: - break; - case 1: - { - uint32_t back = backdrop; - uint8_t top2 = 0x20; - if(((mask & 1) && (uint8_t)(line[0][x]>>24) < (uint8_t)(back >> 24)) && top != 0x01) - { - back = line[0][x]; - top2 = 0x01; - } - - if(((mask & 2) && (uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) && top != 0x02) - { - back = line[1][x]; - top2 = 0x02; - } - - if(((mask & 4) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) && top != 0x04) - { - back = line[2][x]; - top2 = 0x04; - } - - if(((mask & 8) && (uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) && top != 0x08) - { - back = line[3][x]; - top2 = 0x08; - } - - if(((mask & 16) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) && top != 0x10) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - } - break; - case 2: - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } - - lineMix[x] = CONVERT_COLOR(color); - } -} - -/* -Mode 1 is a tiled graphics mode, but with background layer 2 supporting scaling and rotation. -There is no layer 3 in this mode. -Layers 0 and 1 can be either 16 colours (with 16 different palettes) or 256 colours. -There are 1024 tiles available. -Layer 2 is 256 colours and allows only 256 tiles. - -These routines only render a single line at a time, because of the way the GBA does events. -*/ - -void mode1RenderLine (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 1: Render Line\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0100) { - gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]); - } - - if(graphics.layerEnable & 0x0200) { - gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]); - } - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, - io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD], - gfxBG2X, gfxBG2Y, changed, line[2]); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - for(uint32_t x = 0; x < 240u; ++x) { - uint32_t color = backdrop; - uint8_t top = 0x20; - - uint8_t li1 = (uint8_t)(line[1][x]>>24); - uint8_t li2 = (uint8_t)(line[2][x]>>24); - uint8_t li4 = (uint8_t)(line[4][x]>>24); - - uint8_t r = (li2 < li1) ? (li2) : (li1); - - if(li4 < r){ - r = (li4); - } - - if(line[0][x] < backdrop) { - color = line[0][x]; - top = 0x01; - } - - if(r < (uint8_t)(color >> 24)) { - if(r == li1){ - color = line[1][x]; - top = 0x02; - }else if(r == li2){ - color = line[2][x]; - top = 0x04; - }else if(r == li4){ - color = line[4][x]; - top = 0x10; - if((color & 0x00010000)) - { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - uint8_t li0 = (uint8_t)(line[0][x]>>24); - uint8_t li1 = (uint8_t)(line[1][x]>>24); - uint8_t li2 = (uint8_t)(line[2][x]>>24); - uint8_t r = (li1 < li0) ? (li1) : (li0); - - if(li2 < r) { - r = (li2); - } - - if(r < (uint8_t)(back >> 24)) { - if(r == li0){ - back = line[0][x]; - top2 = 0x01; - }else if(r == li1){ - back = line[1][x]; - top2 = 0x02; - }else if(r == li2){ - back = line[2][x]; - top2 = 0x04; - } - } - - alpha_blend_brightness_switch(); - } - } - } - - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode1RenderLineNoWindow (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 1: Render Line No Window\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0100) { - gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]); - } - - - if(graphics.layerEnable & 0x0200) { - gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]); - } - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, - io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD], - gfxBG2X, gfxBG2Y, changed, line[2]); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) { - uint32_t color = backdrop; - uint8_t top = 0x20; - - uint8_t li1 = (uint8_t)(line[1][x]>>24); - uint8_t li2 = (uint8_t)(line[2][x]>>24); - uint8_t li4 = (uint8_t)(line[4][x]>>24); - - uint8_t r = (li2 < li1) ? (li2) : (li1); - - if(li4 < r){ - r = (li4); - } - - if(line[0][x] < backdrop) { - color = line[0][x]; - top = 0x01; - } - - if(r < (uint8_t)(color >> 24)) { - if(r == li1){ - color = line[1][x]; - top = 0x02; - }else if(r == li2){ - color = line[2][x]; - top = 0x04; - }else if(r == li4){ - color = line[4][x]; - top = 0x10; - } - } - - if(!(color & 0x00010000)) { - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((top != 0x01) && (uint8_t)(line[0][x]>>24) < (uint8_t)(back >> 24)) { - back = line[0][x]; - top2 = 0x01; - } - - if((top != 0x02) && (uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) { - back = line[1][x]; - top2 = 0x02; - } - - if((top != 0x04) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) { - back = line[2][x]; - top2 = 0x04; - } - - if((top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } else { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - uint8_t li0 = (uint8_t)(line[0][x]>>24); - uint8_t li1 = (uint8_t)(line[1][x]>>24); - uint8_t li2 = (uint8_t)(line[2][x]>>24); - - uint8_t r = (li1 < li0) ? (li1) : (li0); - - if(li2 < r) { - r = (li2); - } - - if(r < (uint8_t)(back >> 24)) - { - if(r == li0) - { - back = line[0][x]; - top2 = 0x01; - } - else if(r == li1) - { - back = line[1][x]; - top2 = 0x02; - } - else if(r == li2) - { - back = line[2][x]; - top2 = 0x04; - } - } - - alpha_blend_brightness_switch(); - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode1RenderLineAll (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 1: Render Line All\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - bool inWindow0 = false; - bool inWindow1 = false; - - if(graphics.layerEnable & 0x2000) - { - uint8_t v0 = io_registers[REG_WIN0V] >> 8; - uint8_t v1 = io_registers[REG_WIN0V] & 255; - inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - if(graphics.layerEnable & 0x4000) - { - uint8_t v0 = io_registers[REG_WIN1V] >> 8; - uint8_t v1 = io_registers[REG_WIN1V] & 255; - inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - - if(graphics.layerEnable & 0x0100) { - gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]); - } - - if(graphics.layerEnable & 0x0200) { - gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]); - } - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, - io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD], - gfxBG2X, gfxBG2Y, changed, line[2]); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF; - uint8_t inWin1Mask = io_registers[REG_WININ] >> 8; - uint8_t outMask = io_registers[REG_WINOUT] & 0xFF; - - for(int x = 0; x < 240; ++x) { - uint32_t color = backdrop; - uint8_t top = 0x20; - uint8_t mask = outMask; - - if(!(line[5][x] & 0x80000000)) { - mask = io_registers[REG_WINOUT] >> 8; - } - - int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31; - int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31; - mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask); - mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask); - - // At the very least, move the inexpensive 'mask' operation up front - if((mask & 1) && line[0][x] < backdrop) { - color = line[0][x]; - top = 0x01; - } - - if((mask & 2) && (uint8_t)(line[1][x]>>24) < (uint8_t)(color >> 24)) { - color = line[1][x]; - top = 0x02; - } - - if((mask & 4) && (uint8_t)(line[2][x]>>24) < (uint8_t)(color >> 24)) { - color = line[2][x]; - top = 0x04; - } - - if((mask & 16) && (uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) { - color = line[4][x]; - top = 0x10; - } - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((mask & 1) && (uint8_t)(line[0][x]>>24) < (uint8_t)(backdrop >> 24)) { - back = line[0][x]; - top2 = 0x01; - } - - if((mask & 2) && (uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) { - back = line[1][x]; - top2 = 0x02; - } - - if((mask & 4) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } else if(mask & 32) { - // special FX on the window - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((mask & 1) && (top != 0x01) && (uint8_t)(line[0][x]>>24) < (uint8_t)(backdrop >> 24)) { - back = line[0][x]; - top2 = 0x01; - } - - if((mask & 2) && (top != 0x02) && (uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) { - back = line[1][x]; - top2 = 0x02; - } - - if((mask & 4) && (top != 0x04) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) { - back = line[2][x]; - top2 = 0x04; - } - - if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -/* -Mode 2 is a 256 colour tiled graphics mode which supports scaling and rotation. -There is no background layer 0 or 1 in this mode. Only background layers 2 and 3. -There are 256 tiles available. -It does not support flipping. - -These routines only render a single line at a time, because of the way the GBA does events. -*/ - -void mode2RenderLine (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 2: Render Line\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, - io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD], gfxBG2X, gfxBG2Y, - changed, line[2]); - } - - if(graphics.layerEnable & 0x0800) { - int changed = gfxBG3Changed; -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen(io_registers[REG_BG3CNT], BG3X_L, BG3X_H, BG3Y_L, BG3Y_H, - io_registers[REG_BG3PA], io_registers[REG_BG3PB], io_registers[REG_BG3PC], io_registers[REG_BG3PD], gfxBG3X, gfxBG3Y, - changed, line[3]); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) { - uint32_t color = backdrop; - uint8_t top = 0x20; - - uint8_t li2 = (uint8_t)(line[2][x]>>24); - uint8_t li3 = (uint8_t)(line[3][x]>>24); - uint8_t li4 = (uint8_t)(line[4][x]>>24); - - uint8_t r = (li3 < li2) ? (li3) : (li2); - - if(li4 < r){ - r = (li4); - } - - if(r < (uint8_t)(color >> 24)) { - if(r == li2){ - color = line[2][x]; - top = 0x04; - }else if(r == li3){ - color = line[3][x]; - top = 0x08; - }else if(r == li4){ - color = line[4][x]; - top = 0x10; - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - uint8_t li2 = (uint8_t)(line[2][x]>>24); - uint8_t li3 = (uint8_t)(line[3][x]>>24); - uint8_t r = (li3 < li2) ? (li3) : (li2); - - if(r < (uint8_t)(back >> 24)) { - if(r == li2){ - back = line[2][x]; - top2 = 0x04; - }else if(r == li3){ - back = line[3][x]; - top2 = 0x08; - } - } - - alpha_blend_brightness_switch(); - } - } - } - - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - gfxBG3Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode2RenderLineNoWindow (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 2: Render Line No Window\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, - io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD], gfxBG2X, gfxBG2Y, - changed, line[2]); - } - - if(graphics.layerEnable & 0x0800) { - int changed = gfxBG3Changed; -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen(io_registers[REG_BG3CNT], BG3X_L, BG3X_H, BG3Y_L, BG3Y_H, - io_registers[REG_BG3PA], io_registers[REG_BG3PB], io_registers[REG_BG3PC], io_registers[REG_BG3PD], gfxBG3X, gfxBG3Y, - changed, line[3]); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) { - uint32_t color = backdrop; - uint8_t top = 0x20; - - uint8_t li2 = (uint8_t)(line[2][x]>>24); - uint8_t li3 = (uint8_t)(line[3][x]>>24); - uint8_t li4 = (uint8_t)(line[4][x]>>24); - - uint8_t r = (li3 < li2) ? (li3) : (li2); - - if(li4 < r){ - r = (li4); - } - - if(r < (uint8_t)(color >> 24)) { - if(r == li2){ - color = line[2][x]; - top = 0x04; - }else if(r == li3){ - color = line[3][x]; - top = 0x08; - }else if(r == li4){ - color = line[4][x]; - top = 0x10; - } - } - - if(!(color & 0x00010000)) { - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((top != 0x04) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) { - back = line[2][x]; - top2 = 0x04; - } - - if((top != 0x08) && (uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) { - back = line[3][x]; - top2 = 0x08; - } - - if((top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } else { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - uint8_t li2 = (uint8_t)(line[2][x]>>24); - uint8_t li3 = (uint8_t)(line[3][x]>>24); - uint8_t r = (li3 < li2) ? (li3) : (li2); - - if(r < (uint8_t)(back >> 24)) { - if(r == li2){ - back = line[2][x]; - top2 = 0x04; - }else if(r == li3){ - back = line[3][x]; - top2 = 0x08; - } - } - - alpha_blend_brightness_switch(); - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - gfxBG3Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode2RenderLineAll (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 2: Render Line All\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - bool inWindow0 = false; - bool inWindow1 = false; - - if(graphics.layerEnable & 0x2000) - { - uint8_t v0 = io_registers[REG_WIN0V] >> 8; - uint8_t v1 = io_registers[REG_WIN0V] & 255; - inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - if(graphics.layerEnable & 0x4000) - { - uint8_t v0 = io_registers[REG_WIN1V] >> 8; - uint8_t v1 = io_registers[REG_WIN1V] & 255; - inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, - io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD], gfxBG2X, gfxBG2Y, - changed, line[2]); - } - - if(graphics.layerEnable & 0x0800) { - int changed = gfxBG3Changed; -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen(io_registers[REG_BG3CNT], BG3X_L, BG3X_H, BG3Y_L, BG3Y_H, - io_registers[REG_BG3PA], io_registers[REG_BG3PB], io_registers[REG_BG3PC], io_registers[REG_BG3PD], gfxBG3X, gfxBG3Y, - changed, line[3]); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF; - uint8_t inWin1Mask = io_registers[REG_WININ] >> 8; - uint8_t outMask = io_registers[REG_WINOUT] & 0xFF; - - for(int x = 0; x < 240; x++) { - uint32_t color = backdrop; - uint8_t top = 0x20; - uint8_t mask = outMask; - - if(!(line[5][x] & 0x80000000)) { - mask = io_registers[REG_WINOUT] >> 8; - } - - int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31; - int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31; - mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask); - mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask); - - if((mask & 4) && line[2][x] < color) { - color = line[2][x]; - top = 0x04; - } - - if((mask & 8) && (uint8_t)(line[3][x]>>24) < (uint8_t)(color >> 24)) { - color = line[3][x]; - top = 0x08; - } - - if((mask & 16) && (uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) { - color = line[4][x]; - top = 0x10; - } - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((mask & 4) && line[2][x] < back) { - back = line[2][x]; - top2 = 0x04; - } - - if((mask & 8) && (uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) { - back = line[3][x]; - top2 = 0x08; - } - - alpha_blend_brightness_switch(); - } else if(mask & 32) { - // special FX on the window - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((mask & 4) && (top != 0x04) && line[2][x] < back) { - back = line[2][x]; - top2 = 0x04; - } - - if((mask & 8) && (top != 0x08) && (uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) { - back = line[3][x]; - top2 = 0x08; - } - - if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - gfxBG3Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -/* -Mode 3 is a 15-bit (32768) colour bitmap graphics mode. -It has a single layer, background layer 2, the same size as the screen. -It doesn't support paging, scrolling, flipping, rotation or tiles. - -These routines only render a single line at a time, because of the way the GBA does events. -*/ - -void mode3RenderLine (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 3: Render Line\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; - -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen16Bit(gfxBG2X, gfxBG2Y, changed); - } - - uint32_t background = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) { - uint32_t color = background; - uint8_t top = 0x20; - - if(line[2][x] < color) { - color = line[2][x]; - top = 0x04; - } - - if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24)) { - color = line[4][x]; - top = 0x10; - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = background; - uint8_t top2 = 0x20; - - if(line[2][x] < background) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } - } - - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode3RenderLineNoWindow (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 3: Render Line No Window\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; - -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen16Bit(gfxBG2X, gfxBG2Y, changed); - } - - uint32_t background = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) { - uint32_t color = background; - uint8_t top = 0x20; - - if(line[2][x] < background) { - color = line[2][x]; - top = 0x04; - } - - if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24)) { - color = line[4][x]; - top = 0x10; - } - - if(!(color & 0x00010000)) { - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = background; - uint8_t top2 = 0x20; - - if(top != 0x04 && (line[2][x] < background) ) { - back = line[2][x]; - top2 = 0x04; - } - - if(top != 0x10 && ((uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24))) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } else { - // semi-transparent OBJ - uint32_t back = background; - uint8_t top2 = 0x20; - - if(line[2][x] < background) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode3RenderLineAll (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 3: Render Line All\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - bool inWindow0 = false; - bool inWindow1 = false; - - if(graphics.layerEnable & 0x2000) - { - uint8_t v0 = io_registers[REG_WIN0V] >> 8; - uint8_t v1 = io_registers[REG_WIN0V] & 255; - inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - - if(graphics.layerEnable & 0x4000) - { - uint8_t v0 = io_registers[REG_WIN1V] >> 8; - uint8_t v1 = io_registers[REG_WIN1V] & 255; - inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; - -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen16Bit(gfxBG2X, gfxBG2Y, changed); - } - - uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF; - uint8_t inWin1Mask = io_registers[REG_WININ] >> 8; - uint8_t outMask = io_registers[REG_WINOUT] & 0xFF; - - uint32_t background = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) { - uint32_t color = background; - uint8_t top = 0x20; - uint8_t mask = outMask; - - if(!(line[5][x] & 0x80000000)) { - mask = io_registers[REG_WINOUT] >> 8; - } - - int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31; - int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31; - mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask); - mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask); - - if((mask & 4) && line[2][x] < background) { - color = line[2][x]; - top = 0x04; - } - - if((mask & 16) && ((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24))) { - color = line[4][x]; - top = 0x10; - } - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = background; - uint8_t top2 = 0x20; - - if((mask & 4) && line[2][x] < background) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } else if(mask & 32) { - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = background; - uint8_t top2 = 0x20; - - if((mask & 4) && (top != 0x04) && line[2][x] < back) { - back = line[2][x]; - top2 = 0x04; - } - - if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -/* -Mode 4 is a 256 colour bitmap graphics mode with 2 swappable pages. -It has a single layer, background layer 2, the same size as the screen. -It doesn't support scrolling, flipping, rotation or tiles. - -These routines only render a single line at a time, because of the way the GBA does events. -*/ - -void mode4RenderLine (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 4: Render Line\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x400) - { - int changed = gfxBG2Changed; - -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen256(gfxBG2X, gfxBG2Y, changed); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) - { - uint32_t color = backdrop; - uint8_t top = 0x20; - - if(line[2][x] < backdrop) { - color = line[2][x]; - top = 0x04; - } - - if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) { - color = line[4][x]; - top = 0x10; - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if(line[2][x] < backdrop) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } - } - - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode4RenderLineNoWindow (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 4: Render Line No Window\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x400) - { - int changed = gfxBG2Changed; - -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen256(gfxBG2X, gfxBG2Y, changed); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) - { - uint32_t color = backdrop; - uint8_t top = 0x20; - - if(line[2][x] < backdrop) { - color = line[2][x]; - top = 0x04; - } - - if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) { - color = line[4][x]; - top = 0x10; - } - - if(!(color & 0x00010000)) { - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((top != 0x04) && line[2][x] < backdrop) { - back = line[2][x]; - top2 = 0x04; - } - - if((top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } else { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if(line[2][x] < back) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode4RenderLineAll (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 4: Render Line All\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - bool inWindow0 = false; - bool inWindow1 = false; - - if(graphics.layerEnable & 0x2000) - { - uint8_t v0 = io_registers[REG_WIN0V] >> 8; - uint8_t v1 = io_registers[REG_WIN0V] & 255; - inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - - if(graphics.layerEnable & 0x4000) - { - uint8_t v0 = io_registers[REG_WIN1V] >> 8; - uint8_t v1 = io_registers[REG_WIN1V] & 255; - inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - - if(graphics.layerEnable & 0x400) - { - int changed = gfxBG2Changed; - -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen256(gfxBG2X, gfxBG2Y, changed); - } - - uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000); - - uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF; - uint8_t inWin1Mask = io_registers[REG_WININ] >> 8; - uint8_t outMask = io_registers[REG_WINOUT] & 0xFF; - - for(int x = 0; x < 240; ++x) { - uint32_t color = backdrop; - uint8_t top = 0x20; - uint8_t mask = outMask; - - if(!(line[5][x] & 0x80000000)) - mask = io_registers[REG_WINOUT] >> 8; - - int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31; - int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31; - mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask); - mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask); - - if((mask & 4) && (line[2][x] < backdrop)) - { - color = line[2][x]; - top = 0x04; - } - - if((mask & 16) && ((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24))) - { - color = line[4][x]; - top = 0x10; - } - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((mask & 4) && line[2][x] < back) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } else if(mask & 32) { - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = backdrop; - uint8_t top2 = 0x20; - - if((mask & 4) && (top != 0x04) && (line[2][x] < backdrop)) { - back = line[2][x]; - top2 = 0x04; - } - - if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -/* -Mode 5 is a low resolution (160x128) 15-bit colour bitmap graphics mode -with 2 swappable pages! -It has a single layer, background layer 2, lower resolution than the screen. -It doesn't support scrolling, flipping, rotation or tiles. - -These routines only render a single line at a time, because of the way the GBA does events. -*/ - -void mode5RenderLine (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 5: Render Line\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; - -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen16Bit160(gfxBG2X, gfxBG2Y, changed); - } - - uint32_t background; - background = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) { - uint32_t color = background; - uint8_t top = 0x20; - - if(line[2][x] < background) { - color = line[2][x]; - top = 0x04; - } - - if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24)) { - color = line[4][x]; - top = 0x10; - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = background; - uint8_t top2 = 0x20; - - if(line[2][x] < back) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } - } - - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode5RenderLineNoWindow (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 5: Render Line No Window\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0400) { - int changed = gfxBG2Changed; - -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen16Bit160(gfxBG2X, gfxBG2Y, changed); - } - - uint32_t background; - background = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) { - uint32_t color = background; - uint8_t top = 0x20; - - if(line[2][x] < background) { - color = line[2][x]; - top = 0x04; - } - - if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24)) { - color = line[4][x]; - top = 0x10; - } - - if(!(color & 0x00010000)) { - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = background; - uint8_t top2 = 0x20; - - if((top != 0x04) && line[2][x] < background) { - back = line[2][x]; - top2 = 0x04; - } - - if((top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } else { - // semi-transparent OBJ - uint32_t back = background; - uint8_t top2 = 0x20; - - if(line[2][x] < back) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void mode5RenderLineAll (void) -{ -#ifdef REPORT_VIDEO_MODES - fprintf(stderr, "MODE 5: Render Line All\n"); -#endif - INIT_COLOR_DEPTH_LINE_MIX(); - - uint16_t *palette = (uint16_t *)graphics.paletteRAM; - - if(graphics.layerEnable & 0x0400) - { - int changed = gfxBG2Changed; - -#if 0 - if(gfxLastVCOUNT > io_registers[REG_VCOUNT]) - changed = 3; -#endif - - gfxDrawRotScreen16Bit160(gfxBG2X, gfxBG2Y, changed); - } - - - - bool inWindow0 = false; - bool inWindow1 = false; - - if(graphics.layerEnable & 0x2000) - { - uint8_t v0 = io_registers[REG_WIN0V] >> 8; - uint8_t v1 = io_registers[REG_WIN0V] & 255; - inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - - if(graphics.layerEnable & 0x4000) - { - uint8_t v0 = io_registers[REG_WIN1V] >> 8; - uint8_t v1 = io_registers[REG_WIN1V] & 255; - inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); -#ifndef ORIGINAL_BRANCHES - uint32_t condition = v1 >= v0; - int32_t condition_mask = ((condition) | -(condition)) >> 31; - inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask)))); -#else - if(v1 >= v0) - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1); - else - inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1); -#endif - } - - uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF; - uint8_t inWin1Mask = io_registers[REG_WININ] >> 8; - uint8_t outMask = io_registers[REG_WINOUT] & 0xFF; - - uint32_t background; - background = (READ16LE(&palette[0]) | 0x30000000); - - for(int x = 0; x < 240; ++x) { - uint32_t color = background; - uint8_t top = 0x20; - uint8_t mask = outMask; - - if(!(line[5][x] & 0x80000000)) { - mask = io_registers[REG_WINOUT] >> 8; - } - - int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31; - int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31; - mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask); - mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask); - - if((mask & 4) && (line[2][x] < background)) { - color = line[2][x]; - top = 0x04; - } - - if((mask & 16) && ((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24))) { - color = line[4][x]; - top = 0x10; - } - - if(color & 0x00010000) { - // semi-transparent OBJ - uint32_t back = background; - uint8_t top2 = 0x20; - - if((mask & 4) && line[2][x] < back) { - back = line[2][x]; - top2 = 0x04; - } - - alpha_blend_brightness_switch(); - } else if(mask & 32) { - switch((BLDMOD >> 6) & 3) { - case 0: - break; - case 1: - if(top & BLDMOD) - { - uint32_t back = background; - uint8_t top2 = 0x20; - - if((mask & 4) && (top != 0x04) && (line[2][x] < background)) { - back = line[2][x]; - top2 = 0x04; - } - - if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) { - back = line[4][x]; - top2 = 0x10; - } - - if(top2 & (BLDMOD>>8) && color < 0x80000000) - { - GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); - } - } - break; - case 2: - if(BLDMOD & top) - color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); - break; - case 3: - if(BLDMOD & top) - color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); - break; - } - } - - lineMix[x] = CONVERT_COLOR(color); - } - gfxBG2Changed = 0; - //gfxLastVCOUNT = io_registers[REG_VCOUNT]; -} - -void (Gigazoid::*renderLine)(void); -bool render_line_all_enabled; - -#define CPUUpdateRender() \ - render_line_all_enabled = false; \ - switch(io_registers[REG_DISPCNT] & 7) { \ - case 0: \ - if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \ - renderLine = &Gigazoid::mode0RenderLine; \ - else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \ - renderLine = &Gigazoid::mode0RenderLineNoWindow; \ - else { \ - renderLine = &Gigazoid::mode0RenderLineAll; \ - render_line_all_enabled = true; \ - } \ - break; \ - case 1: \ - if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \ - renderLine = &Gigazoid::mode1RenderLine; \ - else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \ - renderLine = &Gigazoid::mode1RenderLineNoWindow; \ - else { \ - renderLine = &Gigazoid::mode1RenderLineAll; \ - render_line_all_enabled = true; \ - } \ - break; \ - case 2: \ - if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \ - renderLine = &Gigazoid::mode2RenderLine; \ - else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \ - renderLine = &Gigazoid::mode2RenderLineNoWindow; \ - else { \ - renderLine = &Gigazoid::mode2RenderLineAll; \ - render_line_all_enabled = true; \ - } \ - break; \ - case 3: \ - if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \ - renderLine = &Gigazoid::mode3RenderLine; \ - else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \ - renderLine = &Gigazoid::mode3RenderLineNoWindow; \ - else { \ - renderLine = &Gigazoid::mode3RenderLineAll; \ - render_line_all_enabled = true; \ - } \ - break; \ - case 4: \ - if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \ - renderLine = &Gigazoid::mode4RenderLine; \ - else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \ - renderLine = &Gigazoid::mode4RenderLineNoWindow; \ - else { \ - renderLine = &Gigazoid::mode4RenderLineAll; \ - render_line_all_enabled = true; \ - } \ - break; \ - case 5: \ - if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \ - renderLine = &Gigazoid::mode5RenderLine; \ - else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \ - renderLine = &Gigazoid::mode5RenderLineNoWindow; \ - else { \ - renderLine = &Gigazoid::mode5RenderLineAll; \ - render_line_all_enabled = true; \ - } \ - } - -#define CPUSwap(a, b) \ -a ^= b; \ -b ^= a; \ -a ^= b; - -void CPUSwitchMode(int mode, bool saveState, bool breakLoop) -{ - CPU_UPDATE_CPSR(); - - switch(armMode) { - case 0x10: - case 0x1F: - bus.reg[R13_USR].I = bus.reg[13].I; - bus.reg[R14_USR].I = bus.reg[14].I; - bus.reg[17].I = bus.reg[16].I; - break; - case 0x11: - CPUSwap(bus.reg[R8_FIQ].I, bus.reg[8].I); - CPUSwap(bus.reg[R9_FIQ].I, bus.reg[9].I); - CPUSwap(bus.reg[R10_FIQ].I, bus.reg[10].I); - CPUSwap(bus.reg[R11_FIQ].I, bus.reg[11].I); - CPUSwap(bus.reg[R12_FIQ].I, bus.reg[12].I); - bus.reg[R13_FIQ].I = bus.reg[13].I; - bus.reg[R14_FIQ].I = bus.reg[14].I; - bus.reg[SPSR_FIQ].I = bus.reg[17].I; - break; - case 0x12: - bus.reg[R13_IRQ].I = bus.reg[13].I; - bus.reg[R14_IRQ].I = bus.reg[14].I; - bus.reg[SPSR_IRQ].I = bus.reg[17].I; - break; - case 0x13: - bus.reg[R13_SVC].I = bus.reg[13].I; - bus.reg[R14_SVC].I = bus.reg[14].I; - bus.reg[SPSR_SVC].I = bus.reg[17].I; - break; - case 0x17: - bus.reg[R13_ABT].I = bus.reg[13].I; - bus.reg[R14_ABT].I = bus.reg[14].I; - bus.reg[SPSR_ABT].I = bus.reg[17].I; - break; - case 0x1b: - bus.reg[R13_UND].I = bus.reg[13].I; - bus.reg[R14_UND].I = bus.reg[14].I; - bus.reg[SPSR_UND].I = bus.reg[17].I; - break; - } - - uint32_t CPSR = bus.reg[16].I; - uint32_t SPSR = bus.reg[17].I; - - switch(mode) { - case 0x10: - case 0x1F: - bus.reg[13].I = bus.reg[R13_USR].I; - bus.reg[14].I = bus.reg[R14_USR].I; - bus.reg[16].I = SPSR; - break; - case 0x11: - CPUSwap(bus.reg[8].I, bus.reg[R8_FIQ].I); - CPUSwap(bus.reg[9].I, bus.reg[R9_FIQ].I); - CPUSwap(bus.reg[10].I, bus.reg[R10_FIQ].I); - CPUSwap(bus.reg[11].I, bus.reg[R11_FIQ].I); - CPUSwap(bus.reg[12].I, bus.reg[R12_FIQ].I); - bus.reg[13].I = bus.reg[R13_FIQ].I; - bus.reg[14].I = bus.reg[R14_FIQ].I; - if(saveState) - bus.reg[17].I = CPSR; else - bus.reg[17].I = bus.reg[SPSR_FIQ].I; - break; - case 0x12: - bus.reg[13].I = bus.reg[R13_IRQ].I; - bus.reg[14].I = bus.reg[R14_IRQ].I; - bus.reg[16].I = SPSR; - if(saveState) - bus.reg[17].I = CPSR; - else - bus.reg[17].I = bus.reg[SPSR_IRQ].I; - break; - case 0x13: - bus.reg[13].I = bus.reg[R13_SVC].I; - bus.reg[14].I = bus.reg[R14_SVC].I; - bus.reg[16].I = SPSR; - if(saveState) - bus.reg[17].I = CPSR; - else - bus.reg[17].I = bus.reg[SPSR_SVC].I; - break; - case 0x17: - bus.reg[13].I = bus.reg[R13_ABT].I; - bus.reg[14].I = bus.reg[R14_ABT].I; - bus.reg[16].I = SPSR; - if(saveState) - bus.reg[17].I = CPSR; - else - bus.reg[17].I = bus.reg[SPSR_ABT].I; - break; - case 0x1b: - bus.reg[13].I = bus.reg[R13_UND].I; - bus.reg[14].I = bus.reg[R14_UND].I; - bus.reg[16].I = SPSR; - if(saveState) - bus.reg[17].I = CPSR; - else - bus.reg[17].I = bus.reg[SPSR_UND].I; - break; - default: - break; - } - armMode = mode; - CPUUpdateFlags(breakLoop); - CPU_UPDATE_CPSR(); -} - - - -void doDMA(uint32_t &s, uint32_t &d, uint32_t si, uint32_t di, uint32_t c, int transfer32) -{ - int sm = s >> 24; - int dm = d >> 24; - int sw = 0; - int dw = 0; - int sc = c; - - cpuDmaCount = c; - // This is done to get the correct waitstates. - int32_t sm_gt_15_mask = ((sm>15) | -(sm>15)) >> 31; - int32_t dm_gt_15_mask = ((dm>15) | -(dm>15)) >> 31; - sm = ((((15) & sm_gt_15_mask) | ((((sm) & ~(sm_gt_15_mask)))))); - dm = ((((15) & dm_gt_15_mask) | ((((dm) & ~(dm_gt_15_mask)))))); - - //if ((sm>=0x05) && (sm<=0x07) || (dm>=0x05) && (dm <=0x07)) - // blank = (((io_registers[REG_DISPSTAT] | ((io_registers[REG_DISPSTAT] >> 1)&1))==1) ? true : false); - - if(transfer32) - { - s &= 0xFFFFFFFC; - if(s < 0x02000000 && (bus.reg[15].I >> 24)) - { - do - { - CPUWriteMemory(d, 0); - d += di; - c--; - }while(c != 0); - } - else - { - do { - CPUWriteMemory(d, CPUReadMemory(s)); - d += di; - s += si; - c--; - }while(c != 0); - } - } - else - { - s &= 0xFFFFFFFE; - si = (int)si >> 1; - di = (int)di >> 1; - if(s < 0x02000000 && (bus.reg[15].I >> 24)) - { - do { - CPUWriteHalfWord(d, 0); - d += di; - c--; - }while(c != 0); - } - else - { - do{ - CPUWriteHalfWord(d, CPUReadHalfWord(s)); - d += di; - s += si; - c--; - }while(c != 0); - } - } - - cpuDmaCount = 0; - - if(transfer32) - { - sw = 1+memoryWaitSeq32[sm & 15]; - dw = 1+memoryWaitSeq32[dm & 15]; - cpuDmaTicksToUpdate += (sw+dw)*(sc-1) + 6 + memoryWait32[sm & 15] + memoryWaitSeq32[dm & 15]; - } - else - { - sw = 1+memoryWaitSeq[sm & 15]; - dw = 1+memoryWaitSeq[dm & 15]; - cpuDmaTicksToUpdate += (sw+dw)*(sc-1) + 6 + memoryWait[sm & 15] + memoryWaitSeq[dm & 15]; - } -} - - -void CPUCheckDMA(int reason, int dmamask) -{ - uint32_t arrayval[] = {4, (uint32_t)-4, 0, 4}; - // DMA 0 - if((DM0CNT_H & 0x8000) && (dmamask & 1)) - { - if(((DM0CNT_H >> 12) & 3) == reason) - { - uint32_t sourceIncrement, destIncrement; - uint32_t condition1 = ((DM0CNT_H >> 7) & 3); - uint32_t condition2 = ((DM0CNT_H >> 5) & 3); - sourceIncrement = arrayval[condition1]; - destIncrement = arrayval[condition2]; - doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement, - DM0CNT_L ? DM0CNT_L : 0x4000, - DM0CNT_H & 0x0400); - - if(DM0CNT_H & 0x4000) - { - io_registers[REG_IF] |= 0x0100; - UPDATE_REG(0x202, io_registers[REG_IF]); - cpuNextEvent = cpuTotalTicks; - } - - if(((DM0CNT_H >> 5) & 3) == 3) { - dma0Dest = DM0DAD_L | (DM0DAD_H << 16); - } - - if(!(DM0CNT_H & 0x0200) || (reason == 0)) { - DM0CNT_H &= 0x7FFF; - UPDATE_REG(0xBA, DM0CNT_H); - } - } - } - - // DMA 1 - if((DM1CNT_H & 0x8000) && (dmamask & 2)) { - if(((DM1CNT_H >> 12) & 3) == reason) { - uint32_t sourceIncrement, destIncrement; - uint32_t condition1 = ((DM1CNT_H >> 7) & 3); - uint32_t condition2 = ((DM1CNT_H >> 5) & 3); - sourceIncrement = arrayval[condition1]; - destIncrement = arrayval[condition2]; - uint32_t di_value, c_value, transfer_value; - if(reason == 3) - { - di_value = 0; - c_value = 4; - transfer_value = 0x0400; - } - else - { - di_value = destIncrement; - c_value = DM1CNT_L ? DM1CNT_L : 0x4000; - transfer_value = DM1CNT_H & 0x0400; - } - doDMA(dma1Source, dma1Dest, sourceIncrement, di_value, c_value, transfer_value); - - if(DM1CNT_H & 0x4000) { - io_registers[REG_IF] |= 0x0200; - UPDATE_REG(0x202, io_registers[REG_IF]); - cpuNextEvent = cpuTotalTicks; - } - - if(((DM1CNT_H >> 5) & 3) == 3) { - dma1Dest = DM1DAD_L | (DM1DAD_H << 16); - } - - if(!(DM1CNT_H & 0x0200) || (reason == 0)) { - DM1CNT_H &= 0x7FFF; - UPDATE_REG(0xC6, DM1CNT_H); - } - } - } - - // DMA 2 - if((DM2CNT_H & 0x8000) && (dmamask & 4)) { - if(((DM2CNT_H >> 12) & 3) == reason) { - uint32_t sourceIncrement, destIncrement; - uint32_t condition1 = ((DM2CNT_H >> 7) & 3); - uint32_t condition2 = ((DM2CNT_H >> 5) & 3); - sourceIncrement = arrayval[condition1]; - destIncrement = arrayval[condition2]; - uint32_t di_value, c_value, transfer_value; - if(reason == 3) - { - di_value = 0; - c_value = 4; - transfer_value = 0x0400; - } - else - { - di_value = destIncrement; - c_value = DM2CNT_L ? DM2CNT_L : 0x4000; - transfer_value = DM2CNT_H & 0x0400; - } - doDMA(dma2Source, dma2Dest, sourceIncrement, di_value, c_value, transfer_value); - - if(DM2CNT_H & 0x4000) { - io_registers[REG_IF] |= 0x0400; - UPDATE_REG(0x202, io_registers[REG_IF]); - cpuNextEvent = cpuTotalTicks; - } - - if(((DM2CNT_H >> 5) & 3) == 3) { - dma2Dest = DM2DAD_L | (DM2DAD_H << 16); - } - - if(!(DM2CNT_H & 0x0200) || (reason == 0)) { - DM2CNT_H &= 0x7FFF; - UPDATE_REG(0xD2, DM2CNT_H); - } - } - } - - // DMA 3 - if((DM3CNT_H & 0x8000) && (dmamask & 8)) - { - if(((DM3CNT_H >> 12) & 3) == reason) - { - uint32_t sourceIncrement, destIncrement; - uint32_t condition1 = ((DM3CNT_H >> 7) & 3); - uint32_t condition2 = ((DM3CNT_H >> 5) & 3); - sourceIncrement = arrayval[condition1]; - destIncrement = arrayval[condition2]; - doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement, - DM3CNT_L ? DM3CNT_L : 0x10000, - DM3CNT_H & 0x0400); - if(DM3CNT_H & 0x4000) { - io_registers[REG_IF] |= 0x0800; - UPDATE_REG(0x202, io_registers[REG_IF]); - cpuNextEvent = cpuTotalTicks; - } - - if(((DM3CNT_H >> 5) & 3) == 3) { - dma3Dest = DM3DAD_L | (DM3DAD_H << 16); - } - - if(!(DM3CNT_H & 0x0200) || (reason == 0)) { - DM3CNT_H &= 0x7FFF; - UPDATE_REG(0xDE, DM3CNT_H); - } - } - } -} - -uint16_t *address_lut[0x300]; - -void CPUUpdateRegister(uint32_t address, uint16_t value) -{ - switch(address) - { - case 0x00: - { - if((value & 7) > 5) // display modes above 0-5 are prohibited - io_registers[REG_DISPCNT] = (value & 7); - - bool change = (0 != ((io_registers[REG_DISPCNT] ^ value) & 0x80)); - bool changeBG = (0 != ((io_registers[REG_DISPCNT] ^ value) & 0x0F00)); - uint16_t changeBGon = ((~io_registers[REG_DISPCNT]) & value) & 0x0F00; // these layers are being activated - - io_registers[REG_DISPCNT] = (value & 0xFFF7); // bit 3 can only be accessed by the BIOS to enable GBC mode - UPDATE_REG(0x00, io_registers[REG_DISPCNT]); - - graphics.layerEnable = value; - - if(changeBGon) - { - graphics.layerEnableDelay = 4; - graphics.layerEnable &= ~changeBGon; - } - - windowOn = (graphics.layerEnable & 0x6000) ? true : false; - if(change && !((value & 0x80))) - { - if(!(io_registers[REG_DISPSTAT] & 1)) - { - graphics.lcdTicks = 1008; - io_registers[REG_DISPSTAT] &= 0xFFFC; - UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); - CPUCompareVCOUNT(); - } - } - CPUUpdateRender(); - // we only care about changes in BG0-BG3 - if(changeBG) - { - if(!(graphics.layerEnable & 0x0100)) - memset(line[0], -1, 240 * sizeof(u32)); - if(!(graphics.layerEnable & 0x0200)) - memset(line[1], -1, 240 * sizeof(u32)); - if(!(graphics.layerEnable & 0x0400)) - memset(line[2], -1, 240 * sizeof(u32)); - if(!(graphics.layerEnable & 0x0800)) - memset(line[3], -1, 240 * sizeof(u32)); - } - break; - } - case 0x04: - io_registers[REG_DISPSTAT] = (value & 0xFF38) | (io_registers[REG_DISPSTAT] & 7); - UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); - break; - case 0x06: - // not writable - break; - case 0x08: /* BG0CNT */ - case 0x0A: /* BG1CNT */ - *address_lut[address] = (value & 0xDFCF); - UPDATE_REG(address, *address_lut[address]); - break; - case 0x0C: /* BG2CNT */ - case 0x0E: /* BG3CNT */ - *address_lut[address] = (value & 0xFFCF); - UPDATE_REG(address, *address_lut[address]); - break; - case 0x10: /* BG0HOFS */ - case 0x12: /* BG0VOFS */ - case 0x14: /* BG1HOFS */ - case 0x16: /* BG1VOFS */ - case 0x18: /* BG2HOFS */ - case 0x1A: /* BG2VOFS */ - case 0x1C: /* BG3HOFS */ - case 0x1E: /* BG3VOFS */ - *address_lut[address] = value & 511; - UPDATE_REG(address, *address_lut[address]); - break; - case 0x20: /* BG2PA */ - case 0x22: /* BG2PB */ - case 0x24: /* BG2PC */ - case 0x26: /* BG2PD */ - *address_lut[address] = value; - UPDATE_REG(address, *address_lut[address]); - break; - case 0x28: - BG2X_L = value; - UPDATE_REG(0x28, BG2X_L); - gfxBG2Changed |= 1; - break; - case 0x2A: - BG2X_H = (value & 0xFFF); - UPDATE_REG(0x2A, BG2X_H); - gfxBG2Changed |= 1; - break; - case 0x2C: - BG2Y_L = value; - UPDATE_REG(0x2C, BG2Y_L); - gfxBG2Changed |= 2; - break; - case 0x2E: - BG2Y_H = value & 0xFFF; - UPDATE_REG(0x2E, BG2Y_H); - gfxBG2Changed |= 2; - break; - case 0x30: /* BG3PA */ - case 0x32: /* BG3PB */ - case 0x34: /* BG3PC */ - case 0x36: /* BG3PD */ - *address_lut[address] = value; - UPDATE_REG(address, *address_lut[address]); - break; - case 0x38: - BG3X_L = value; - UPDATE_REG(0x38, BG3X_L); - gfxBG3Changed |= 1; - break; - case 0x3A: - BG3X_H = value & 0xFFF; - UPDATE_REG(0x3A, BG3X_H); - gfxBG3Changed |= 1; - break; - case 0x3C: - BG3Y_L = value; - UPDATE_REG(0x3C, BG3Y_L); - gfxBG3Changed |= 2; - break; - case 0x3E: - BG3Y_H = value & 0xFFF; - UPDATE_REG(0x3E, BG3Y_H); - gfxBG3Changed |= 2; - break; - case 0x40: - io_registers[REG_WIN0H] = value; - UPDATE_REG(0x40, io_registers[REG_WIN0H]); - CPUUpdateWindow0(); - break; - case 0x42: - io_registers[REG_WIN1H] = value; - UPDATE_REG(0x42, io_registers[REG_WIN1H]); - CPUUpdateWindow1(); - break; - case 0x44: - case 0x46: - *address_lut[address] = value; - UPDATE_REG(address, *address_lut[address]); - break; - case 0x48: /* WININ */ - case 0x4A: /* WINOUT */ - *address_lut[address] = value & 0x3F3F; - UPDATE_REG(address, *address_lut[address]); - break; - case 0x4C: - MOSAIC = value; - UPDATE_REG(0x4C, MOSAIC); - break; - case 0x50: - BLDMOD = value & 0x3FFF; - UPDATE_REG(0x50, BLDMOD); - fxOn = ((BLDMOD>>6)&3) != 0; - CPUUpdateRender(); - break; - case 0x52: - COLEV = value & 0x1F1F; - UPDATE_REG(0x52, COLEV); - break; - case 0x54: - COLY = value & 0x1F; - UPDATE_REG(0x54, COLY); - break; - case 0x60: - case 0x62: - case 0x64: - case 0x68: - case 0x6c: - case 0x70: - case 0x72: - case 0x74: - case 0x78: - case 0x7c: - case 0x80: - case 0x84: - { - int gb_addr[2] = {address & 0xFF, (address & 0xFF) + 1}; - uint32_t address_array[2] = {address & 0xFF, (address&0xFF)+1}; - uint8_t data_array[2] = {(uint8_t)(value & 0xFF), (uint8_t)(value>>8)}; - gb_addr[0] = table[gb_addr[0] - 0x60]; - gb_addr[1] = table[gb_addr[1] - 0x60]; - soundEvent_u8_parallel(gb_addr, address_array, data_array); - break; - } - case 0x82: - case 0x88: - case 0xa0: - case 0xa2: - case 0xa4: - case 0xa6: - case 0x90: - case 0x92: - case 0x94: - case 0x96: - case 0x98: - case 0x9a: - case 0x9c: - case 0x9e: - soundEvent_u16(address&0xFF, value); - break; - case 0xB0: - DM0SAD_L = value; - UPDATE_REG(0xB0, DM0SAD_L); - break; - case 0xB2: - DM0SAD_H = value & 0x07FF; - UPDATE_REG(0xB2, DM0SAD_H); - break; - case 0xB4: - DM0DAD_L = value; - UPDATE_REG(0xB4, DM0DAD_L); - break; - case 0xB6: - DM0DAD_H = value & 0x07FF; - UPDATE_REG(0xB6, DM0DAD_H); - break; - case 0xB8: - DM0CNT_L = value & 0x3FFF; - UPDATE_REG(0xB8, 0); - break; - case 0xBA: - { - bool start = ((DM0CNT_H ^ value) & 0x8000) ? true : false; - value &= 0xF7E0; - - DM0CNT_H = value; - UPDATE_REG(0xBA, DM0CNT_H); - - if(start && (value & 0x8000)) - { - dma0Source = DM0SAD_L | (DM0SAD_H << 16); - dma0Dest = DM0DAD_L | (DM0DAD_H << 16); - CPUCheckDMA(0, 1); - } - } - break; - case 0xBC: - DM1SAD_L = value; - UPDATE_REG(0xBC, DM1SAD_L); - break; - case 0xBE: - DM1SAD_H = value & 0x0FFF; - UPDATE_REG(0xBE, DM1SAD_H); - break; - case 0xC0: - DM1DAD_L = value; - UPDATE_REG(0xC0, DM1DAD_L); - break; - case 0xC2: - DM1DAD_H = value & 0x07FF; - UPDATE_REG(0xC2, DM1DAD_H); - break; - case 0xC4: - DM1CNT_L = value & 0x3FFF; - UPDATE_REG(0xC4, 0); - break; - case 0xC6: - { - bool start = ((DM1CNT_H ^ value) & 0x8000) ? true : false; - value &= 0xF7E0; - - DM1CNT_H = value; - UPDATE_REG(0xC6, DM1CNT_H); - - if(start && (value & 0x8000)) - { - dma1Source = DM1SAD_L | (DM1SAD_H << 16); - dma1Dest = DM1DAD_L | (DM1DAD_H << 16); - CPUCheckDMA(0, 2); - } - } - break; - case 0xC8: - DM2SAD_L = value; - UPDATE_REG(0xC8, DM2SAD_L); - break; - case 0xCA: - DM2SAD_H = value & 0x0FFF; - UPDATE_REG(0xCA, DM2SAD_H); - break; - case 0xCC: - DM2DAD_L = value; - UPDATE_REG(0xCC, DM2DAD_L); - break; - case 0xCE: - DM2DAD_H = value & 0x07FF; - UPDATE_REG(0xCE, DM2DAD_H); - break; - case 0xD0: - DM2CNT_L = value & 0x3FFF; - UPDATE_REG(0xD0, 0); - break; - case 0xD2: - { - bool start = ((DM2CNT_H ^ value) & 0x8000) ? true : false; - - value &= 0xF7E0; - - DM2CNT_H = value; - UPDATE_REG(0xD2, DM2CNT_H); - - if(start && (value & 0x8000)) { - dma2Source = DM2SAD_L | (DM2SAD_H << 16); - dma2Dest = DM2DAD_L | (DM2DAD_H << 16); - - CPUCheckDMA(0, 4); - } - } - break; - case 0xD4: - DM3SAD_L = value; - UPDATE_REG(0xD4, DM3SAD_L); - break; - case 0xD6: - DM3SAD_H = value & 0x0FFF; - UPDATE_REG(0xD6, DM3SAD_H); - break; - case 0xD8: - DM3DAD_L = value; - UPDATE_REG(0xD8, DM3DAD_L); - break; - case 0xDA: - DM3DAD_H = value & 0x0FFF; - UPDATE_REG(0xDA, DM3DAD_H); - break; - case 0xDC: - DM3CNT_L = value; - UPDATE_REG(0xDC, 0); - break; - case 0xDE: - { - bool start = ((DM3CNT_H ^ value) & 0x8000) ? true : false; - - value &= 0xFFE0; - - DM3CNT_H = value; - UPDATE_REG(0xDE, DM3CNT_H); - - if(start && (value & 0x8000)) { - dma3Source = DM3SAD_L | (DM3SAD_H << 16); - dma3Dest = DM3DAD_L | (DM3DAD_H << 16); - CPUCheckDMA(0,8); - } - } - break; - case 0x100: - timer0Reload = value; - break; - case 0x102: - timer0Value = value; - timerOnOffDelay|=1; - cpuNextEvent = cpuTotalTicks; - break; - case 0x104: - timer1Reload = value; - break; - case 0x106: - timer1Value = value; - timerOnOffDelay|=2; - cpuNextEvent = cpuTotalTicks; - break; - case 0x108: - timer2Reload = value; - break; - case 0x10A: - timer2Value = value; - timerOnOffDelay|=4; - cpuNextEvent = cpuTotalTicks; - break; - case 0x10C: - timer3Reload = value; - break; - case 0x10E: - timer3Value = value; - timerOnOffDelay|=8; - cpuNextEvent = cpuTotalTicks; - break; - case 0x130: - io_registers[REG_P1] |= (value & 0x3FF); - UPDATE_REG(0x130, io_registers[REG_P1]); - break; - case 0x132: - UPDATE_REG(0x132, value & 0xC3FF); - break; - - - case 0x200: - io_registers[REG_IE] = value & 0x3FFF; - UPDATE_REG(0x200, io_registers[REG_IE]); - if ((io_registers[REG_IME] & 1) && (io_registers[REG_IF] & io_registers[REG_IE]) && armIrqEnable) - cpuNextEvent = cpuTotalTicks; - break; - case 0x202: - io_registers[REG_IF] ^= (value & io_registers[REG_IF]); - UPDATE_REG(0x202, io_registers[REG_IF]); - break; - case 0x204: - { - memoryWait[0x0e] = memoryWaitSeq[0x0e] = gamepakRamWaitState[value & 3]; - - memoryWait[0x08] = memoryWait[0x09] = 3; - memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = 1; - - memoryWait[0x0a] = memoryWait[0x0b] = 3; - memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = 1; - - memoryWait[0x0c] = memoryWait[0x0d] = 3; - memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = 1; - - memoryWait32[8] = memoryWait[8] + memoryWaitSeq[8] + 1; - memoryWaitSeq32[8] = memoryWaitSeq[8]*2 + 1; - - memoryWait32[9] = memoryWait[9] + memoryWaitSeq[9] + 1; - memoryWaitSeq32[9] = memoryWaitSeq[9]*2 + 1; - - memoryWait32[10] = memoryWait[10] + memoryWaitSeq[10] + 1; - memoryWaitSeq32[10] = memoryWaitSeq[10]*2 + 1; - - memoryWait32[11] = memoryWait[11] + memoryWaitSeq[11] + 1; - memoryWaitSeq32[11] = memoryWaitSeq[11]*2 + 1; - - memoryWait32[12] = memoryWait[12] + memoryWaitSeq[12] + 1; - memoryWaitSeq32[12] = memoryWaitSeq[12]*2 + 1; - - memoryWait32[13] = memoryWait[13] + memoryWaitSeq[13] + 1; - memoryWaitSeq32[13] = memoryWaitSeq[13]*2 + 1; - - memoryWait32[14] = memoryWait[14] + memoryWaitSeq[14] + 1; - memoryWaitSeq32[14] = memoryWaitSeq[14]*2 + 1; - - if((value & 0x4000) == 0x4000) - bus.busPrefetchEnable = true; - else - bus.busPrefetchEnable = false; - - bus.busPrefetch = false; - bus.busPrefetchCount = 0; - - UPDATE_REG(0x204, value & 0x7FFF); - - } - break; - case 0x208: - io_registers[REG_IME] = value & 1; - UPDATE_REG(0x208, io_registers[REG_IME]); - if ((io_registers[REG_IME] & 1) && (io_registers[REG_IF] & io_registers[REG_IE]) && armIrqEnable) - cpuNextEvent = cpuTotalTicks; - break; - case 0x300: - if(value != 0) - value &= 0xFFFE; - UPDATE_REG(0x300, value); - break; - default: - UPDATE_REG(address&0x3FE, value); - break; - } -} - - -void CPUInit(const u8 *biosfile, const u32 biosfilelen) -{ - eepromInUse = false; - switch(cpuSaveType) - { - case 0: // automatic - default: - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = &Gigazoid::flashSaveDecide; // EEPROM usage is automatically detected - break; - case 1: // EEPROM - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = &Gigazoid::dummyWrite; // EEPROM usage is automatically detected - break; - case 2: // SRAM - cpuEEPROMEnabled = false; - cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = &Gigazoid::sramWrite; - break; - case 3: // FLASH - cpuEEPROMEnabled = false; - cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = &Gigazoid::flashWrite; - break; - case 4: // EEPROM+Sensor - cpuEEPROMEnabled = true; - cpuEEPROMSensorEnabled = true; - cpuSaveGameFunc = &Gigazoid::dummyWrite; // EEPROM usage is automatically detected - break; - case 5: // NONE - cpuEEPROMEnabled = false; - cpuEEPROMSensorEnabled = false; - cpuSaveGameFunc = &Gigazoid::dummyWrite; - break; - } - - memcpy(bios, biosfile, 16384); - - int i = 0; - - biosProtected[0] = 0x00; - biosProtected[1] = 0xf0; - biosProtected[2] = 0x29; - biosProtected[3] = 0xe1; - - for(i = 0; i < 256; i++) - { - int count = 0; - int j; - for(j = 0; j < 8; j++) - if(i & (1 << j)) - count++; - cpuBitsSet[i] = count; - - for(j = 0; j < 8; j++) - if(i & (1 << j)) - break; - } - - for(i = 0; i < 0x400; i++) - ioReadable[i] = true; - for(i = 0x10; i < 0x48; i++) - ioReadable[i] = false; - for(i = 0x4c; i < 0x50; i++) - ioReadable[i] = false; - for(i = 0x54; i < 0x60; i++) - ioReadable[i] = false; - for(i = 0x8c; i < 0x90; i++) - ioReadable[i] = false; - for(i = 0xa0; i < 0xb8; i++) - ioReadable[i] = false; - for(i = 0xbc; i < 0xc4; i++) - ioReadable[i] = false; - for(i = 0xc8; i < 0xd0; i++) - ioReadable[i] = false; - for(i = 0xd4; i < 0xdc; i++) - ioReadable[i] = false; - for(i = 0xe0; i < 0x100; i++) - ioReadable[i] = false; - for(i = 0x110; i < 0x120; i++) - ioReadable[i] = false; - for(i = 0x12c; i < 0x130; i++) - ioReadable[i] = false; - for(i = 0x138; i < 0x140; i++) - ioReadable[i] = false; - for(i = 0x144; i < 0x150; i++) - ioReadable[i] = false; - for(i = 0x15c; i < 0x200; i++) - ioReadable[i] = false; - for(i = 0x20c; i < 0x300; i++) - ioReadable[i] = false; - for(i = 0x304; i < 0x400; i++) - ioReadable[i] = false; - - // what is this? - if(romSize < 0x1fe2000) { - *((uint16_t *)&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA - *((uint16_t *)&rom[0x1fe209e]) = 0x4770; // BX LR - } - - graphics.layerEnable = 0xff00; - graphics.layerEnableDelay = 1; - io_registers[REG_DISPCNT] = 0x0080; - io_registers[REG_DISPSTAT] = 0; - graphics.lcdTicks = (useBios && !skipBios) ? 1008 : 208; - - /* address lut for use in CPUUpdateRegister */ - address_lut[0x08] = &io_registers[REG_BG0CNT]; - address_lut[0x0A] = &io_registers[REG_BG1CNT]; - address_lut[0x0C] = &io_registers[REG_BG2CNT]; - address_lut[0x0E] = &io_registers[REG_BG3CNT]; - address_lut[0x10] = &io_registers[REG_BG0HOFS]; - address_lut[0x12] = &io_registers[REG_BG0VOFS]; - address_lut[0x14] = &io_registers[REG_BG1HOFS]; - address_lut[0x16] = &io_registers[REG_BG1VOFS]; - address_lut[0x18] = &io_registers[REG_BG2HOFS]; - address_lut[0x1A] = &io_registers[REG_BG2VOFS]; - address_lut[0x1C] = &io_registers[REG_BG3HOFS]; - address_lut[0x1E] = &io_registers[REG_BG3VOFS]; - address_lut[0x20] = &io_registers[REG_BG2PA]; - address_lut[0x22] = &io_registers[REG_BG2PB]; - address_lut[0x24] = &io_registers[REG_BG2PC]; - address_lut[0x26] = &io_registers[REG_BG2PD]; - address_lut[0x48] = &io_registers[REG_WININ]; - address_lut[0x4A] = &io_registers[REG_WINOUT]; - address_lut[0x30] = &io_registers[REG_BG3PA]; - address_lut[0x32] = &io_registers[REG_BG3PB]; - address_lut[0x34] = &io_registers[REG_BG3PC]; - address_lut[0x36] = &io_registers[REG_BG3PD]; - address_lut[0x40] = &io_registers[REG_WIN0H]; - address_lut[0x42] = &io_registers[REG_WIN1H]; - address_lut[0x44] = &io_registers[REG_WIN0V]; - address_lut[0x46] = &io_registers[REG_WIN1V]; -} - -void CPUReset (void) -{ - rtcReset(); - memset(&bus.reg[0], 0, sizeof(bus.reg)); // clean registers - memset(oam, 0, 0x400); // clean OAM - memset(graphics.paletteRAM, 0, 0x400); // clean palette - memset(pix, 0, 4 * 160 * 240); // clean picture - memset(vram, 0, 0x20000); // clean vram - memset(ioMem, 0, 0x400); // clean io memory - - io_registers[REG_DISPCNT] = 0x0080; - io_registers[REG_DISPSTAT] = 0x0000; - io_registers[REG_VCOUNT] = (useBios && !skipBios) ? 0 :0x007E; - io_registers[REG_BG0CNT] = 0x0000; - io_registers[REG_BG1CNT] = 0x0000; - io_registers[REG_BG2CNT] = 0x0000; - io_registers[REG_BG3CNT] = 0x0000; - io_registers[REG_BG0HOFS] = 0x0000; - io_registers[REG_BG0VOFS] = 0x0000; - io_registers[REG_BG1HOFS] = 0x0000; - io_registers[REG_BG1VOFS] = 0x0000; - io_registers[REG_BG2HOFS] = 0x0000; - io_registers[REG_BG2VOFS] = 0x0000; - io_registers[REG_BG3HOFS] = 0x0000; - io_registers[REG_BG3VOFS] = 0x0000; - io_registers[REG_BG2PA] = 0x0100; - io_registers[REG_BG2PB] = 0x0000; - io_registers[REG_BG2PC] = 0x0000; - io_registers[REG_BG2PD] = 0x0100; - BG2X_L = 0x0000; - BG2X_H = 0x0000; - BG2Y_L = 0x0000; - BG2Y_H = 0x0000; - io_registers[REG_BG3PA] = 0x0100; - io_registers[REG_BG3PB] = 0x0000; - io_registers[REG_BG3PC] = 0x0000; - io_registers[REG_BG3PD] = 0x0100; - BG3X_L = 0x0000; - BG3X_H = 0x0000; - BG3Y_L = 0x0000; - BG3Y_H = 0x0000; - io_registers[REG_WIN0H] = 0x0000; - io_registers[REG_WIN1H] = 0x0000; - io_registers[REG_WIN0V] = 0x0000; - io_registers[REG_WIN1V] = 0x0000; - io_registers[REG_WININ] = 0x0000; - io_registers[REG_WINOUT] = 0x0000; - MOSAIC = 0x0000; - BLDMOD = 0x0000; - COLEV = 0x0000; - COLY = 0x0000; - DM0SAD_L = 0x0000; - DM0SAD_H = 0x0000; - DM0DAD_L = 0x0000; - DM0DAD_H = 0x0000; - DM0CNT_L = 0x0000; - DM0CNT_H = 0x0000; - DM1SAD_L = 0x0000; - DM1SAD_H = 0x0000; - DM1DAD_L = 0x0000; - DM1DAD_H = 0x0000; - DM1CNT_L = 0x0000; - DM1CNT_H = 0x0000; - DM2SAD_L = 0x0000; - DM2SAD_H = 0x0000; - DM2DAD_L = 0x0000; - DM2DAD_H = 0x0000; - DM2CNT_L = 0x0000; - DM2CNT_H = 0x0000; - DM3SAD_L = 0x0000; - DM3SAD_H = 0x0000; - DM3DAD_L = 0x0000; - DM3DAD_H = 0x0000; - DM3CNT_L = 0x0000; - DM3CNT_H = 0x0000; - io_registers[REG_TM0D] = 0x0000; - io_registers[REG_TM0CNT] = 0x0000; - io_registers[REG_TM1D] = 0x0000; - io_registers[REG_TM1CNT] = 0x0000; - io_registers[REG_TM2D] = 0x0000; - io_registers[REG_TM2CNT] = 0x0000; - io_registers[REG_TM3D] = 0x0000; - io_registers[REG_TM3CNT] = 0x0000; - io_registers[REG_P1] = 0x03FF; - io_registers[REG_IE] = 0x0000; - io_registers[REG_IF] = 0x0000; - io_registers[REG_IME] = 0x0000; - - armMode = 0x1F; - - if(cpuIsMultiBoot) { - bus.reg[13].I = 0x03007F00; - bus.reg[15].I = 0x02000000; - bus.reg[16].I = 0x00000000; - bus.reg[R13_IRQ].I = 0x03007FA0; - bus.reg[R13_SVC].I = 0x03007FE0; - armIrqEnable = true; - } else { -#ifdef HAVE_HLE_BIOS - if(useBios && !skipBios) - { - bus.reg[15].I = 0x00000000; - armMode = 0x13; - armIrqEnable = false; - } - else - { -#endif - bus.reg[13].I = 0x03007F00; - bus.reg[15].I = 0x08000000; - bus.reg[16].I = 0x00000000; - bus.reg[R13_IRQ].I = 0x03007FA0; - bus.reg[R13_SVC].I = 0x03007FE0; - armIrqEnable = true; -#ifdef HAVE_HLE_BIOS - } -#endif - } - armState = true; - C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false; - UPDATE_REG(0x00, io_registers[REG_DISPCNT]); - UPDATE_REG(0x06, io_registers[REG_VCOUNT]); - UPDATE_REG(0x20, io_registers[REG_BG2PA]); - UPDATE_REG(0x26, io_registers[REG_BG2PD]); - UPDATE_REG(0x30, io_registers[REG_BG3PA]); - UPDATE_REG(0x36, io_registers[REG_BG3PD]); - UPDATE_REG(0x130, io_registers[REG_P1]); - UPDATE_REG(0x88, 0x200); - - // disable FIQ - bus.reg[16].I |= 0x40; - - CPU_UPDATE_CPSR(); - - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 4; - - // reset internal state - holdState = false; - - biosProtected[0] = 0x00; - biosProtected[1] = 0xf0; - biosProtected[2] = 0x29; - biosProtected[3] = 0xe1; - - graphics.lcdTicks = (useBios && !skipBios) ? 1008 : 208; - timer0On = false; - timer0Ticks = 0; - timer0Reload = 0; - timer0ClockReload = 0; - timer1On = false; - timer1Ticks = 0; - timer1Reload = 0; - timer1ClockReload = 0; - timer2On = false; - timer2Ticks = 0; - timer2Reload = 0; - timer2ClockReload = 0; - timer3On = false; - timer3Ticks = 0; - timer3Reload = 0; - timer3ClockReload = 0; - dma0Source = 0; - dma0Dest = 0; - dma1Source = 0; - dma1Dest = 0; - dma2Source = 0; - dma2Dest = 0; - dma3Source = 0; - dma3Dest = 0; - renderLine = &Gigazoid::mode0RenderLine; - fxOn = false; - windowOn = false; - graphics.layerEnable = io_registers[REG_DISPCNT]; - - memset(line[0], -1, 240 * sizeof(u32)); - memset(line[1], -1, 240 * sizeof(u32)); - memset(line[2], -1, 240 * sizeof(u32)); - memset(line[3], -1, 240 * sizeof(u32)); - - for(int i = 0; i < 256; i++) { - map[i].address = 0; - map[i].mask = 0; - } - - map[0].address = bios; - map[0].mask = 0x3FFF; - map[2].address = workRAM; - map[2].mask = 0x3FFFF; - map[3].address = internalRAM; - map[3].mask = 0x7FFF; - map[4].address = ioMem; - map[4].mask = 0x3FF; - map[5].address = graphics.paletteRAM; - map[5].mask = 0x3FF; - map[6].address = vram; - map[6].mask = 0x1FFFF; - map[7].address = oam; - map[7].mask = 0x3FF; - map[8].address = rom; - map[8].mask = 0x1FFFFFF; - map[9].address = rom; - map[9].mask = 0x1FFFFFF; - map[10].address = rom; - map[10].mask = 0x1FFFFFF; - map[12].address = rom; - map[12].mask = 0x1FFFFFF; - map[14].address = flashSaveMemory; - map[14].mask = 0xFFFF; - - eepromReset(); - flashReset(); - - soundReset(); - - CPUUpdateWindow0(); - CPUUpdateWindow1(); - - // make sure registers are correctly initialized if not using BIOS - if(cpuIsMultiBoot) - BIOS_RegisterRamReset(0xfe); - else if(!useBios && !cpuIsMultiBoot) - BIOS_RegisterRamReset(0xff); - else if (skipBios) - BIOS_RegisterRamReset(0xff); // ?? - - ARM_PREFETCH; -} - -void CPUInterrupt(void) -{ - uint32_t PC = bus.reg[15].I; - bool savedState = armState; - - if(armMode != 0x12 ) - CPUSwitchMode(0x12, true, false); - - bus.reg[14].I = PC; - if(!savedState) - bus.reg[14].I += 2; - bus.reg[15].I = 0x18; - armState = true; - armIrqEnable = false; - - bus.armNextPC = bus.reg[15].I; - bus.reg[15].I += 4; - ARM_PREFETCH; - - // if(!holdState) - biosProtected[0] = 0x02; - biosProtected[1] = 0xc0; - biosProtected[2] = 0x5e; - biosProtected[3] = 0xe5; -} - -void CPULoop (void) -{ - bus.busPrefetchCount = 0; - int ticks = 300000; - int timerOverflow = 0; - // variable used by the CPU core - cpuTotalTicks = 0; - - cpuNextEvent = CPUUpdateTicks(); - if(cpuNextEvent > ticks) - cpuNextEvent = ticks; - - bool framedone = false; - - do - { - if(!holdState) - { - if(armState) - { - if (!armExecute()) - return; - } - else - { - if (!thumbExecute()) - return; - } - clockTicks = 0; - } - else - clockTicks = CPUUpdateTicks(); - - cpuTotalTicks += clockTicks; - - - if(cpuTotalTicks >= cpuNextEvent) { - int remainingTicks = cpuTotalTicks - cpuNextEvent; - - clockTicks = cpuNextEvent; - cpuTotalTicks = 0; - -updateLoop: - - if (IRQTicks) - { - IRQTicks -= clockTicks; - if (IRQTicks<0) - IRQTicks = 0; - } - - graphics.lcdTicks -= clockTicks; - - soundTicksUp += clockTicks; - - AdvanceRTC(clockTicks); - - if(graphics.lcdTicks <= 0) - { - if(io_registers[REG_DISPSTAT] & 1) - { // V-BLANK - // if in V-Blank mode, keep computing... - if(io_registers[REG_DISPSTAT] & 2) - { - graphics.lcdTicks += 1008; - io_registers[REG_VCOUNT] += 1; - UPDATE_REG(0x06, io_registers[REG_VCOUNT]); - io_registers[REG_DISPSTAT] &= 0xFFFD; - UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); - CPUCompareVCOUNT(); - } - else - { - graphics.lcdTicks += 224; - io_registers[REG_DISPSTAT] |= 2; - UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); - if(io_registers[REG_DISPSTAT] & 16) - { - io_registers[REG_IF] |= 2; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - if (scanlineCallback && scanlineCallbackLine == io_registers[REG_VCOUNT]) - scanlineCallback(); - } - - if(io_registers[REG_VCOUNT] >= 228) - { - //Reaching last line - io_registers[REG_DISPSTAT] &= 0xFFFC; - UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); - io_registers[REG_VCOUNT] = 0; - UPDATE_REG(0x06, io_registers[REG_VCOUNT]); - CPUCompareVCOUNT(); - } - } - else if(io_registers[REG_DISPSTAT] & 2) - { - // if in H-Blank, leave it and move to drawing mode - io_registers[REG_VCOUNT] += 1; - UPDATE_REG(0x06, io_registers[REG_VCOUNT]); - graphics.lcdTicks += 1008; - io_registers[REG_DISPSTAT] &= 0xFFFD; - if(io_registers[REG_VCOUNT] == 160) - { - // moved to start of emulated frame - //UpdateJoypad(); - - io_registers[REG_DISPSTAT] |= 1; - io_registers[REG_DISPSTAT] &= 0xFFFD; - UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); - if(io_registers[REG_DISPSTAT] & 0x0008) - { - io_registers[REG_IF] |= 1; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - CPUCheckDMA(1, 0x0f); - systemDrawScreen(); - - process_sound_tick_fn(); - framedone = true; - } - - UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); - CPUCompareVCOUNT(); - } - else - { - bool draw_objwin = (graphics.layerEnable & 0x9000) == 0x9000; - bool draw_sprites = graphics.layerEnable & 0x1000; - memset(line[4], -1, 240 * sizeof(u32)); // erase all sprites - - if(draw_sprites) - gfxDrawSprites(); - - if(render_line_all_enabled) - { - memset(line[5], -1, 240 * sizeof(u32)); // erase all OBJ Win - if(draw_objwin) - gfxDrawOBJWin(); - } - - (this->*renderLine)(); - - // entering H-Blank - io_registers[REG_DISPSTAT] |= 2; - UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); - graphics.lcdTicks += 224; - CPUCheckDMA(2, 0x0f); - if(io_registers[REG_DISPSTAT] & 16) - { - io_registers[REG_IF] |= 2; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - if (scanlineCallback && scanlineCallbackLine == io_registers[REG_VCOUNT]) - scanlineCallback(); - } - } - - // we shouldn't be doing sound in stop state, but we lose synchronization - // if sound is disabled, so in stop state, soundTick will just produce - // mute sound - - // moving this may have consequences; we'll see - //soundTicksUp += clockTicks; - - if(!stopState) { - if(timer0On) { - timer0Ticks -= clockTicks; - if(timer0Ticks <= 0) { - timer0Ticks += (0x10000 - timer0Reload) << timer0ClockReload; - timerOverflow |= 1; - soundTimerOverflow(0); - if(io_registers[REG_TM0CNT] & 0x40) { - io_registers[REG_IF] |= 0x08; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - } - io_registers[REG_TM0D] = 0xFFFF - (timer0Ticks >> timer0ClockReload); - UPDATE_REG(0x100, io_registers[REG_TM0D]); - } - - if(timer1On) { - if(io_registers[REG_TM1CNT] & 4) { - if(timerOverflow & 1) { - io_registers[REG_TM1D]++; - if(io_registers[REG_TM1D] == 0) { - io_registers[REG_TM1D] += timer1Reload; - timerOverflow |= 2; - soundTimerOverflow(1); - if(io_registers[REG_TM1CNT] & 0x40) { - io_registers[REG_IF] |= 0x10; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - } - UPDATE_REG(0x104, io_registers[REG_TM1D]); - } - } else { - timer1Ticks -= clockTicks; - if(timer1Ticks <= 0) { - timer1Ticks += (0x10000 - timer1Reload) << timer1ClockReload; - timerOverflow |= 2; - soundTimerOverflow(1); - if(io_registers[REG_TM1CNT] & 0x40) { - io_registers[REG_IF] |= 0x10; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - } - io_registers[REG_TM1D] = 0xFFFF - (timer1Ticks >> timer1ClockReload); - UPDATE_REG(0x104, io_registers[REG_TM1D]); - } - } - - if(timer2On) { - if(io_registers[REG_TM2CNT] & 4) { - if(timerOverflow & 2) { - io_registers[REG_TM2D]++; - if(io_registers[REG_TM2D] == 0) { - io_registers[REG_TM2D] += timer2Reload; - timerOverflow |= 4; - if(io_registers[REG_TM2CNT] & 0x40) { - io_registers[REG_IF] |= 0x20; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - } - UPDATE_REG(0x108, io_registers[REG_TM2D]); - } - } else { - timer2Ticks -= clockTicks; - if(timer2Ticks <= 0) { - timer2Ticks += (0x10000 - timer2Reload) << timer2ClockReload; - timerOverflow |= 4; - if(io_registers[REG_TM2CNT] & 0x40) { - io_registers[REG_IF] |= 0x20; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - } - io_registers[REG_TM2D] = 0xFFFF - (timer2Ticks >> timer2ClockReload); - UPDATE_REG(0x108, io_registers[REG_TM2D]); - } - } - - if(timer3On) { - if(io_registers[REG_TM3CNT] & 4) { - if(timerOverflow & 4) { - io_registers[REG_TM3D]++; - if(io_registers[REG_TM3D] == 0) { - io_registers[REG_TM3D] += timer3Reload; - if(io_registers[REG_TM3CNT] & 0x40) { - io_registers[REG_IF] |= 0x40; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - } - UPDATE_REG(0x10C, io_registers[REG_TM3D]); - } - } else { - timer3Ticks -= clockTicks; - if(timer3Ticks <= 0) { - timer3Ticks += (0x10000 - timer3Reload) << timer3ClockReload; - if(io_registers[REG_TM3CNT] & 0x40) { - io_registers[REG_IF] |= 0x40; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - } - io_registers[REG_TM3D] = 0xFFFF - (timer3Ticks >> timer3ClockReload); - UPDATE_REG(0x10C, io_registers[REG_TM3D]); - } - } - } - - timerOverflow = 0; - ticks -= clockTicks; - cpuNextEvent = CPUUpdateTicks(); - - if(cpuDmaTicksToUpdate > 0) - { - if(cpuDmaTicksToUpdate > cpuNextEvent) - clockTicks = cpuNextEvent; - else - clockTicks = cpuDmaTicksToUpdate; - cpuDmaTicksToUpdate -= clockTicks; - if(cpuDmaTicksToUpdate < 0) - cpuDmaTicksToUpdate = 0; - goto skipIRQ; - } - - if(io_registers[REG_IF] && (io_registers[REG_IME] & 1) && armIrqEnable) - { - int res = io_registers[REG_IF] & io_registers[REG_IE]; - if(stopState) - res &= 0x3080; - if(res) - { - if (intState) - { - if (!IRQTicks) - { - CPUInterrupt(); - intState = false; - holdState = false; - stopState = false; - } - } - else - { - if (!holdState) - { - intState = true; - IRQTicks=7; - if (cpuNextEvent> IRQTicks) - cpuNextEvent = IRQTicks; - } - else - { - CPUInterrupt(); - holdState = false; - stopState = false; - } - } - } - } - - skipIRQ: - - if(remainingTicks > 0) { - if(remainingTicks > cpuNextEvent) - clockTicks = cpuNextEvent; - else - clockTicks = remainingTicks; - remainingTicks -= clockTicks; - if(remainingTicks < 0) - remainingTicks = 0; - goto updateLoop; - } - - if (timerOnOffDelay) - { - // Apply Timer - if (timerOnOffDelay & 1) - { - timer0ClockReload = TIMER_TICKS[timer0Value & 3]; - if(!timer0On && (timer0Value & 0x80)) { - // reload the counter - io_registers[REG_TM0D] = timer0Reload; - timer0Ticks = (0x10000 - io_registers[REG_TM0D]) << timer0ClockReload; - UPDATE_REG(0x100, io_registers[REG_TM0D]); - } - timer0On = timer0Value & 0x80 ? true : false; - io_registers[REG_TM0CNT] = timer0Value & 0xC7; - UPDATE_REG(0x102, io_registers[REG_TM0CNT]); - } - if (timerOnOffDelay & 2) - { - timer1ClockReload = TIMER_TICKS[timer1Value & 3]; - if(!timer1On && (timer1Value & 0x80)) { - // reload the counter - io_registers[REG_TM1D] = timer1Reload; - timer1Ticks = (0x10000 - io_registers[REG_TM1D]) << timer1ClockReload; - UPDATE_REG(0x104, io_registers[REG_TM1D]); - } - timer1On = timer1Value & 0x80 ? true : false; - io_registers[REG_TM1CNT] = timer1Value & 0xC7; - UPDATE_REG(0x106, io_registers[REG_TM1CNT]); - } - if (timerOnOffDelay & 4) - { - timer2ClockReload = TIMER_TICKS[timer2Value & 3]; - if(!timer2On && (timer2Value & 0x80)) { - // reload the counter - io_registers[REG_TM2D] = timer2Reload; - timer2Ticks = (0x10000 - io_registers[REG_TM2D]) << timer2ClockReload; - UPDATE_REG(0x108, io_registers[REG_TM2D]); - } - timer2On = timer2Value & 0x80 ? true : false; - io_registers[REG_TM2CNT] = timer2Value & 0xC7; - UPDATE_REG(0x10A, io_registers[REG_TM2CNT]); - } - if (timerOnOffDelay & 8) - { - timer3ClockReload = TIMER_TICKS[timer3Value & 3]; - if(!timer3On && (timer3Value & 0x80)) { - // reload the counter - io_registers[REG_TM3D] = timer3Reload; - timer3Ticks = (0x10000 - io_registers[REG_TM3D]) << timer3ClockReload; - UPDATE_REG(0x10C, io_registers[REG_TM3D]); - } - timer3On = timer3Value & 0x80 ? true : false; - io_registers[REG_TM3CNT] = timer3Value & 0xC7; - UPDATE_REG(0x10E, io_registers[REG_TM3CNT]); - } - cpuNextEvent = CPUUpdateTicks(); - timerOnOffDelay = 0; - // End of Apply Timer - } - - if(cpuNextEvent > ticks) - cpuNextEvent = ticks; - - if(ticks <= 0 || framedone) - break; - - } - }while(1); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// END GBA.CPP -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void Gigazoid_Init() -{ - // one time constructor stuff - - flashState = FLASH_READ_ARRAY; - flashReadState = FLASH_READ_ARRAY; - flashSize = 0x10000; - flashDeviceID = 0x1b; - flashManufacturerID = 0x32; - flashBank = 0; - - eepromMode = EEPROM_IDLE; - - eepromInUse = false; - eepromSize = 512; - - // this is constant now - // soundSampleRate = 22050; - - soundEnableFlag = 0x3ff; /* emulator channels enabled*/ - - armState = true; - armIrqEnable = true; - armMode = 0x1f; - - renderLine = &Gigazoid::mode0RenderLine; - - #define ARRAYINIT(n) memcpy((n), (n##_init), sizeof(n)) - ARRAYINIT(memoryWait); - ARRAYINIT(memoryWaitSeq); - ARRAYINIT(memoryWait32); - ARRAYINIT(memoryWaitSeq32); - #undef ARRAYINIT -} - -u32 *systemVideoFrameDest; -u32 *systemVideoFramePalette; -s16 *systemAudioFrameDest; -int *systemAudioFrameSamp; -bool lagged; - -void (*scanlineCallback)(); -int scanlineCallbackLine; - -void (*fetchCallback)(u32 addr); -void (*writeCallback)(u32 addr); -void (*readCallback)(u32 addr); -void (*traceCallback)(u32 addr, u32 opcode); - -void (*padCallback)(); - -void systemDrawScreen (void) -{ - // upconvert 555->888 (TODO: BETTER) - for (int i = 0; i < 240 * 160; i++) - { - u32 input = pix[i]; - /* - u32 output = 0xff000000 | - input << 9 & 0xf80000 | - input << 6 & 0xf800 | - input << 3 & 0xf8; - */ - u32 output = systemVideoFramePalette[input]; - systemVideoFrameDest[i] = output; - } - systemVideoFrameDest = nullptr; - systemVideoFramePalette = nullptr; -} - -// called at regular intervals on sound clock -void systemOnWriteDataToSoundBuffer(int16_t * finalWave, int length) -{ - memcpy(systemAudioFrameDest, finalWave, length * 2); - systemAudioFrameDest = nullptr; - *systemAudioFrameSamp = length / 2; - systemAudioFrameSamp = nullptr; -} - -void UpdateJoypad() -{ - /* update joystick information */ - io_registers[REG_P1] = 0x03FF ^ (joy & 0x3FF); -#if 0 - if(cpuEEPROMSensorEnabled) - systemUpdateMotionSensor(); -#endif - UPDATE_REG(0x130, io_registers[REG_P1]); - io_registers[REG_P1CNT] = READ16LE(((uint16_t *)&ioMem[0x132])); - - // this seems wrong, but there are cases where the game - // can enter the stop state without requesting an IRQ from - // the joypad. - if((io_registers[REG_P1CNT] & 0x4000) || stopState) { - uint16_t p1 = (0x3FF ^ io_registers[REG_P1CNT]) & 0x3FF; - if(io_registers[REG_P1CNT] & 0x8000) { - if(p1 == (io_registers[REG_P1CNT] & 0x3FF)) { - io_registers[REG_IF] |= 0x1000; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - } else { - if(p1 & io_registers[REG_P1CNT]) { - io_registers[REG_IF] |= 0x1000; - UPDATE_REG(0x202, io_registers[REG_IF]); - } - } - } -} - -public: - -templatevoid SyncState(NewState *ns) -{ - NSS(flashSaveMemory); - NSS(flashState); - NSS(flashReadState); - NSS(flashSize); - NSS(flashDeviceID); - NSS(flashManufacturerID); - NSS(flashBank); - - NSS(eepromMode); - NSS(eepromByte); - NSS(eepromBits); - NSS(eepromAddress); - NSS(eepromData); - NSS(eepromBuffer); - NSS(eepromInUse); - NSS(eepromSize); - - NSS(rtcClockData); - NSS(rtcEnabled); - SSS(rtcInternalTime); - NSS(RTCTicks); - NSS(RTCUseRealTime); - - NSS(soundTicksUp); - NSS(soundEnableFlag); - SSS_HACKY(pcm[0], this); - SSS_HACKY(pcm[1], this); - SSS(pcm_synth); - - SSS(bufs_buffer[0]); - SSS(bufs_buffer[1]); - SSS(bufs_buffer[2]); - NSS(mixer_samples_read); - - SSS(gb_apu); - - NSS(cpuNextEvent); - NSS(holdState); - NSS(cpuPrefetch); - NSS(cpuTotalTicks); - NSS(memoryWait); - NSS(memoryWaitSeq); - NSS(memoryWait32); - NSS(memoryWaitSeq32); - NSS(biosProtected); - NSS(cpuBitsSet); - - NSS(N_FLAG); - NSS(C_FLAG); - NSS(Z_FLAG); - NSS(V_FLAG); - NSS(armState); - NSS(armIrqEnable); - NSS(armMode); - - NSS(io_registers); - - NSS(MOSAIC); - - NSS(BG2X_L); - NSS(BG2X_H); - NSS(BG2Y_L); - NSS(BG2Y_H); - NSS(BG3X_L); - NSS(BG3X_H); - NSS(BG3Y_L); - NSS(BG3Y_H); - NSS(BLDMOD); - NSS(COLEV); - NSS(COLY); - NSS(DM0SAD_L); - NSS(DM0SAD_H); - NSS(DM0DAD_L); - NSS(DM0DAD_H); - NSS(DM0CNT_L); - NSS(DM0CNT_H); - NSS(DM1SAD_L); - NSS(DM1SAD_H); - NSS(DM1DAD_L); - NSS(DM1DAD_H); - NSS(DM1CNT_L); - NSS(DM1CNT_H); - NSS(DM2SAD_L); - NSS(DM2SAD_H); - NSS(DM2DAD_L); - NSS(DM2DAD_H); - NSS(DM2CNT_L); - NSS(DM2CNT_H); - NSS(DM3SAD_L); - NSS(DM3SAD_H); - NSS(DM3DAD_L); - NSS(DM3DAD_H); - NSS(DM3CNT_L); - NSS(DM3CNT_H); - - NSS(timerOnOffDelay); - NSS(timer0Value); - NSS(dma0Source); - NSS(dma0Dest); - NSS(dma1Source); - NSS(dma1Dest); - NSS(dma2Source); - NSS(dma2Dest); - NSS(dma3Source); - NSS(dma3Dest); - - EBS(cpuSaveGameFunc, 0); - EVS(cpuSaveGameFunc, &Gigazoid::flashWrite, 1); - EVS(cpuSaveGameFunc, &Gigazoid::sramWrite, 2); - EVS(cpuSaveGameFunc, &Gigazoid::flashSaveDecide, 3); - EVS(cpuSaveGameFunc, &Gigazoid::dummyWrite, 4); - EES(cpuSaveGameFunc, nullptr); - - NSS(fxOn); - NSS(windowOn); - NSS(cpuDmaTicksToUpdate); - NSS(IRQTicks); - NSS(intState); - - NSS(bus); - NSS(graphics); - - // map; // values never change - - NSS(clockTicks); - - NSS(romSize); - NSS(line); - NSS(gfxInWin); - NSS(lineOBJpixleft); - NSS(joy); - - NSS(gfxBG2Changed); - NSS(gfxBG3Changed); - - NSS(gfxBG2X); - NSS(gfxBG2Y); - NSS(gfxBG3X); - NSS(gfxBG3Y); - - NSS(ioReadable); - - NSS(stopState); - - NSS(timer0On); - NSS(timer0Ticks); - NSS(timer0Reload); - NSS(timer0ClockReload); - NSS(timer1Value); - NSS(timer1On); - NSS(timer1Ticks); - NSS(timer1Reload); - NSS(timer1ClockReload); - NSS(timer2Value); - NSS(timer2On); - NSS(timer2Ticks); - NSS(timer2Reload); - NSS(timer2ClockReload); - NSS(timer3Value); - NSS(timer3On); - NSS(timer3Ticks); - NSS(timer3Reload); - NSS(timer3ClockReload); - - NSS(skipBios); - NSS(cpuSaveType); - NSS(mirroringEnable); - - NSS(cpuDmaCount); - - NSS(internalRAM); - NSS(workRAM); - NSS(vram); - NSS(pix); - NSS(oam); - NSS(ioMem); - - NSS(cpuEEPROMEnabled); - NSS(cpuEEPROMSensorEnabled); - - EBS(renderLine, 0); - EVS(renderLine, &Gigazoid::mode0RenderLine, 0x01); - EVS(renderLine, &Gigazoid::mode0RenderLineNoWindow, 0x02); - EVS(renderLine, &Gigazoid::mode0RenderLineAll, 0x03); - EVS(renderLine, &Gigazoid::mode1RenderLine, 0x11); - EVS(renderLine, &Gigazoid::mode1RenderLineNoWindow, 0x12); - EVS(renderLine, &Gigazoid::mode1RenderLineAll, 0x13); - EVS(renderLine, &Gigazoid::mode2RenderLine, 0x21); - EVS(renderLine, &Gigazoid::mode2RenderLineNoWindow, 0x22); - EVS(renderLine, &Gigazoid::mode2RenderLineAll, 0x23); - EVS(renderLine, &Gigazoid::mode3RenderLine, 0x31); - EVS(renderLine, &Gigazoid::mode3RenderLineNoWindow, 0x32); - EVS(renderLine, &Gigazoid::mode3RenderLineAll, 0x33); - EVS(renderLine, &Gigazoid::mode4RenderLine, 0x41); - EVS(renderLine, &Gigazoid::mode4RenderLineNoWindow, 0x42); - EVS(renderLine, &Gigazoid::mode4RenderLineAll, 0x43); - EVS(renderLine, &Gigazoid::mode5RenderLine, 0x51); - EVS(renderLine, &Gigazoid::mode5RenderLineNoWindow, 0x52); - EVS(renderLine, &Gigazoid::mode5RenderLineAll, 0x53); - EES(renderLine, nullptr); - - NSS(render_line_all_enabled); - - // address_lut; // values never change - - NSS(lagged); -} - -// load a legacy battery ram file to a place where it might work, who knows -void LoadLegacyBatteryRam(const char *data, int len) -{ - std::memcpy(eepromData, data, std::min(len, sizeof(eepromData))); - std::memcpy(flashSaveMemory, data, std::min(len, sizeof(flashSaveMemory))); - if (len <= 0x10000) - { - // can salvage broken pokeymans saves in some cases - std::memcpy(flashSaveMemory + 0x10000, data, std::min(len, 0x10000)); - } -} - -bool HasBatteryRam() -{ - return cpuSaveType != 5; -} - -int BatteryRamSize() -{ - switch (cpuSaveType) - { - default: - case 0: // auto - return 0x10000; - case 1: - case 4: // eeprom - return eepromSize; - case 2: // sram - // should only be 32K, but vba uses 64K as a stand-in for both SRAM (guess no game ever checks mirroring?), - // and for 64K flash where the program never issues any flash commands - return 0x10000; - case 3: // flash - return flashSize; - case 5: // none - return 0; - } -} - -void SaveLegacyBatteryRam(char *dest) -{ - switch (cpuSaveType) - { - default: - case 0: // auto - std::memcpy(dest, flashSaveMemory, 0x10000); - return; - case 1: - case 4: // eeprom - std::memcpy(dest, eepromData, eepromSize); - return; - case 2: // sram - // should only be 32K, but vba uses 64K as a stand-in for both SRAM (guess no game ever checks mirroring?), - // and for 64K flash where the program never issues any flash commands - std::memcpy(dest, flashSaveMemory, 0x10000); - return; - case 3: // flash - std::memcpy(dest, flashSaveMemory, flashSize); - return; - case 5: // none - return; - } -} - -templatebool SyncBatteryRam(NewState *ns) -{ - // if we were given a positive ID from the gamedb, we can choose to save/load only that type - // else, we save\load everything -- even if we used our knowledge of the current state to - // save only what was needed, we'd have to save that metadata as well for load - - // file id detection - char batteryramid[8]; - std::memcpy(batteryramid, "GBABATT\0", 8); - NSS(batteryramid); - if (std::memcmp(batteryramid, "GBABATT\0", 8) != 0) - return false; - - int flashFileSize; - int eepromFileSize; - - // when writing, try to figure out the sizes as smartly as we can - switch (cpuSaveType) - { - default: - case 0: // auto - flashFileSize = 0x20000; - eepromFileSize = 0x2000; - break; - case 1: - case 4: // eeprom - flashFileSize = 0; - eepromFileSize = eepromSize; - break; - case 2: // sram - // should only be 32K, but vba uses 64K as a stand-in for both SRAM (guess no game ever checks mirroring?), - // and for 64K flash where the program never issues any flash commands - flashFileSize = 0x10000; - eepromFileSize = 0; - break; - case 3: // flash - flashFileSize = flashSize; - eepromFileSize = 0; - break; - case 5: // none - flashFileSize = 0; - eepromFileSize = 0; - break; - } - NSS(flashFileSize); - NSS(eepromFileSize); - // when reading, cap to allowable limits. any save file with numbers larger than this is not legal. - flashFileSize = std::min(flashFileSize, sizeof(flashSaveMemory)); - eepromFileSize = std::min(eepromFileSize, sizeof(eepromData)); - - PSS(flashSaveMemory, flashFileSize); - PSS(eepromData, eepromFileSize); - - return true; -} - - Gigazoid() - { - Gigazoid_Init(); - } - - ~Gigazoid() - { - } - - bool LoadRom(const u8 *romfile, const u32 romfilelen, const u8 *biosfile, const u32 biosfilelen, const FrontEndSettings &settings) - { - if (biosfilelen != 16384) - return false; - - if (!CPULoadRom(romfile, romfilelen)) - return false; - - cpuSaveType = settings.cpuSaveType; - flashSize = settings.flashSize; - rtcEnabled = settings.enableRtc; - mirroringEnable = settings.mirroringEnable; - skipBios = settings.skipBios; - - RTCUseRealTime = settings.RTCuseRealTime; - rtcInternalTime.hour = settings.RTChour; - rtcInternalTime.mday = settings.RTCmday; - rtcInternalTime.min = settings.RTCmin; - rtcInternalTime.month = settings.RTCmonth; - rtcInternalTime.sec = settings.RTCsec; - rtcInternalTime.wday = settings.RTCwday; - rtcInternalTime.year = settings.RTCyear; - - if(flashSize == 0x10000) - { - flashDeviceID = 0x1b; - flashManufacturerID = 0x32; - } - else - { - flashDeviceID = 0x13; //0x09; - flashManufacturerID = 0x62; //0xc2; - } - - doMirroring(mirroringEnable); - - CPUInit(biosfile, biosfilelen); - CPUReset(); - - // CPUReset already calls this, but if that were to change - // soundReset(); - - return true; - } - - void Reset() - { - CPUReset(); - } - - bool FrameAdvance(int input, u32 *videobuffer, s16 *audiobuffer, int *numsamp, u32 *videopalette) - { - joy = input; - systemVideoFrameDest = videobuffer; - systemVideoFramePalette = videopalette; - systemAudioFrameDest = audiobuffer; - systemAudioFrameSamp = numsamp; - lagged = true; - UpdateJoypad(); - do - { - CPULoop(); - } while (systemVideoFrameDest); - return lagged; - } - - void FillMemoryAreas(MemoryAreas &mem) - { - mem.bios = bios; - mem.iwram = internalRAM; - mem.ewram = workRAM; - mem.palram = graphics.paletteRAM; - mem.mmio = ioMem; - mem.rom = rom; - mem.vram = vram; - mem.oam = oam; - switch (cpuSaveType) - { - default: - case 0: // auto - mem.sram = flashSaveMemory; - mem.sram_size = 0x10000;; - return; - case 1: - case 4: // eeprom - mem.sram = eepromData; - mem.sram_size = eepromSize; - return; - case 2: // sram - mem.sram = flashSaveMemory; - mem.sram_size = 0x10000; - return; - case 3: // flash - mem.sram = flashSaveMemory; - mem.sram_size = flashSize; - return; - case 5: // none - return; - } - } - - void BusWrite(u32 addr, u8 val) - { - CPUWriteByte(addr, val); - } - u8 BusRead(u32 addr) - { - return CPUReadByte(addr); - } - - void SetScanlineCallback(void (*cb)(), int scanline) - { - // the sequence of calls in a frame will be: - // 160,161,...,227,0,1,...,160 - // calls coincide with entering hblank, or something like that - if (scanline < 0 || scanline > 227) - cb = nullptr; - scanlineCallback = cb; - scanlineCallbackLine = scanline; - } - - uint32_t *GetRegisters() - { - return &bus.reg[0].I; - } - - void SetPadCallback(void (*cb)()) - { - // before each read of the pad regs - padCallback = cb; - } - - void SetFetchCallback(void (*cb)(u32 addr)) - { - // before each opcode fetch - fetchCallback = cb; - } - - void SetReadCallback(void (*cb)(u32 addr)) - { - // before each read, not including opcodes, including pad regs - readCallback = cb; - } - - void SetWriteCallback(void (*cb)(u32 addr)) - { - // before each write - writeCallback = cb; - } - - void SetTraceCallback(void (*cb)(u32 addr, u32 opcode)) - { - // before each opcode fetch - traceCallback = cb; - } - -}; // class Gigazoid - -// zeroing mem operators: these are very important -void *operator new(std::size_t n) -{ - void *p = std::malloc(n); - std::memset(p, 0, n); - return p; -} -void operator delete(void *p) -{ - std::free(p); -} - -#ifdef _WIN32 -#define EXPORT extern "C" __declspec(dllexport) -#elif __linux__ -#define EXPORT extern "C" -#endif - -// public interface follows -EXPORT Gigazoid *Create() -{ - return new Gigazoid(); -} - -EXPORT void Destroy(Gigazoid *g) -{ - delete g; -} - -EXPORT int LoadRom(Gigazoid *g, const u8 *romfile, const u32 romfilelen, const u8 *biosfile, const u32 biosfilelen, const FrontEndSettings *settings) -{ - return g->LoadRom(romfile, romfilelen, biosfile, biosfilelen, *settings); -} - -EXPORT void Reset(Gigazoid *g) -{ - // TODO: this calls a soundreset that seems to remake some buffers. that seems like it should be fixed? - g->Reset(); -} - -EXPORT int FrameAdvance(Gigazoid *g, int input, u32 *videobuffer, s16 *audiobuffer, int *numsamp, u32 *videopalette) -{ - return g->FrameAdvance(input, videobuffer, audiobuffer, numsamp, videopalette); -} - -EXPORT int SaveRamSize(Gigazoid *g) -{ - /* - if (g->HasBatteryRam()) - { - NewStateDummy dummy; - g->SyncBatteryRam(&dummy); - return dummy.GetLength(); - } - else - { - return 0; - }*/ - return g->BatteryRamSize(); -} - -EXPORT int SaveRamSave(Gigazoid *g, char *data, int length) -{ - /* - if (g->HasBatteryRam()) - { - NewStateExternalBuffer saver(data, length); - g->SyncBatteryRam(&saver); - return !saver.Overflow() && saver.GetLength() == length; - } - else - { - return false; - }*/ - if (!g->HasBatteryRam() || length != g->BatteryRamSize()) - return false; - g->SaveLegacyBatteryRam(data); - return true; -} - -EXPORT int SaveRamLoad(Gigazoid *g, const char *data, int length) -{ - if (g->HasBatteryRam()) - { - NewStateExternalBuffer loader(const_cast(data), length); - if (g->SyncBatteryRam(&loader)) - { - return !loader.Overflow() && loader.GetLength() == length; - } - else - { - // couldn't find the magic signature at the top, so try a salvage load - g->LoadLegacyBatteryRam(data, length); - return true; - } - } - else - { - return false; - } -} - -EXPORT int BinStateSize(Gigazoid *g) -{ - NewStateDummy dummy; - g->SyncState(&dummy); - return dummy.GetLength(); -} - -EXPORT int BinStateSave(Gigazoid *g, char *data, int length) -{ - NewStateExternalBuffer saver(data, length); - g->SyncState(&saver); - return !saver.Overflow() && saver.GetLength() == length; -} - -EXPORT int BinStateLoad(Gigazoid *g, const char *data, int length) -{ - NewStateExternalBuffer loader(const_cast(data), length); - g->SyncState(&loader); - return !loader.Overflow() && loader.GetLength() == length; -} - -EXPORT void TxtStateSave(Gigazoid *g, FPtrs *ff) -{ - NewStateExternalFunctions saver(ff); - g->SyncState(&saver); -} - -EXPORT void TxtStateLoad(Gigazoid *g, FPtrs *ff) -{ - NewStateExternalFunctions loader(ff); - g->SyncState(&loader); -} - -EXPORT void GetMemoryAreas(Gigazoid *g, MemoryAreas *mem) -{ - g->FillMemoryAreas(*mem); -} - -EXPORT void SystemBusWrite(Gigazoid *g, u32 addr, u8 val) -{ - g->BusWrite(addr, val); -} - -EXPORT u8 SystemBusRead(Gigazoid *g, u32 addr) -{ - return g->BusRead(addr); -} - -EXPORT void SetScanlineCallback(Gigazoid *g, void (*cb)(), int scanline) -{ - g->SetScanlineCallback(cb, scanline); -} - -EXPORT void SetTraceCallback(Gigazoid *g, void (*cb)(u32 addr, u32 opcode)) -{ - g->SetTraceCallback(cb); -} - -EXPORT u32 *GetRegisters(Gigazoid *g) -{ - return g->GetRegisters(); -} - -EXPORT void SetPadCallback(Gigazoid *g, void (*cb)()) { g->SetPadCallback(cb); } -EXPORT void SetFetchCallback(Gigazoid *g, void (*cb)(u32 addr)) { g->SetFetchCallback(cb); } -EXPORT void SetReadCallback(Gigazoid *g, void (*cb)(u32 addr)) { g->SetReadCallback(cb); } -EXPORT void SetWriteCallback(Gigazoid *g, void (*cb)(u32 addr)) { g->SetWriteCallback(cb); } - - -#include "optable.inc" diff --git a/vbanext/instance.h b/vbanext/instance.h deleted file mode 100644 index 3139a854ba..0000000000 --- a/vbanext/instance.h +++ /dev/null @@ -1,227 +0,0 @@ -#ifndef INSTANCE_H -#define INSTANCE_H - -struct FrontEndSettings -{ - int cpuSaveType; // [0auto] 1eeprom 2sram 3flash 4eeprom+sensor 5none - int flashSize; // [0x10000] 0x20000 - int enableRtc; // [false] true - int mirroringEnable; // [false] true - int skipBios; // [false] true - - int RTCuseRealTime; - int RTCyear; // 00..99 - int RTCmonth; // 00..11 - int RTCmday; // 01..31 - int RTCwday; // 00..06 - int RTChour; // 00..23 - int RTCmin; // 00..59 - int RTCsec; // 00..59 - -}; - -struct MemoryAreas -{ - void *bios; - void *iwram; - void *ewram; - void *palram; - void *vram; - void *oam; - void *rom; - void *mmio; - void *sram; - uint32_t sram_size; -}; - -#define FLASH_128K_SZ 0x20000 - -#define EEPROM_IDLE 0 -#define EEPROM_READADDRESS 1 -#define EEPROM_READDATA 2 -#define EEPROM_READDATA2 3 -#define EEPROM_WRITEDATA 4 - -enum { - IMAGE_UNKNOWN, - IMAGE_GBA -}; - -#define SGCNT0_H 0x82 -#define FIFOA_L 0xa0 -#define FIFOA_H 0xa2 -#define FIFOB_L 0xa4 -#define FIFOB_H 0xa6 - -#define BLIP_BUFFER_ACCURACY 16 -#define BLIP_PHASE_BITS 8 -#define BLIP_WIDEST_IMPULSE_ 16 -#define BLIP_BUFFER_EXTRA_ 18 -#define BLIP_RES 256 -#define BLIP_RES_MIN_ONE 255 -#define BLIP_SAMPLE_BITS 30 -#define BLIP_READER_DEFAULT_BASS 9 -#define BLIP_DEFAULT_LENGTH 250 /* 1/4th of a second */ - -#define BUFS_SIZE 3 -#define STEREO 2 - -#define CLK_MUL GB_APU_OVERCLOCK -#define CLK_MUL_MUL_2 8 -#define CLK_MUL_MUL_4 16 -#define CLK_MUL_MUL_6 24 -#define CLK_MUL_MUL_8 32 -#define CLK_MUL_MUL_15 60 -#define CLK_MUL_MUL_32 128 -#define DAC_BIAS 7 - -#define PERIOD_MASK 0x70 -#define SHIFT_MASK 0x07 - -#define PERIOD2_MASK 0x1FFFF - -#define BANK40_MASK 0x40 -#define BANK_SIZE 32 -#define BANK_SIZE_MIN_ONE 31 -#define BANK_SIZE_DIV_TWO 16 - -/* 11-bit frequency in NRx3 and NRx4*/ -#define GB_OSC_FREQUENCY() (((regs[4] & 7) << 8) + regs[3]) - -#define WAVE_TYPE 0x100 -#define NOISE_TYPE 0x200 -#define MIXED_TYPE WAVE_TYPE | NOISE_TYPE -#define TYPE_INDEX_MASK 0xFF - -#define BITS_16 0 -#define BITS_32 1 - -#define R13_IRQ 18 -#define R14_IRQ 19 -#define SPSR_IRQ 20 -#define R13_USR 26 -#define R14_USR 27 -#define R13_SVC 28 -#define R14_SVC 29 -#define SPSR_SVC 30 -#define R13_ABT 31 -#define R14_ABT 32 -#define SPSR_ABT 33 -#define R13_UND 34 -#define R14_UND 35 -#define SPSR_UND 36 -#define R8_FIQ 37 -#define R9_FIQ 38 -#define R10_FIQ 39 -#define R11_FIQ 40 -#define R12_FIQ 41 -#define R13_FIQ 42 -#define R14_FIQ 43 -#define SPSR_FIQ 44 - -typedef struct { - uint8_t *address; - uint32_t mask; -} memoryMap; - -typedef union { - struct { -#ifdef LSB_FIRST - uint8_t B0; - uint8_t B1; - uint8_t B2; - uint8_t B3; -#else - uint8_t B3; - uint8_t B2; - uint8_t B1; - uint8_t B0; -#endif - } B; - struct { -#ifdef LSB_FIRST - uint16_t W0; - uint16_t W1; -#else - uint16_t W1; - uint16_t W0; -#endif - } W; -#ifdef LSB_FIRST - uint32_t I; -#else - volatile uint32_t I; -#endif -} reg_pair; - -typedef struct -{ - reg_pair reg[45]; - bool busPrefetch; - bool busPrefetchEnable; - uint32_t busPrefetchCount; - uint32_t armNextPC; -} bus_t; - -typedef struct -{ - uint8_t paletteRAM[0x400]; - int layerEnable; - int layerEnableDelay; - int lcdTicks; -} graphics_t; - -/* Begins reading from buffer. Name should be unique to the current block.*/ -#define BLIP_READER_BEGIN( name, blip_buffer ) \ - const int32_t * name##_reader_buf = (blip_buffer).buffer_;\ - int32_t name##_reader_accum = (blip_buffer).reader_accum_ - -/* Advances to next sample*/ -#define BLIP_READER_NEXT( name, bass ) \ - (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass))) - -/* Ends reading samples from buffer. The number of samples read must now be removed - using Blip_Buffer::remove_samples(). */ -#define BLIP_READER_END( name, blip_buffer ) \ - (void) ((blip_buffer).reader_accum_ = name##_reader_accum) - -#define BLIP_READER_ADJ_( name, offset ) (name##_reader_buf += offset) - -#define BLIP_READER_NEXT_IDX_( name, idx ) {\ - name##_reader_accum -= name##_reader_accum >> BLIP_READER_DEFAULT_BASS;\ - name##_reader_accum += name##_reader_buf [(idx)];\ -} - -#define BLIP_READER_NEXT_RAW_IDX_( name, idx ) {\ - name##_reader_accum -= name##_reader_accum >> BLIP_READER_DEFAULT_BASS; \ - name##_reader_accum += *(int32_t const*) ((char const*) name##_reader_buf + (idx)); \ -} - -#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ - defined (__x86_64__) || defined (__ia64__) || defined (__i386__) - #define BLIP_CLAMP_( in ) in < -0x8000 || 0x7FFF < in -#else - #define BLIP_CLAMP_( in ) (int16_t) in != in -#endif - -/* Clamp sample to int16_t range */ -#define BLIP_CLAMP( sample, out ) { if ( BLIP_CLAMP_( (sample) ) ) (out) = ((sample) >> 24) ^ 0x7FFF; } -#define GB_ENV_DAC_ENABLED() (regs[2] & 0xF8) /* Non-zero if DAC is enabled*/ -#define GB_NOISE_PERIOD2_INDEX() (regs[3] >> 4) -#define GB_NOISE_PERIOD2(base) (base << GB_NOISE_PERIOD2_INDEX()) -#define GB_NOISE_LFSR_MASK() ((regs[3] & 0x08) ? ~0x4040 : ~0x4000) -#define GB_WAVE_DAC_ENABLED() (regs[0] & 0x80) /* Non-zero if DAC is enabled*/ - -#define reload_sweep_timer() \ - sweep_delay = (regs [0] & PERIOD_MASK) >> 4; \ - if ( !sweep_delay ) \ - sweep_delay = 8; - - -#ifdef __LIBRETRO__ -#define PIX_BUFFER_SCREEN_WIDTH 256 -#else -#define PIX_BUFFER_SCREEN_WIDTH 240 -#endif - -#endif diff --git a/vbanext/mingw/Makefile b/vbanext/mingw/Makefile deleted file mode 100644 index 05f14773d1..0000000000 --- a/vbanext/mingw/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -CXX = g++ -CXXFLAGS = -Wall -O3 -fpermissive -Wno-unused-but-set-variable \ - -Wno-strict-aliasing -Wzero-as-null-pointer-constant -Wno-unused-variable \ - -Wno-parentheses -Wno-sign-compare -std=gnu++11 -fomit-frame-pointer -fno-exceptions -fPIC - -MACHINE = $(shell $(CXX) -dumpmachine) -ifneq (,$(findstring i686,$(MACHINE))) - $(error 32 bit build no longer supported) -else ifneq (,$(findstring x86_64,$(MACHINE))) - ARCH = 64 -else - $(error Unknown arch) -endif - -LDFLAGS_32 = -static-libgcc -static-libstdc++ -LDFLAGS_64 = -LDFLAGS = -shared $(LDFLAGS_$(ARCH)) $(CXXFLAGS) - -TARGET = libvbanext.dll -RM = rm -CP = cp - -SRCS = \ - ../instance.cpp \ - ../newstate.cpp - -OBJS = $(SRCS:.cpp=.o) -DEST_32 = ../../output/dll -DEST_64 = ../../output/dll - -all: $(TARGET) - -%.o: %.cpp - $(CXX) -c -o $@ $< $(CXXFLAGS) - -$(TARGET) : $(OBJS) - $(CXX) -o $@ $(LDFLAGS) $(OBJS) - -clean: - $(RM) $(OBJS) - $(RM) $(TARGET) - -install: - $(CP) $(TARGET) $(DEST_$(ARCH)) diff --git a/vbanext/msvs/libvbanext/libvbanext.sln b/vbanext/msvs/libvbanext/libvbanext.sln deleted file mode 100644 index 3b47db7b92..0000000000 --- a/vbanext/msvs/libvbanext/libvbanext.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libvbanext", "libvbanext.vcxproj", "{DE666222-17A4-4B1E-8A5A-0A69838AE23F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DE666222-17A4-4B1E-8A5A-0A69838AE23F}.Debug|Win32.ActiveCfg = Debug|Win32 - {DE666222-17A4-4B1E-8A5A-0A69838AE23F}.Debug|Win32.Build.0 = Debug|Win32 - {DE666222-17A4-4B1E-8A5A-0A69838AE23F}.Release|Win32.ActiveCfg = Release|Win32 - {DE666222-17A4-4B1E-8A5A-0A69838AE23F}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/vbanext/msvs/libvbanext/libvbanext.vcxproj b/vbanext/msvs/libvbanext/libvbanext.vcxproj deleted file mode 100644 index c2e55b1d9c..0000000000 --- a/vbanext/msvs/libvbanext/libvbanext.vcxproj +++ /dev/null @@ -1,90 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {DE666222-17A4-4B1E-8A5A-0A69838AE23F} - libvbanext - - - - DynamicLibrary - true - MultiByte - - - DynamicLibrary - false - true - MultiByte - - - - - - - - - - - - - - - Level3 - Disabled - 4146;4800 - - - true - - - copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\..\..\output\dll\$(TargetFileName) - - - - - Level3 - Full - true - true - 4146;4800 - AnySuitable - true - - - true - true - true - - - copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\..\..\output\dll\$(TargetFileName) - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vbanext/msvs/libvbanext/libvbanext.vcxproj.filters b/vbanext/msvs/libvbanext/libvbanext.vcxproj.filters deleted file mode 100644 index 17408fd5f3..0000000000 --- a/vbanext/msvs/libvbanext/libvbanext.vcxproj.filters +++ /dev/null @@ -1,53 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {25bb448a-4359-4425-bc82-a36c2dcddcb8} - - - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Header Files - - - \ No newline at end of file diff --git a/vbanext/newstate.cpp b/vbanext/newstate.cpp deleted file mode 100644 index 1b356e3a86..0000000000 --- a/vbanext/newstate.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "newstate.h" -#include - -NewStateDummy::NewStateDummy() - :length(0) -{ -} -void NewStateDummy::Save(const void *ptr, size_t size, const char *name) -{ - length += size; -} -void NewStateDummy::Load(void *ptr, size_t size, const char *name) -{ -} - -NewStateExternalBuffer::NewStateExternalBuffer(char *buffer, long maxlength) - :buffer(buffer), length(0), maxlength(maxlength) -{ -} - -void NewStateExternalBuffer::Save(const void *ptr, size_t size, const char *name) -{ - if (maxlength - length >= (long)size) - { - std::memcpy(buffer + length, ptr, size); - } - length += size; -} - -void NewStateExternalBuffer::Load(void *ptr, size_t size, const char *name) -{ - char *dst = static_cast(ptr); - if (maxlength - length >= (long)size) - { - std::memcpy(dst, buffer + length, size); - } - length += size; -} - -NewStateExternalFunctions::NewStateExternalFunctions(const FPtrs *ff) - :Save_(ff->Save_), - Load_(ff->Load_), - EnterSection_(ff->EnterSection_), - ExitSection_(ff->ExitSection_) -{ -} - -void NewStateExternalFunctions::Save(const void *ptr, size_t size, const char *name) -{ - Save_(ptr, size, name); -} -void NewStateExternalFunctions::Load(void *ptr, size_t size, const char *name) -{ - Load_(ptr, size, name); -} -void NewStateExternalFunctions::EnterSection(const char *name) -{ - EnterSection_(name); -} -void NewStateExternalFunctions::ExitSection(const char *name) -{ - ExitSection_(name); -} - diff --git a/vbanext/newstate.h b/vbanext/newstate.h deleted file mode 100644 index 2f0f75f8ef..0000000000 --- a/vbanext/newstate.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef NEWSTATE_H -#define NEWSTATE_H - -#include -#include - -class NewState -{ -public: - virtual void Save(const void *ptr, size_t size, const char *name) = 0; - virtual void Load(void *ptr, size_t size, const char *name) = 0; - virtual void EnterSection(const char *name) { } - virtual void ExitSection(const char *name) { } -}; - -class NewStateDummy : public NewState -{ -private: - long length; -public: - NewStateDummy(); - long GetLength() { return length; } - void Rewind() { length = 0; } - virtual void Save(const void *ptr, size_t size, const char *name); - virtual void Load(void *ptr, size_t size, const char *name); -}; - -class NewStateExternalBuffer : public NewState -{ -private: - char *const buffer; - long length; - const long maxlength; -public: - NewStateExternalBuffer(char *buffer, long maxlength); - long GetLength() { return length; } - void Rewind() { length = 0; } - bool Overflow() { return length > maxlength; } - virtual void Save(const void *ptr, size_t size, const char *name); - virtual void Load(void *ptr, size_t size, const char *name); -}; - -struct FPtrs -{ - void (*Save_)(const void *ptr, size_t size, const char *name); - void (*Load_)(void *ptr, size_t size, const char *name); - void (*EnterSection_)(const char *name); - void (*ExitSection_)(const char *name); -}; - -class NewStateExternalFunctions : public NewState -{ -private: - void (*Save_)(const void *ptr, size_t size, const char *name); - void (*Load_)(void *ptr, size_t size, const char *name); - void (*EnterSection_)(const char *name); - void (*ExitSection_)(const char *name); -public: - NewStateExternalFunctions(const FPtrs *ff); - virtual void Save(const void *ptr, size_t size, const char *name); - virtual void Load(void *ptr, size_t size, const char *name); - virtual void EnterSection(const char *name); - virtual void ExitSection(const char *name); -}; - -// defines and explicitly instantiates -#define SYNCFUNC(x)\ - template void x::SyncState(NewState *ns);\ - template void x::SyncState(NewState *ns);\ - templatevoid x::SyncState(NewState *ns) - -// N = normal variable -// P = pointer to fixed size data -// S = "sub object" -// T = "ptr to sub object" -// R = pointer, store its offset from some other pointer -// E = general purpose cased value "enum" - - -// first line is default value in converted enum; last line is default value in argument x -#define EBS(x,d) do { int _ttmp = (d); if (isReader) ns->Load(&_ttmp, sizeof(_ttmp), #x); if (0) -#define EVS(x,v,n) else if (!isReader && (x) == (v)) _ttmp = (n); else if (isReader && _ttmp == (n)) (x) = (v) -#define EES(x,d) else if (isReader) (x) = (d); if (!isReader) ns->Save(&_ttmp, sizeof(_ttmp), #x); } while (0) - -#define RSS(x,b) do { if (isReader)\ -{ ptrdiff_t _ttmp; ns->Load(&_ttmp, sizeof(_ttmp), #x); (x) = (_ttmp == (ptrdiff_t)0xdeadbeef ? 0 : (b) + _ttmp); }\ - else\ -{ ptrdiff_t _ttmp = (x) == 0 ? 0xdeadbeef : (x) - (b); ns->Save(&_ttmp, sizeof(_ttmp), #x); } } while (0) - -#define PSS(x,s) do { if (isReader) ns->Load((x), (s), #x); else ns->Save((x), (s), #x); } while (0) - -#define NSS(x) do { if (isReader) ns->Load(&(x), sizeof(x), #x); else ns->Save(&(x), sizeof(x), #x); } while (0) - -#define SSS(x) do { ns->EnterSection(#x); (x).SyncState(ns); ns->ExitSection(#x); } while (0) -#define SSS_HACKY(x,extra) do { ns->EnterSection(#x); (x).SyncState(ns, extra); ns->ExitSection(#x); } while (0) - -#define TSS(x) do { ns->EnterSection(#x); (x)->SyncState(ns); ns->ExitSection(#x); } while (0) - -#endif diff --git a/vbanext/optable.inc b/vbanext/optable.inc deleted file mode 100644 index d0cbc9eb00..0000000000 --- a/vbanext/optable.inc +++ /dev/null @@ -1,327 +0,0 @@ -#define F(fcn) &Gigazoid::fcn - -#define REP16(insn) \ - F(insn),F(insn),F(insn),F(insn),F(insn),F(insn),F(insn),F(insn),\ - F(insn),F(insn),F(insn),F(insn),F(insn),F(insn),F(insn),F(insn) -#define REP256(insn) \ - REP16(insn),REP16(insn),REP16(insn),REP16(insn),\ - REP16(insn),REP16(insn),REP16(insn),REP16(insn),\ - REP16(insn),REP16(insn),REP16(insn),REP16(insn),\ - REP16(insn),REP16(insn),REP16(insn),REP16(insn) - -#define arm_UI armUnknownInsn -#define arm_BP armUnknownInsn - -#define thumbUI thumbUnknownInsn -#define thumbBP thumbUnknownInsn - -void (Gigazoid::*const Gigazoid::armInsnTable[4096])(u32 opcode) = { - F(arm000),F(arm001),F(arm002),F(arm003),F(arm004),F(arm005),F(arm006),F(arm007), // F(000) - F(arm000),F(arm009),F(arm002),F(arm00B),F(arm004),F(arm_UI),F(arm006),F(arm_UI), // F(008) - F(arm010),F(arm011),F(arm012),F(arm013),F(arm014),F(arm015),F(arm016),F(arm017), // F(010) - F(arm010),F(arm019),F(arm012),F(arm01B),F(arm014),F(arm01D),F(arm016),F(arm01F), // F(018) - F(arm020),F(arm021),F(arm022),F(arm023),F(arm024),F(arm025),F(arm026),F(arm027), // F(020) - F(arm020),F(arm029),F(arm022),F(arm_UI),F(arm024),F(arm_UI),F(arm026),F(arm_UI), // F(028) - F(arm030),F(arm031),F(arm032),F(arm033),F(arm034),F(arm035),F(arm036),F(arm037), // F(030) - F(arm030),F(arm039),F(arm032),F(arm_UI),F(arm034),F(arm01D),F(arm036),F(arm01F), // F(038) - F(arm040),F(arm041),F(arm042),F(arm043),F(arm044),F(arm045),F(arm046),F(arm047), // F(040) - F(arm040),F(arm_UI),F(arm042),F(arm04B),F(arm044),F(arm_UI),F(arm046),F(arm_UI), // F(048) - F(arm050),F(arm051),F(arm052),F(arm053),F(arm054),F(arm055),F(arm056),F(arm057), // F(050) - F(arm050),F(arm_UI),F(arm052),F(arm05B),F(arm054),F(arm05D),F(arm056),F(arm05F), // F(058) - F(arm060),F(arm061),F(arm062),F(arm063),F(arm064),F(arm065),F(arm066),F(arm067), // F(060) - F(arm060),F(arm_UI),F(arm062),F(arm_UI),F(arm064),F(arm_UI),F(arm066),F(arm_UI), // F(068) - F(arm070),F(arm071),F(arm072),F(arm073),F(arm074),F(arm075),F(arm076),F(arm077), // F(070) - F(arm070),F(arm_UI),F(arm072),F(arm_UI),F(arm074),F(arm05D),F(arm076),F(arm05F), // F(078) - F(arm080),F(arm081),F(arm082),F(arm083),F(arm084),F(arm085),F(arm086),F(arm087), // F(080) - F(arm080),F(arm089),F(arm082),F(arm08B),F(arm084),F(arm_UI),F(arm086),F(arm_UI), // F(088) - F(arm090),F(arm091),F(arm092),F(arm093),F(arm094),F(arm095),F(arm096),F(arm097), // F(090) - F(arm090),F(arm099),F(arm092),F(arm09B),F(arm094),F(arm09D),F(arm096),F(arm09F), // F(098) - F(arm0A0),F(arm0A1),F(arm0A2),F(arm0A3),F(arm0A4),F(arm0A5),F(arm0A6),F(arm0A7), // F(0A0) - F(arm0A0),F(arm0A9),F(arm0A2),F(arm_UI),F(arm0A4),F(arm_UI),F(arm0A6),F(arm_UI), // F(0A8) - F(arm0B0),F(arm0B1),F(arm0B2),F(arm0B3),F(arm0B4),F(arm0B5),F(arm0B6),F(arm0B7), // F(0B0) - F(arm0B0),F(arm0B9),F(arm0B2),F(arm_UI),F(arm0B4),F(arm09D),F(arm0B6),F(arm09F), // F(0B8) - F(arm0C0),F(arm0C1),F(arm0C2),F(arm0C3),F(arm0C4),F(arm0C5),F(arm0C6),F(arm0C7), // F(0C0) - F(arm0C0),F(arm0C9),F(arm0C2),F(arm0CB),F(arm0C4),F(arm_UI),F(arm0C6),F(arm_UI), // F(0C8) - F(arm0D0),F(arm0D1),F(arm0D2),F(arm0D3),F(arm0D4),F(arm0D5),F(arm0D6),F(arm0D7), // F(0D0) - F(arm0D0),F(arm0D9),F(arm0D2),F(arm0DB),F(arm0D4),F(arm0DD),F(arm0D6),F(arm0DF), // F(0D8) - F(arm0E0),F(arm0E1),F(arm0E2),F(arm0E3),F(arm0E4),F(arm0E5),F(arm0E6),F(arm0E7), // F(0E0) - F(arm0E0),F(arm0E9),F(arm0E2),F(arm_UI),F(arm0E4),F(arm_UI),F(arm0E6),F(arm_UI), // F(0E8) - F(arm0F0),F(arm0F1),F(arm0F2),F(arm0F3),F(arm0F4),F(arm0F5),F(arm0F6),F(arm0F7), // F(0F0) - F(arm0F0),F(arm0F9),F(arm0F2),F(arm_UI),F(arm0F4),F(arm0DD),F(arm0F6),F(arm0DF), // F(0F8) - - F(arm100),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI), // F(100) - F(arm_UI),F(arm109),F(arm_UI),F(arm10B),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI), // F(108) - F(arm110),F(arm111),F(arm112),F(arm113),F(arm114),F(arm115),F(arm116),F(arm117), // F(110) - F(arm110),F(arm_UI),F(arm112),F(arm11B),F(arm114),F(arm11D),F(arm116),F(arm11F), // F(118) - F(arm120),F(arm121),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_BP), // F(120) - F(arm_UI),F(arm_UI),F(arm_UI),F(arm12B),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI), // F(128) - F(arm130),F(arm131),F(arm132),F(arm133),F(arm134),F(arm135),F(arm136),F(arm137), // F(130) - F(arm130),F(arm_UI),F(arm132),F(arm13B),F(arm134),F(arm13D),F(arm136),F(arm13F), // F(138) - F(arm140),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI), // F(140) - F(arm_UI),F(arm149),F(arm_UI),F(arm14B),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI), // F(148) - F(arm150),F(arm151),F(arm152),F(arm153),F(arm154),F(arm155),F(arm156),F(arm157), // F(150) - F(arm150),F(arm_UI),F(arm152),F(arm15B),F(arm154),F(arm15D),F(arm156),F(arm15F), // F(158) - F(arm160),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI), // F(160) - F(arm_UI),F(arm_UI),F(arm_UI),F(arm16B),F(arm_UI),F(arm_UI),F(arm_UI),F(arm_UI), // F(168) - F(arm170),F(arm171),F(arm172),F(arm173),F(arm174),F(arm175),F(arm176),F(arm177), // F(170) - F(arm170),F(arm_UI),F(arm172),F(arm17B),F(arm174),F(arm17D),F(arm176),F(arm17F), // F(178) - F(arm180),F(arm181),F(arm182),F(arm183),F(arm184),F(arm185),F(arm186),F(arm187), // F(180) - F(arm180),F(arm_UI),F(arm182),F(arm18B),F(arm184),F(arm_UI),F(arm186),F(arm_UI), // F(188) - F(arm190),F(arm191),F(arm192),F(arm193),F(arm194),F(arm195),F(arm196),F(arm197), // F(190) - F(arm190),F(arm_UI),F(arm192),F(arm19B),F(arm194),F(arm19D),F(arm196),F(arm19F), // F(198) - F(arm1A0),F(arm1A1),F(arm1A2),F(arm1A3),F(arm1A4),F(arm1A5),F(arm1A6),F(arm1A7), // F(1A0) - F(arm1A0),F(arm_UI),F(arm1A2),F(arm1AB),F(arm1A4),F(arm_UI),F(arm1A6),F(arm_UI), // F(1A8) - F(arm1B0),F(arm1B1),F(arm1B2),F(arm1B3),F(arm1B4),F(arm1B5),F(arm1B6),F(arm1B7), // F(1B0) - F(arm1B0),F(arm_UI),F(arm1B2),F(arm1BB),F(arm1B4),F(arm1BD),F(arm1B6),F(arm1BF), // F(1B8) - F(arm1C0),F(arm1C1),F(arm1C2),F(arm1C3),F(arm1C4),F(arm1C5),F(arm1C6),F(arm1C7), // F(1C0) - F(arm1C0),F(arm_UI),F(arm1C2),F(arm1CB),F(arm1C4),F(arm_UI),F(arm1C6),F(arm_UI), // F(1C8) - F(arm1D0),F(arm1D1),F(arm1D2),F(arm1D3),F(arm1D4),F(arm1D5),F(arm1D6),F(arm1D7), // F(1D0) - F(arm1D0),F(arm_UI),F(arm1D2),F(arm1DB),F(arm1D4),F(arm1DD),F(arm1D6),F(arm1DF), // F(1D8) - F(arm1E0),F(arm1E1),F(arm1E2),F(arm1E3),F(arm1E4),F(arm1E5),F(arm1E6),F(arm1E7), // F(1E0) - F(arm1E0),F(arm_UI),F(arm1E2),F(arm1EB),F(arm1E4),F(arm_UI),F(arm1E6),F(arm_UI), // F(1E8) - F(arm1F0),F(arm1F1),F(arm1F2),F(arm1F3),F(arm1F4),F(arm1F5),F(arm1F6),F(arm1F7), // F(1F0) - F(arm1F0),F(arm_UI),F(arm1F2),F(arm1FB),F(arm1F4),F(arm1FD),F(arm1F6),F(arm1FF), // F(1F8) - - REP16(arm200),REP16(arm210),REP16(arm220),REP16(arm230), // 200 - REP16(arm240),REP16(arm250),REP16(arm260),REP16(arm270), // 240 - REP16(arm280),REP16(arm290),REP16(arm2A0),REP16(arm2B0), // 280 - REP16(arm2C0),REP16(arm2D0),REP16(arm2E0),REP16(arm2F0), // 2C0 - REP16(arm_UI),REP16(arm310),REP16(arm320),REP16(arm330), // 300 - REP16(arm_UI),REP16(arm350),REP16(arm360),REP16(arm370), // 340 - REP16(arm380),REP16(arm390),REP16(arm3A0),REP16(arm3B0), // 380 - REP16(arm3C0),REP16(arm3D0),REP16(arm3E0),REP16(arm3F0), // 3C0 - - REP16(arm400),REP16(arm410),REP16(arm400),REP16(arm410), // 400 - REP16(arm440),REP16(arm450),REP16(arm440),REP16(arm450), // 440 - REP16(arm480),REP16(arm490),REP16(arm480),REP16(arm490), // 480 - REP16(arm4C0),REP16(arm4D0),REP16(arm4C0),REP16(arm4D0), // 4C0 - REP16(arm500),REP16(arm510),REP16(arm520),REP16(arm530), // 500 - REP16(arm540),REP16(arm550),REP16(arm560),REP16(arm570), // 540 - REP16(arm580),REP16(arm590),REP16(arm5A0),REP16(arm5B0), // 580 - REP16(arm5C0),REP16(arm5D0),REP16(arm5E0),REP16(arm5F0), // 5C0 - - F(arm600),F(arm_UI),F(arm602),F(arm_UI),F(arm604),F(arm_UI),F(arm606),F(arm_UI), // F(600) - F(arm600),F(arm_UI),F(arm602),F(arm_UI),F(arm604),F(arm_UI),F(arm606),F(arm_UI), // F(608) - F(arm610),F(arm_UI),F(arm612),F(arm_UI),F(arm614),F(arm_UI),F(arm616),F(arm_UI), // F(610) - F(arm610),F(arm_UI),F(arm612),F(arm_UI),F(arm614),F(arm_UI),F(arm616),F(arm_UI), // F(618) - F(arm600),F(arm_UI),F(arm602),F(arm_UI),F(arm604),F(arm_UI),F(arm606),F(arm_UI), // F(620) - F(arm600),F(arm_UI),F(arm602),F(arm_UI),F(arm604),F(arm_UI),F(arm606),F(arm_UI), // F(628) - F(arm610),F(arm_UI),F(arm612),F(arm_UI),F(arm614),F(arm_UI),F(arm616),F(arm_UI), // F(630) - F(arm610),F(arm_UI),F(arm612),F(arm_UI),F(arm614),F(arm_UI),F(arm616),F(arm_UI), // F(638) - F(arm640),F(arm_UI),F(arm642),F(arm_UI),F(arm644),F(arm_UI),F(arm646),F(arm_UI), // F(640) - F(arm640),F(arm_UI),F(arm642),F(arm_UI),F(arm644),F(arm_UI),F(arm646),F(arm_UI), // F(648) - F(arm650),F(arm_UI),F(arm652),F(arm_UI),F(arm654),F(arm_UI),F(arm656),F(arm_UI), // F(650) - F(arm650),F(arm_UI),F(arm652),F(arm_UI),F(arm654),F(arm_UI),F(arm656),F(arm_UI), // F(658) - F(arm640),F(arm_UI),F(arm642),F(arm_UI),F(arm644),F(arm_UI),F(arm646),F(arm_UI), // F(660) - F(arm640),F(arm_UI),F(arm642),F(arm_UI),F(arm644),F(arm_UI),F(arm646),F(arm_UI), // F(668) - F(arm650),F(arm_UI),F(arm652),F(arm_UI),F(arm654),F(arm_UI),F(arm656),F(arm_UI), // F(670) - F(arm650),F(arm_UI),F(arm652),F(arm_UI),F(arm654),F(arm_UI),F(arm656),F(arm_UI), // F(678) - F(arm680),F(arm_UI),F(arm682),F(arm_UI),F(arm684),F(arm_UI),F(arm686),F(arm_UI), // F(680) - F(arm680),F(arm_UI),F(arm682),F(arm_UI),F(arm684),F(arm_UI),F(arm686),F(arm_UI), // F(688) - F(arm690),F(arm_UI),F(arm692),F(arm_UI),F(arm694),F(arm_UI),F(arm696),F(arm_UI), // F(690) - F(arm690),F(arm_UI),F(arm692),F(arm_UI),F(arm694),F(arm_UI),F(arm696),F(arm_UI), // F(698) - F(arm680),F(arm_UI),F(arm682),F(arm_UI),F(arm684),F(arm_UI),F(arm686),F(arm_UI), // F(6A0) - F(arm680),F(arm_UI),F(arm682),F(arm_UI),F(arm684),F(arm_UI),F(arm686),F(arm_UI), // F(6A8) - F(arm690),F(arm_UI),F(arm692),F(arm_UI),F(arm694),F(arm_UI),F(arm696),F(arm_UI), // F(6B0) - F(arm690),F(arm_UI),F(arm692),F(arm_UI),F(arm694),F(arm_UI),F(arm696),F(arm_UI), // F(6B8) - F(arm6C0),F(arm_UI),F(arm6C2),F(arm_UI),F(arm6C4),F(arm_UI),F(arm6C6),F(arm_UI), // F(6C0) - F(arm6C0),F(arm_UI),F(arm6C2),F(arm_UI),F(arm6C4),F(arm_UI),F(arm6C6),F(arm_UI), // F(6C8) - F(arm6D0),F(arm_UI),F(arm6D2),F(arm_UI),F(arm6D4),F(arm_UI),F(arm6D6),F(arm_UI), // F(6D0) - F(arm6D0),F(arm_UI),F(arm6D2),F(arm_UI),F(arm6D4),F(arm_UI),F(arm6D6),F(arm_UI), // F(6D8) - F(arm6C0),F(arm_UI),F(arm6C2),F(arm_UI),F(arm6C4),F(arm_UI),F(arm6C6),F(arm_UI), // F(6E0) - F(arm6C0),F(arm_UI),F(arm6C2),F(arm_UI),F(arm6C4),F(arm_UI),F(arm6C6),F(arm_UI), // F(6E8) - F(arm6D0),F(arm_UI),F(arm6D2),F(arm_UI),F(arm6D4),F(arm_UI),F(arm6D6),F(arm_UI), // F(6F0) - F(arm6D0),F(arm_UI),F(arm6D2),F(arm_UI),F(arm6D4),F(arm_UI),F(arm6D6),F(arm_UI), // F(6F8) - - F(arm700),F(arm_UI),F(arm702),F(arm_UI),F(arm704),F(arm_UI),F(arm706),F(arm_UI), // F(700) - F(arm700),F(arm_UI),F(arm702),F(arm_UI),F(arm704),F(arm_UI),F(arm706),F(arm_UI), // F(708) - F(arm710),F(arm_UI),F(arm712),F(arm_UI),F(arm714),F(arm_UI),F(arm716),F(arm_UI), // F(710) - F(arm710),F(arm_UI),F(arm712),F(arm_UI),F(arm714),F(arm_UI),F(arm716),F(arm_UI), // F(718) - F(arm720),F(arm_UI),F(arm722),F(arm_UI),F(arm724),F(arm_UI),F(arm726),F(arm_UI), // F(720) - F(arm720),F(arm_UI),F(arm722),F(arm_UI),F(arm724),F(arm_UI),F(arm726),F(arm_UI), // F(728) - F(arm730),F(arm_UI),F(arm732),F(arm_UI),F(arm734),F(arm_UI),F(arm736),F(arm_UI), // F(730) - F(arm730),F(arm_UI),F(arm732),F(arm_UI),F(arm734),F(arm_UI),F(arm736),F(arm_UI), // F(738) - F(arm740),F(arm_UI),F(arm742),F(arm_UI),F(arm744),F(arm_UI),F(arm746),F(arm_UI), // F(740) - F(arm740),F(arm_UI),F(arm742),F(arm_UI),F(arm744),F(arm_UI),F(arm746),F(arm_UI), // F(748) - F(arm750),F(arm_UI),F(arm752),F(arm_UI),F(arm754),F(arm_UI),F(arm756),F(arm_UI), // F(750) - F(arm750),F(arm_UI),F(arm752),F(arm_UI),F(arm754),F(arm_UI),F(arm756),F(arm_UI), // F(758) - F(arm760),F(arm_UI),F(arm762),F(arm_UI),F(arm764),F(arm_UI),F(arm766),F(arm_UI), // F(760) - F(arm760),F(arm_UI),F(arm762),F(arm_UI),F(arm764),F(arm_UI),F(arm766),F(arm_UI), // F(768) - F(arm770),F(arm_UI),F(arm772),F(arm_UI),F(arm774),F(arm_UI),F(arm776),F(arm_UI), // F(770) - F(arm770),F(arm_UI),F(arm772),F(arm_UI),F(arm774),F(arm_UI),F(arm776),F(arm_UI), // F(778) - F(arm780),F(arm_UI),F(arm782),F(arm_UI),F(arm784),F(arm_UI),F(arm786),F(arm_UI), // F(780) - F(arm780),F(arm_UI),F(arm782),F(arm_UI),F(arm784),F(arm_UI),F(arm786),F(arm_UI), // F(788) - F(arm790),F(arm_UI),F(arm792),F(arm_UI),F(arm794),F(arm_UI),F(arm796),F(arm_UI), // F(790) - F(arm790),F(arm_UI),F(arm792),F(arm_UI),F(arm794),F(arm_UI),F(arm796),F(arm_UI), // F(798) - F(arm7A0),F(arm_UI),F(arm7A2),F(arm_UI),F(arm7A4),F(arm_UI),F(arm7A6),F(arm_UI), // F(7A0) - F(arm7A0),F(arm_UI),F(arm7A2),F(arm_UI),F(arm7A4),F(arm_UI),F(arm7A6),F(arm_UI), // F(7A8) - F(arm7B0),F(arm_UI),F(arm7B2),F(arm_UI),F(arm7B4),F(arm_UI),F(arm7B6),F(arm_UI), // F(7B0) - F(arm7B0),F(arm_UI),F(arm7B2),F(arm_UI),F(arm7B4),F(arm_UI),F(arm7B6),F(arm_UI), // F(7B8) - F(arm7C0),F(arm_UI),F(arm7C2),F(arm_UI),F(arm7C4),F(arm_UI),F(arm7C6),F(arm_UI), // F(7C0) - F(arm7C0),F(arm_UI),F(arm7C2),F(arm_UI),F(arm7C4),F(arm_UI),F(arm7C6),F(arm_UI), // F(7C8) - F(arm7D0),F(arm_UI),F(arm7D2),F(arm_UI),F(arm7D4),F(arm_UI),F(arm7D6),F(arm_UI), // F(7D0) - F(arm7D0),F(arm_UI),F(arm7D2),F(arm_UI),F(arm7D4),F(arm_UI),F(arm7D6),F(arm_UI), // F(7D8) - F(arm7E0),F(arm_UI),F(arm7E2),F(arm_UI),F(arm7E4),F(arm_UI),F(arm7E6),F(arm_UI), // F(7E0) - F(arm7E0),F(arm_UI),F(arm7E2),F(arm_UI),F(arm7E4),F(arm_UI),F(arm7E6),F(arm_UI), // F(7E8) - F(arm7F0),F(arm_UI),F(arm7F2),F(arm_UI),F(arm7F4),F(arm_UI),F(arm7F6),F(arm_UI), // F(7F0) - F(arm7F0),F(arm_UI),F(arm7F2),F(arm_UI),F(arm7F4),F(arm_UI),F(arm7F6),F(arm_BP), // F(7F8) - - REP16(arm800),REP16(arm810),REP16(arm820),REP16(arm830), // 800 - REP16(arm840),REP16(arm850),REP16(arm860),REP16(arm870), // 840 - REP16(arm880),REP16(arm890),REP16(arm8A0),REP16(arm8B0), // 880 - REP16(arm8C0),REP16(arm8D0),REP16(arm8E0),REP16(arm8F0), // 8C0 - REP16(arm900),REP16(arm910),REP16(arm920),REP16(arm930), // 900 - REP16(arm940),REP16(arm950),REP16(arm960),REP16(arm970), // 940 - REP16(arm980),REP16(arm990),REP16(arm9A0),REP16(arm9B0), // 980 - REP16(arm9C0),REP16(arm9D0),REP16(arm9E0),REP16(arm9F0), // 9C0 - - REP256(armA00), // A00 - REP256(armB00), // B00 - REP256(arm_UI), // C00 - REP256(arm_UI), // D00 - - F(arm_UI),F(armE01),F(arm_UI),F(armE01),F(arm_UI),F(armE01),F(arm_UI),F(armE01), // F(E00) - F(arm_UI),F(armE01),F(arm_UI),F(armE01),F(arm_UI),F(armE01),F(arm_UI),F(armE01), // F(E08) - F(arm_UI),F(armE01),F(arm_UI),F(armE01),F(arm_UI),F(armE01),F(arm_UI),F(armE01), // F(E10) - F(arm_UI),F(armE01),F(arm_UI),F(armE01),F(arm_UI),F(armE01),F(arm_UI),F(armE01), // F(E18) - REP16(arm_UI), // E20 - REP16(arm_UI), // E30 - REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E40 - REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // E80 - REP16(arm_UI),REP16(arm_UI),REP16(arm_UI),REP16(arm_UI), // EC0 - - REP256(armF00), // F00 -}; - -void (Gigazoid::*const Gigazoid::thumbInsnTable[1024])(u32 opcode) = { - F(thumb00_00),F(thumb00_01),F(thumb00_02),F(thumb00_03),F(thumb00_04),F(thumb00_05),F(thumb00_06),F(thumb00_07), // F(00) - F(thumb00_08),F(thumb00_09),F(thumb00_0A),F(thumb00_0B),F(thumb00_0C),F(thumb00_0D),F(thumb00_0E),F(thumb00_0F), - F(thumb00_10),F(thumb00_11),F(thumb00_12),F(thumb00_13),F(thumb00_14),F(thumb00_15),F(thumb00_16),F(thumb00_17), - F(thumb00_18),F(thumb00_19),F(thumb00_1A),F(thumb00_1B),F(thumb00_1C),F(thumb00_1D),F(thumb00_1E),F(thumb00_1F), - F(thumb08_00),F(thumb08_01),F(thumb08_02),F(thumb08_03),F(thumb08_04),F(thumb08_05),F(thumb08_06),F(thumb08_07), // F(08) - F(thumb08_08),F(thumb08_09),F(thumb08_0A),F(thumb08_0B),F(thumb08_0C),F(thumb08_0D),F(thumb08_0E),F(thumb08_0F), - F(thumb08_10),F(thumb08_11),F(thumb08_12),F(thumb08_13),F(thumb08_14),F(thumb08_15),F(thumb08_16),F(thumb08_17), - F(thumb08_18),F(thumb08_19),F(thumb08_1A),F(thumb08_1B),F(thumb08_1C),F(thumb08_1D),F(thumb08_1E),F(thumb08_1F), - F(thumb10_00),F(thumb10_01),F(thumb10_02),F(thumb10_03),F(thumb10_04),F(thumb10_05),F(thumb10_06),F(thumb10_07), // F(10) - F(thumb10_08),F(thumb10_09),F(thumb10_0A),F(thumb10_0B),F(thumb10_0C),F(thumb10_0D),F(thumb10_0E),F(thumb10_0F), - F(thumb10_10),F(thumb10_11),F(thumb10_12),F(thumb10_13),F(thumb10_14),F(thumb10_15),F(thumb10_16),F(thumb10_17), - F(thumb10_18),F(thumb10_19),F(thumb10_1A),F(thumb10_1B),F(thumb10_1C),F(thumb10_1D),F(thumb10_1E),F(thumb10_1F), - F(thumb18_0),F(thumb18_1),F(thumb18_2),F(thumb18_3),F(thumb18_4),F(thumb18_5),F(thumb18_6),F(thumb18_7), // F(18) - F(thumb1A_0),F(thumb1A_1),F(thumb1A_2),F(thumb1A_3),F(thumb1A_4),F(thumb1A_5),F(thumb1A_6),F(thumb1A_7), - F(thumb1C_0),F(thumb1C_1),F(thumb1C_2),F(thumb1C_3),F(thumb1C_4),F(thumb1C_5),F(thumb1C_6),F(thumb1C_7), - F(thumb1E_0),F(thumb1E_1),F(thumb1E_2),F(thumb1E_3),F(thumb1E_4),F(thumb1E_5),F(thumb1E_6),F(thumb1E_7), - F(thumb20),F(thumb20),F(thumb20),F(thumb20),F(thumb21),F(thumb21),F(thumb21),F(thumb21), // F(20) - F(thumb22),F(thumb22),F(thumb22),F(thumb22),F(thumb23),F(thumb23),F(thumb23),F(thumb23), - F(thumb24),F(thumb24),F(thumb24),F(thumb24),F(thumb25),F(thumb25),F(thumb25),F(thumb25), - F(thumb26),F(thumb26),F(thumb26),F(thumb26),F(thumb27),F(thumb27),F(thumb27),F(thumb27), - F(thumb28),F(thumb28),F(thumb28),F(thumb28),F(thumb29),F(thumb29),F(thumb29),F(thumb29), // F(28) - F(thumb2A),F(thumb2A),F(thumb2A),F(thumb2A),F(thumb2B),F(thumb2B),F(thumb2B),F(thumb2B), - F(thumb2C),F(thumb2C),F(thumb2C),F(thumb2C),F(thumb2D),F(thumb2D),F(thumb2D),F(thumb2D), - F(thumb2E),F(thumb2E),F(thumb2E),F(thumb2E),F(thumb2F),F(thumb2F),F(thumb2F),F(thumb2F), - F(thumb30),F(thumb30),F(thumb30),F(thumb30),F(thumb31),F(thumb31),F(thumb31),F(thumb31), // F(30) - F(thumb32),F(thumb32),F(thumb32),F(thumb32),F(thumb33),F(thumb33),F(thumb33),F(thumb33), - F(thumb34),F(thumb34),F(thumb34),F(thumb34),F(thumb35),F(thumb35),F(thumb35),F(thumb35), - F(thumb36),F(thumb36),F(thumb36),F(thumb36),F(thumb37),F(thumb37),F(thumb37),F(thumb37), - F(thumb38),F(thumb38),F(thumb38),F(thumb38),F(thumb39),F(thumb39),F(thumb39),F(thumb39), // F(38) - F(thumb3A),F(thumb3A),F(thumb3A),F(thumb3A),F(thumb3B),F(thumb3B),F(thumb3B),F(thumb3B), - F(thumb3C),F(thumb3C),F(thumb3C),F(thumb3C),F(thumb3D),F(thumb3D),F(thumb3D),F(thumb3D), - F(thumb3E),F(thumb3E),F(thumb3E),F(thumb3E),F(thumb3F),F(thumb3F),F(thumb3F),F(thumb3F), - F(thumb40_0),F(thumb40_1),F(thumb40_2),F(thumb40_3),F(thumb41_0),F(thumb41_1),F(thumb41_2),F(thumb41_3), // F(40) - F(thumb42_0),F(thumb42_1),F(thumb42_2),F(thumb42_3),F(thumb43_0),F(thumb43_1),F(thumb43_2),F(thumb43_3), - F(thumbUI),F(thumb44_1),F(thumb44_2),F(thumb44_3),F(thumbUI),F(thumb45_1),F(thumb45_2),F(thumb45_3), - F(thumbUI),F(thumb46_1),F(thumb46_2),F(thumb46_3),F(thumb47),F(thumb47),F(thumbUI),F(thumbUI), - F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48), // F(48) - F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48), - F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48), - F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48),F(thumb48), - F(thumb50),F(thumb50),F(thumb50),F(thumb50),F(thumb50),F(thumb50),F(thumb50),F(thumb50), // F(50) - F(thumb52),F(thumb52),F(thumb52),F(thumb52),F(thumb52),F(thumb52),F(thumb52),F(thumb52), - F(thumb54),F(thumb54),F(thumb54),F(thumb54),F(thumb54),F(thumb54),F(thumb54),F(thumb54), - F(thumb56),F(thumb56),F(thumb56),F(thumb56),F(thumb56),F(thumb56),F(thumb56),F(thumb56), - F(thumb58),F(thumb58),F(thumb58),F(thumb58),F(thumb58),F(thumb58),F(thumb58),F(thumb58), // F(58) - F(thumb5A),F(thumb5A),F(thumb5A),F(thumb5A),F(thumb5A),F(thumb5A),F(thumb5A),F(thumb5A), - F(thumb5C),F(thumb5C),F(thumb5C),F(thumb5C),F(thumb5C),F(thumb5C),F(thumb5C),F(thumb5C), - F(thumb5E),F(thumb5E),F(thumb5E),F(thumb5E),F(thumb5E),F(thumb5E),F(thumb5E),F(thumb5E), - F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60), // F(60) - F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60), - F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60), - F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60),F(thumb60), - F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68), // F(68) - F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68), - F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68), - F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68),F(thumb68), - F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70), // F(70) - F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70), - F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70), - F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70),F(thumb70), - F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78), // F(78) - F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78), - F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78), - F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78),F(thumb78), - F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80), // F(80) - F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80), - F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80), - F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80),F(thumb80), - F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88), // F(88) - F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88), - F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88), - F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88),F(thumb88), - F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90), // F(90) - F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90), - F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90), - F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90),F(thumb90), - F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98), // F(98) - F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98), - F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98), - F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98),F(thumb98), - F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0), // F(A0) - F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0), - F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0), - F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0),F(thumbA0), - F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8), // F(A8) - F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8), - F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8), - F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8),F(thumbA8), - F(thumbB0),F(thumbB0),F(thumbB0),F(thumbB0),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), // F(B0) - F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), - F(thumbB4),F(thumbB4),F(thumbB4),F(thumbB4),F(thumbB5),F(thumbB5),F(thumbB5),F(thumbB5), - F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), - F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), // F(B8) - F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), - F(thumbBC),F(thumbBC),F(thumbBC),F(thumbBC),F(thumbBD),F(thumbBD),F(thumbBD),F(thumbBD), - F(thumbBP),F(thumbBP),F(thumbBP),F(thumbBP),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), - F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0), // F(C0) - F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0), - F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0), - F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0),F(thumbC0), - F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8), // F(C8) - F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8), - F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8), - F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8),F(thumbC8), - F(thumbD0),F(thumbD0),F(thumbD0),F(thumbD0),F(thumbD1),F(thumbD1),F(thumbD1),F(thumbD1), // F(D0) - F(thumbD2),F(thumbD2),F(thumbD2),F(thumbD2),F(thumbD3),F(thumbD3),F(thumbD3),F(thumbD3), - F(thumbD4),F(thumbD4),F(thumbD4),F(thumbD4),F(thumbD5),F(thumbD5),F(thumbD5),F(thumbD5), - F(thumbD6),F(thumbD6),F(thumbD6),F(thumbD6),F(thumbD7),F(thumbD7),F(thumbD7),F(thumbD7), - F(thumbD8),F(thumbD8),F(thumbD8),F(thumbD8),F(thumbD9),F(thumbD9),F(thumbD9),F(thumbD9), // F(D8) - F(thumbDA),F(thumbDA),F(thumbDA),F(thumbDA),F(thumbDB),F(thumbDB),F(thumbDB),F(thumbDB), - F(thumbDC),F(thumbDC),F(thumbDC),F(thumbDC),F(thumbDD),F(thumbDD),F(thumbDD),F(thumbDD), - F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbDF),F(thumbDF),F(thumbDF),F(thumbDF), - F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0), // F(E0) - F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0), - F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0), - F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0),F(thumbE0), - F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), // F(E8) - F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), - F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), - F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI),F(thumbUI), - F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0), // F(F0) - F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0),F(thumbF0), - F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4), - F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4),F(thumbF4), - F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8), // F(F8) - F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8), - F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8), - F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8),F(thumbF8), -}; - -#undef F diff --git a/vbanext/port.h b/vbanext/port.h deleted file mode 100644 index 3b2457042e..0000000000 --- a/vbanext/port.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef PORT_H -#define PORT_H - -#include "types.h" - -/* if a >= 0 return x else y*/ -#define isel(a, x, y) ((x & (~(a >> 31))) + (y & (a >> 31))) - -#ifdef FRONTEND_SUPPORTS_RGB565 -/* 16bit color - RGB565 */ -#define RED_MASK 0xf800 -#define GREEN_MASK 0x7e0 -#define BLUE_MASK 0x1f -#define RED_EXPAND 3 -#define GREEN_EXPAND 2 -#define BLUE_EXPAND 3 -#define RED_SHIFT 11 -#define GREEN_SHIFT 5 -#define BLUE_SHIFT 0 -#define CONVERT_COLOR(color) (((color & 0x001f) << 11) | ((color & 0x03e0) << 1) | ((color & 0x0200) >> 4) | ((color & 0x7c00) >> 10)) -#else -/* 16bit color - RGB555 */ -#define RED_MASK 0x7c00 -#define GREEN_MASK 0x3e0 -#define BLUE_MASK 0x1f -#define RED_EXPAND 3 -#define GREEN_EXPAND 3 -#define BLUE_EXPAND 3 -#define RED_SHIFT 10 -#define GREEN_SHIFT 5 -#define BLUE_SHIFT 0 -#define CONVERT_COLOR(color) ((((color & 0x1f) << 10) | (((color & 0x3e0) >> 5) << 5) | (((color & 0x7c00) >> 10))) & 0x7fff) -#endif - -#ifdef _MSC_VER -#include -#define strcasecmp _stricmp -#endif - -#ifdef USE_CACHE_PREFETCH -#if defined(__ANDROID__) -#define CACHE_PREFETCH(prefetch) prefetch(&prefetch); -#elif defined(_XBOX) -#define CACHE_PREFETCH(prefetch) __dcbt(0, &prefetch); -#else -#define CACHE_PREFETCH(prefetch) __dcbt(&prefetch); -#endif -#else -#define CACHE_PREFETCH(prefetch) -#endif - -#define READ16LE(x) *((u16 *)x) -#define READ32LE(x) *((u32 *)x) -#define WRITE16LE(x,v) *((u16 *)x) = (v) -#define WRITE32LE(x,v) *((u32 *)x) = (v) - -#endif diff --git a/vbanext/sound_blargg.h b/vbanext/sound_blargg.h deleted file mode 100644 index c80d61e18e..0000000000 --- a/vbanext/sound_blargg.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef SOUND_BLARGG_H -#define SOUND_BLARGG_H - -/* Uncomment to have Gb_Apu run at 4x normal clock rate (16777216 Hz), useful in -a Game Boy Advance emulator. */ -#define GB_APU_OVERCLOCK 4 - -#ifndef STATIC_CAST - #if __GNUC__ >= 4 - #define STATIC_CAST(T,expr) static_cast (expr) - #define CONST_CAST( T,expr) const_cast (expr) - #else - #define STATIC_CAST(T,expr) ((T) (expr)) - #define CONST_CAST( T,expr) ((T) (expr)) - #endif -#endif - -// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, -// compiler is assumed to support bool. If undefined, availability is determined. -#ifndef BLARGG_COMPILER_HAS_BOOL - #if defined (__MWERKS__) - #if !__option(bool) - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (_MSC_VER) - #if _MSC_VER < 1100 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (__GNUC__) - // supports bool - #elif __cplusplus < 199711 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif -#endif -#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL - typedef int bool; - const bool true = 1; - const bool false = 0; -#endif - -/* HAVE_STDINT_H: If defined, use for int8_t etc.*/ -#if defined (HAVE_STDINT_H) - #include -/* HAVE_INTTYPES_H: If defined, use for int8_t etc.*/ -#elif defined (HAVE_INTTYPES_H) - #include -#endif - -// If expr yields non-NULL error string, returns it from current function, -// otherwise continues normally. -#undef RETURN_ERR -#define RETURN_ERR( expr ) do { \ - const char * blargg_return_err_ = (expr); \ - if ( blargg_return_err_ ) return blargg_return_err_; \ - } while ( 0 ) - -#endif // #ifndef SOUND_BLARGG_H diff --git a/vbanext/types.h b/vbanext/types.h deleted file mode 100644 index 8433576dcc..0000000000 --- a/vbanext/types.h +++ /dev/null @@ -1,33 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 2008 VBA-M development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef __VBA_TYPES_H__ -#define __VBA_TYPES_H__ - -#include - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - -#endif // __VBA_TYPES_H__