diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index a9d9eeafbc..9d0ef455f7 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -413,7 +413,7 @@ - Intellivision.cs + Intellivision.cs Intellivision.cs @@ -491,26 +491,10 @@ + - - - - Meteor.cs - - - Meteor.cs - - - Meteor.cs - - - Meteor.cs - - - Meteor.cs - diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibMeteor.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibMeteor.cs deleted file mode 100644 index 4f4dc96f68..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibMeteor.cs +++ /dev/null @@ -1,294 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - /// - /// bindings into libmeteor.dll - /// - public static class LibMeteor - { - /// - /// power cycle the emulation core - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_hardreset(); - - /// - /// signal that you are removing data from the sound buffer. - /// the next time frameadvance() is called, writing will start from the beginning - /// - /// the valid length of the buffer, in bytes - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern uint libmeteor_emptysound(); - - /// - /// set up buffers for libmeteor to dump data to. these must be valid before every frameadvance - /// - /// buffer to hold video data as BGRA32 - /// length in bytes. must be at least 240 * 160 * 4 - /// buffer to hold audio data as stereo s16le - /// length in bytes. must be 0 mod 4 (hold a full stereo sample set) - /// false if some problem. buffers will not be valid in this case - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool libmeteor_setbuffers(IntPtr vid, uint vidlen, IntPtr aud, uint audlen); - - /// - /// initialize the library - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_init(); - - /// - /// run emulation for one frame, updating sound and video along the way - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_frameadvance(); - - /// - /// load a rom image - /// - /// raw rom data. need not persist past this call - /// length of data in bytes - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_loadrom(byte[] data, uint datalen); - - /// - /// load a bios image - /// - /// raw bios data. need not persist past this call - /// length of data in bytes - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_loadbios(byte[] data, uint datalen); - - /// - /// core callback to print meaningful (or meaningless) log messages - /// - /// message to be printed - /// true if emulation should be aborted - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void MessageCallback(string msg, bool abort); - - /// - /// set callback for log messages. this can (and should) be called first - /// - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_setmessagecallback(MessageCallback cb); - - /// - /// combination of button flags used by the key callback - /// - [Flags] - public enum Buttons : ushort - { - BTN_A = 0x001, - BTN_B = 0x002, - BTN_SELECT = 0x004, - BTN_START = 0x008, - BTN_RIGHT = 0x010, - BTN_LEFT = 0x020, - BTN_UP = 0x040, - BTN_DOWN = 0x080, - BTN_R = 0x100, - BTN_L = 0x200 - } - - /// - /// core callback to get input state - /// - /// buttons pressed bitfield - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Buttons InputCallback(); - - /// - /// set callback for whenever input is requested - /// - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_setkeycallback(InputCallback callback); - - /// - /// parameter to libmeteor_getmemoryarea - /// - public enum MemoryArea - { - /// - /// BIOS, may be invalid if bios not loaded. valid size: 16K. system bus: @00000000h - /// - bios = 0, - /// - /// external workram. valid size: 256K. system bus: @02000000h - /// - ewram = 1, - /// - /// internal workram. valid size: 32K. system bus: @03000000h - /// - iwram = 2, - /// - /// palettes. valid size: 1K. system bus: @05000000h - /// - palram = 3, - /// - /// video ram. valid size: 96K. system bus: @06000000h - /// - vram = 4, - /// - /// sprite attribute ram. valid size: 1K. system bus: @07000000h - /// - oam = 5, - /// - /// rom. always valid to full size, even if no rom or small rom loaded. valid size: 32M. system bus: @08000000h, others - /// - rom = 6, - /// - /// direct access to cached io port values. this should NEVER be modified! valid size: 4K. system bus: @04000000h (sort of) - /// - io = 7 - } - - /// - /// return a pointer to a memory area - /// - /// - /// IntPtr.Zero if which is unrecognized - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr libmeteor_getmemoryarea(MemoryArea which); - - /// - /// core callback for tracelogging - /// - /// disassembly of an instruction about to be run - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void TraceCallback(string msg); - - /// - /// set callback to run before each instruction is executed - /// - /// null to clear - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_settracecallback(TraceCallback callback); - - /// - /// load saveram from a byte buffer - /// - /// - /// - /// success - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool libmeteor_loadsaveram(byte[] data, uint size); - - /// - /// save saveram to a byte buffer - /// - /// buffer generated by core. copy from, but do not modify - /// length of buffer - /// success - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool libmeteor_savesaveram(ref IntPtr data, ref uint size); - - /// - /// destroy a buffer previously returned by libmeteor_savesaveram() to avoid leakage - /// - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_savesaveram_destroy(IntPtr data); - - /// - /// return true if there is saveram installed on currently loaded cart - /// - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool libmeteor_hassaveram(); - - /// - /// resets the current cart's saveram - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_clearsaveram(); - - /// - /// serialize state - /// - /// buffer generated by core - /// size of buffer - /// success - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool libmeteor_savestate(ref IntPtr data, ref uint size); - - /// - /// destroy a buffer previously returned by libmeteor_savestate() to avoid leakage - /// - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_savestate_destroy(IntPtr data); - - /// - /// unserialize state - /// - /// - /// - /// success - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool libmeteor_loadstate(byte[] data, uint size); - - /// - /// read a byte off the system bus. guaranteed to have no side effects - /// - /// - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern byte libmeteor_peekbus(uint addr); - - /// - /// write a byte to the system bus. - /// - /// - /// - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_writebus(uint addr, byte val); - - /// - /// type of the scanline callback - /// - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void ScanlineCallback(); - - /// - /// set a callback to coincide with vcount interrupts - /// - /// null to clear - /// 0-227, 160 occurring first in a frame - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_setscanlinecallback(ScanlineCallback callback, int scanline); - - /// - /// get current cpu regs - /// - /// length 18 please - [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern void libmeteor_getregs(int[] dest); - - public static readonly string[] regnames = new string[] - { - "r0", - "r1", - "r2", - "r3", - "r4", - "r5", - "r6", - "r7", - "r8", - "r9", - "r10", - "r11", - "r12", - "r13", - "r14", - "r15", - "cpsr", - "spsr" - }; - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IGBAGPUViewable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IGBAGPUViewable.cs deleted file mode 100644 index 76142c1433..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IGBAGPUViewable.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class GBA : IGBAGPUViewable - { - public GBAGPUMemoryAreas GetMemoryAreas() - { - IntPtr _vram = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.vram); - IntPtr _palram = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.palram); - IntPtr _oam = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.oam); - IntPtr _mmio = LibMeteor.libmeteor_getmemoryarea(LibMeteor.MemoryArea.io); - - if (_vram == IntPtr.Zero || _palram == IntPtr.Zero || _oam == IntPtr.Zero || _mmio == IntPtr.Zero) - throw new Exception("libmeteor_getmemoryarea() failed!"); - - return new GBAGPUMemoryAreas - { - vram = _vram, - palram = _palram, - oam = _oam, - mmio = _mmio - }; - } - - 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; - LibMeteor.libmeteor_setscanlinecallback(null, 0); - } - else - { - scanlinecb = new LibMeteor.ScanlineCallback(callback); - LibMeteor.libmeteor_setscanlinecallback(scanlinecb, scanline); - } - } - - private LibMeteor.ScanlineCallback scanlinecb = null; - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IMemoryDomains.cs deleted file mode 100644 index 5835a4241d..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IMemoryDomains.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class GBA - { - private List _domainList = new List(); - private IMemoryDomains _memoryDomains; - - private void AddMemoryDomain(LibMeteor.MemoryArea which, int size, string name) - { - IntPtr data = LibMeteor.libmeteor_getmemoryarea(which); - if (data == IntPtr.Zero) - throw new Exception("libmeteor_getmemoryarea() returned NULL??"); - - MemoryDomain md = MemoryDomain.FromIntPtr(name, size, MemoryDomain.Endian.Little, data); - _domainList.Add(md); - } - - private void SetUpMemoryDomains() - { - _domainList.Clear(); - // this must be first to coincide with "main memory" - // note that ewram could also be considered main memory depending on which hairs you split - AddMemoryDomain(LibMeteor.MemoryArea.iwram, 32 * 1024, "IWRAM"); - AddMemoryDomain(LibMeteor.MemoryArea.ewram, 256 * 1024, "EWRAM"); - AddMemoryDomain(LibMeteor.MemoryArea.bios, 16 * 1024, "BIOS"); - AddMemoryDomain(LibMeteor.MemoryArea.palram, 1024, "PALRAM"); - AddMemoryDomain(LibMeteor.MemoryArea.vram, 96 * 1024, "VRAM"); - AddMemoryDomain(LibMeteor.MemoryArea.oam, 1024, "OAM"); - // even if the rom is less than 32MB, the whole is still valid in meteor - AddMemoryDomain(LibMeteor.MemoryArea.rom, 32 * 1024 * 1024, "ROM"); - // special domain for system bus - { - MemoryDomain sb = new MemoryDomainDelegate("System Bus", 1 << 28, MemoryDomain.Endian.Little, - delegate(long addr) - { - if (addr < 0 || addr >= 0x10000000) - throw new IndexOutOfRangeException(); - return LibMeteor.libmeteor_peekbus((uint)addr); - }, - delegate(long addr, byte val) - { - if (addr < 0 || addr >= 0x10000000) - throw new IndexOutOfRangeException(); - LibMeteor.libmeteor_writebus((uint)addr, val); - }, 4); - _domainList.Add(sb); - } - // special combined ram memory domain - { - var ew = _domainList[1]; - var iw = _domainList[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); - _domainList.Add(cr); - } - - _memoryDomains = new MemoryDomainList(_domainList); - (ServiceProvider as BasicServiceProvider).Register(_memoryDomains); - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.ISaveRam.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.ISaveRam.cs deleted file mode 100644 index ec182a2855..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.ISaveRam.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class GBA : ISaveRam - { - public bool SaveRamModified - { - get - { - if (disposed) - throw new ObjectDisposedException(this.GetType().ToString()); - return LibMeteor.libmeteor_hassaveram(); - } - } - - public byte[] CloneSaveRam() - { - throw new Exception("This needs to be fixed to match the VBANext Core!"); -#if false - if (disposed) - throw new ObjectDisposedException(this.GetType().ToString()); - if (!LibMeteor.libmeteor_hassaveram()) - return null; - IntPtr data = IntPtr.Zero; - uint size = 0; - if (!LibMeteor.libmeteor_savesaveram(ref data, ref size)) - throw new Exception("libmeteor_savesaveram() returned false!"); - byte[] ret = new byte[size]; - Marshal.Copy(data, ret, 0, (int)size); - LibMeteor.libmeteor_savesaveram_destroy(data); - return ret; -#endif - } - - public void StoreSaveRam(byte[] data) - { - throw new Exception("This needs to be fixed to match the VBANext Core!"); -#if false - if (disposed) - throw new ObjectDisposedException(this.GetType().ToString()); - if (!LibMeteor.libmeteor_loadsaveram(data, (uint)data.Length)) - throw new Exception("libmeteor_loadsaveram() returned false!"); -#endif - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IStatable.cs deleted file mode 100644 index 8ac877e5af..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IStatable.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; - -using BizHawk.Common.BufferExtensions; -using BizHawk.Emulation.Common; - - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class GBA : IStatable - { - public bool BinarySaveStatesPreferred { get { return true; } } - - public void SaveStateText(System.IO.TextWriter writer) - { - var temp = SaveStateBinary(); - temp.SaveAsHex(writer); - // write extra copy of stuff we don't use - writer.WriteLine("Frame {0}", Frame); - } - - public void LoadStateText(System.IO.TextReader reader) - { - string hex = reader.ReadLine(); - byte[] state = new byte[hex.Length / 2]; - state.ReadFromHex(hex); - LoadStateBinary(new BinaryReader(new MemoryStream(state))); - } - - public void SaveStateBinary(System.IO.BinaryWriter writer) - { - byte[] data = SaveCoreBinary(); - writer.Write(data.Length); - writer.Write(data); - // other variables - writer.Write(IsLagFrame); - writer.Write(LagCount); - writer.Write(Frame); - } - - public void LoadStateBinary(System.IO.BinaryReader reader) - { - int length = reader.ReadInt32(); - byte[] data = reader.ReadBytes(length); - LoadCoreBinary(data); - // other variables - IsLagFrame = reader.ReadBoolean(); - LagCount = reader.ReadInt32(); - Frame = reader.ReadInt32(); - } - - public byte[] SaveStateBinary() - { - MemoryStream ms = new MemoryStream(); - BinaryWriter bw = new BinaryWriter(ms); - SaveStateBinary(bw); - bw.Flush(); - return ms.ToArray(); - } - - private byte[] SaveCoreBinary() - { - IntPtr ndata = IntPtr.Zero; - uint nsize = 0; - if (!LibMeteor.libmeteor_savestate(ref ndata, ref nsize)) - throw new Exception("libmeteor_savestate() failed!"); - if (ndata == IntPtr.Zero || nsize == 0) - throw new Exception("libmeteor_savestate() returned bad!"); - - byte[] ret = new byte[nsize]; - Marshal.Copy(ndata, ret, 0, (int)nsize); - LibMeteor.libmeteor_savestate_destroy(ndata); - return ret; - } - - private void LoadCoreBinary(byte[] data) - { - if (!LibMeteor.libmeteor_loadstate(data, (uint)data.Length)) - throw new Exception("libmeteor_loadstate() failed!"); - } - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IVideoProvider.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IVideoProvider.cs deleted file mode 100644 index ba313a0280..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IVideoProvider.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - public partial class GBA : IVideoProvider - { - public int VirtualWidth { get { return 240; } } - public int VirtualHeight { get { return 160; } } - public int BufferWidth { get { return 240; } } - public int BufferHeight { get { return 160; } } - public int BackgroundColor - { - get { return unchecked((int)0xff000000); } - } - - public int[] GetVideoBuffer() - { - return videobuffer; - } - - private int[] videobuffer; - private GCHandle videohandle; - } -} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.cs deleted file mode 100644 index d0eaa8ff52..0000000000 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.cs +++ /dev/null @@ -1,336 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.IO; - -using BizHawk.Common.BufferExtensions; -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Nintendo.GBA -{ - [CoreAttributes( - "Meteor", - "blastrock", - isPorted: true, - isReleased: false, - singleInstance: true - )] - [ServiceNotApplicable(typeof(IDriveLight), typeof(IRegionable))] - public partial class GBA : IEmulator, IVideoProvider, ISoundProvider, IGBAGPUViewable, ISaveRam, IStatable, IInputPollable - { - [CoreConstructor("GBA")] - public GBA(CoreComm comm, byte[] file) - { - ServiceProvider = new BasicServiceProvider(this); - Tracer = new TraceBuffer - { - Header = " -Addr--- -Opcode- -Instruction------------------- -R0----- -R1----- -R2----- -R3----- -R4----- -R5----- -R6----- -R7----- -R8----- -R9----- -R10---- -R11---- -R12---- -R13(SP) -R14(LR) -R15(PC) -CPSR--- -SPSR---" - }; - - (ServiceProvider as BasicServiceProvider).Register(Tracer); - - CoreComm = comm; - - comm.VsyncNum = 262144; - comm.VsyncDen = 4389; - comm.NominalWidth = 240; - comm.NominalHeight = 160; - - byte[] bios = CoreComm.CoreFileProvider.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory."); - - if (bios.Length != 16384) - throw new InvalidDataException("GBA bios must be exactly 16384 bytes!"); - if (file.Length > 32 * 1024 * 1024) - throw new InvalidDataException("Rom file is too big! No GBA game is larger than 32MB"); - Init(); - LibMeteor.libmeteor_hardreset(); - LibMeteor.libmeteor_loadbios(bios, (uint)bios.Length); - LibMeteor.libmeteor_loadrom(file, (uint)file.Length); - - SetUpMemoryDomains(); - } - - public IEmulatorServiceProvider ServiceProvider { get; private set; } - - public IDictionary GetCpuFlagsAndRegisters() - { - var ret = new Dictionary(); - int[] data = new int[LibMeteor.regnames.Length]; - LibMeteor.libmeteor_getregs(data); - for (int i = 0; i < data.Length; i++) - ret.Add(LibMeteor.regnames[i], data[i]); - return ret; - } - - public static readonly ControllerDefinition GBAController = - new ControllerDefinition - { - Name = "GBA Controller", - BoolButtons = - { - "Up", "Down", "Left", "Right", "Start", "Select", "B", "A", "L", "R", "Power" - }, - FloatControls = - { - "Tilt X", "Tilt Y", "Tilt Z", "Light Sensor" - }, - FloatRanges = - { - new[] { -32767f, 0f, 32767f }, - new[] { -32767f, 0f, 32767f }, - new[] { -32767f, 0f, 32767f }, - new[] { 0f, 100f, 200f }, - } - }; - public ControllerDefinition ControllerDefinition { get { return GBAController; } } - public IController Controller { get; set; } - - public void FrameAdvance(bool render, bool rendersound = true) - { - Frame++; - IsLagFrame = true; - - if (Controller.IsPressed("Power")) - LibMeteor.libmeteor_hardreset(); - // due to the design of the tracing api, we have to poll whether it's active each frame - LibMeteor.libmeteor_settracecallback(Tracer.Enabled ? tracecallback : null); - if (!coredead) - LibMeteor.libmeteor_frameadvance(); - if (IsLagFrame) - LagCount++; - } - - public int Frame { get; private set; } - public int LagCount { get; set; } - public bool IsLagFrame { get; set; } - - private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem(); - - // TODO: optimize managed to unmanaged using the ActiveChanged event - public IInputCallbackSystem InputCallbacks { [FeatureNotImplemented]get { return _inputCallbacks; } } - - private ITraceable Tracer { get; set; } - - public string SystemId { get { return "GBA"; } } - public bool DeterministicEmulation { get { return true; } } - - // todo: information about the saveram type would be useful here. - public string BoardName { get { return null; } } - - public void ResetCounters() - { - Frame = 0; - LagCount = 0; - IsLagFrame = false; - } - - public CoreComm CoreComm { get; private set; } - - /// like libsnes, the library is single-instance - static GBA attachedcore; - /// hold pointer to message callback so it won't get GCed - LibMeteor.MessageCallback messagecallback; - /// hold pointer to input callback so it won't get GCed - LibMeteor.InputCallback inputcallback; - /// true if libmeteor aborted - bool coredead = false; - /// hold pointer to trace callback so it won't get GCed - LibMeteor.TraceCallback tracecallback; - - LibMeteor.Buttons GetInput() - { - InputCallbacks.Call(); - // libmeteor bitflips everything itself, so 0 == off, 1 == on - IsLagFrame = false; - LibMeteor.Buttons ret = 0; - if (Controller.IsPressed("Up")) ret |= LibMeteor.Buttons.BTN_UP; - if (Controller.IsPressed("Down")) ret |= LibMeteor.Buttons.BTN_DOWN; - if (Controller.IsPressed("Left")) ret |= LibMeteor.Buttons.BTN_LEFT; - if (Controller.IsPressed("Right")) ret |= LibMeteor.Buttons.BTN_RIGHT; - if (Controller.IsPressed("Select")) ret |= LibMeteor.Buttons.BTN_SELECT; - if (Controller.IsPressed("Start")) ret |= LibMeteor.Buttons.BTN_START; - if (Controller.IsPressed("B")) ret |= LibMeteor.Buttons.BTN_B; - if (Controller.IsPressed("A")) ret |= LibMeteor.Buttons.BTN_A; - if (Controller.IsPressed("L")) ret |= LibMeteor.Buttons.BTN_L; - if (Controller.IsPressed("R")) ret |= LibMeteor.Buttons.BTN_R; - return ret; - } - - #region messagecallbacks - - void PrintMessage(string msg, bool abort) - { - Console.Write(msg.Replace("\n", "\r\n")); - if (abort) - StopCore(msg); - } - - void StopCore(string msg) - { - coredead = true; - Console.WriteLine("Core stopped."); - for (int i = 0; i < soundbuffer.Length; i++) - soundbuffer[i] = 0; - - var gz = new System.IO.Compression.GZipStream( - new MemoryStream(Convert.FromBase64String(dispfont), false), - System.IO.Compression.CompressionMode.Decompress); - byte[] font = new byte[2048]; - gz.Read(font, 0, 2048); - gz.Dispose(); - - // cores aren't supposed to have bad dependencies like System.Drawing, right? - - int scx = 0; - int scy = 0; - - foreach (char c in msg) - { - if (scx == 240 || c == '\n') - { - scy += 8; - scx = 0; - } - if (scy == 160) - break; - if (c == '\r' || c == '\n') - continue; - if (c < 256 && c != ' ') - { - int fpos = c * 8; - for (int j = 0; j < 8; j++) - { - for (int i = 0; i < 8; i++) - { - if ((font[fpos] >> i & 1) != 0) - videobuffer[(scy + j) * 240 + scx + i] = unchecked((int)0xffff0000); - else - videobuffer[(scy + j) * 240 + scx + i] = unchecked((int)0xff000000); - } - fpos++; - } - } - scx += 8; - } - } - - const string dispfont = - "H4sICAInrFACAGZvby5yYXcARVU9q9RAFL2gjK8IT+0GDGoh1oGFGHDYQvwL2hoQroXhsdUqGGbxZ/gD" + - "bKys7BRhIZVYLgurIghvG3ksCPKKJfGcm1nfSTJn750792smWUmIr9++/vjmdYzDZlhuh1guFotpfiRH" + - "+dQ4n+aLxfOj/MgUR7mID8GLDMN2CftBgj54oEGG5ZuPH98sh93P3afJZHIzqGrw0e+/7LPs+OqVvuu7" + - "7vTZJb8J223Y+MtZHvLsstwuqlAVt+E1eh+DV0JU+s3mx3q9luCChjoIsVgI7Wg2kAHBQ1mkqPu6EBhk" + - "feYFcM5F0B0d9A74WtX2QvRtdU0SrBp6kaZpKIJ7XI341oV66sVp4TOtJS/L/IN+k8pnQkCbZb4QPEVB" + - "nYYhKB16JHZwbsZRDuBEDWsnEnQeTzSIz60CyHWV6cg19LOXjfb1TqKb1pSrzE0VHBUOvIed8ia3dZGb" + - "c96JM0ZhfgzPBPCbkWEPEs/4j+fO1kd2HM55Q0bf4PdmCW15E/HdFI1M7Dg/Z1xN64InguxqpGn6kkvF" + - "GaJ0Z32/6jrRkxjntFciMB79mTwPM5NLm0ffWac3iCb7kbx0XbfqzzqhEGBPLe2i9TVKmxGtiGPFIm1N" + - "tNj+ppMLDDl7Ywh1q62gPEUKlJX1Yw3k1uTo2P9sCseQW3Y80B4QLznrNwaOnbMGUDK9SNOvVgxt9vQH" + - "gj51IPn7SdlRFDt4MoarIGvKwyoFd6tV34CtAWTLRySiAZF5Oq5DcHvyAvuO8/FtLgZrRNcf9tlp8l/4" + - "sc64HPuhMnLmR/Z3jA/9cbAzexVj2CU59SPYD+rJyU6VfsiIh5NtL+j+/b7cyzmOu+op1wXrjzHXG2Ow" + - "Qikba6pbgwL0P7J4y89XDRsY7ZxEXLcmkydP/zz9NVv74P2N4yLVVaT8wIxDNv9NaRtG1pM5kinLVqKY" + - "ERndzXhOgOicGNe1yPLp5NUXnezAm99//3ymoX0xodQvsMKoE5GH18fr3aPx+v5ivPwFbt1KIx9VffYM" + - "g30GyUkPbV1zJgGzJpt+sWAxGEWSHwH4izg/hwAeBjEMw0GPweTDfNLyUWzSqdroXN+L9L1z1Gy3tsKe" + - "7Zbzpj/oOE+9P8iq5j/Nj/HUQK+S4omkuMJIaqD3g5+xQ2KwvIcEKshXE3YJNkfgjbg7/8YNLbV0Lqo6" + - "AFEaQqJmPlM7n+l9VeDHJTm57wGJPtjRwhg53+LD1DRnMvNFO9q3q9WqFfncnq6+tm7mszbzM4QziERe" + - "h7+LyO+zz8AYfQGerdf+P27cOBYaeUubt1RNU138q4wg74qiuFeGKjQA5BwOgxABACX8A6+GHm0ACAAA"; - - #endregion - - // Tracer refactor TODO - rehook up meteor, if it is worth it - //void Trace(string msg) - //{ - // Tracer.Put(msg); - //} - - private void Init() - { - if (attachedcore != null) - attachedcore.Dispose(); - - messagecallback = PrintMessage; - inputcallback = GetInput; - - // Tracer refactor TODO - rehook up meteor, if it is worth it - //tracecallback = Trace; // don't set this callback now, only set if enabled - LibMeteor.libmeteor_setmessagecallback(messagecallback); - LibMeteor.libmeteor_setkeycallback(inputcallback); - - LibMeteor.libmeteor_init(); - videobuffer = new int[240 * 160]; - videohandle = GCHandle.Alloc(videobuffer, GCHandleType.Pinned); - soundbuffer = new short[2048]; // nominal length of one frame is something like 1480 shorts? - soundhandle = GCHandle.Alloc(soundbuffer, GCHandleType.Pinned); - - if (!LibMeteor.libmeteor_setbuffers - (videohandle.AddrOfPinnedObject(), (uint)(sizeof(int) * videobuffer.Length), - soundhandle.AddrOfPinnedObject(), (uint)(sizeof(short) * soundbuffer.Length))) - throw new Exception("libmeteor_setbuffers() returned false??"); - - attachedcore = this; - } - - private bool disposed = false; - public void Dispose() - { - if (!disposed) - { - disposed = true; - videohandle.Free(); - soundhandle.Free(); - // guarantee crash if it gets accessed - LibMeteor.libmeteor_setbuffers(IntPtr.Zero, 240 * 160 * 4, IntPtr.Zero, 4); - messagecallback = null; - inputcallback = null; - tracecallback = null; - LibMeteor.libmeteor_setmessagecallback(messagecallback); - LibMeteor.libmeteor_setkeycallback(inputcallback); - LibMeteor.libmeteor_settracecallback(tracecallback); - _domainList.Clear(); - } - } - - #region ISoundProvider - - short[] soundbuffer; - GCHandle soundhandle; - - public void GetSamplesSync(out short[] samples, out int nsamp) - { - uint nbytes = LibMeteor.libmeteor_emptysound(); - samples = soundbuffer; - if (!coredead) - nsamp = (int)(nbytes / 4); - else - nsamp = 738; - } - - public void DiscardSamples() - { - LibMeteor.libmeteor_emptysound(); - } - - public bool CanProvideAsync - { - get { return false; } - } - - public void SetSyncMode(SyncSoundMode mode) - { - if (mode == SyncSoundMode.Async) - { - throw new NotSupportedException("Async mode is not supported."); - } - } - - public SyncSoundMode SyncMode - { - get { return SyncSoundMode.Sync; } - } - - public void GetSamplesAsync(short[] samples) - { - throw new InvalidOperationException("Async mode is not supported."); - } - - #endregion - } -} diff --git a/attic/GarboDev/Arm7Processor.cs b/attic/GarboDev/Arm7Processor.cs deleted file mode 100644 index 6b9c83c499..0000000000 --- a/attic/GarboDev/Arm7Processor.cs +++ /dev/null @@ -1,501 +0,0 @@ -namespace GarboDev -{ - using System; - using System.Collections.Generic; - using System.Text; - - public class Arm7Processor - { - private Memory memory = null; - private FastArmCore armCore = null; - private ThumbCore thumbCore = null; - private Dictionary breakpoints = null; - - private int cycles = 0; - private int timerCycles = 0; - private int soundCycles = 0; - - // CPU mode definitions - public const uint USR = 0x10; - public const uint FIQ = 0x11; - public const uint IRQ = 0x12; - public const uint SVC = 0x13; - public const uint ABT = 0x17; - public const uint UND = 0x1B; - public const uint SYS = 0x1F; - - // CPSR bit definitions - public const int N_BIT = 31; - public const int Z_BIT = 30; - public const int C_BIT = 29; - public const int V_BIT = 28; - public const int I_BIT = 7; - public const int F_BIT = 6; - public const int T_BIT = 5; - - public const uint N_MASK = (uint)(1U << N_BIT); - public const uint Z_MASK = (uint)(1U << Z_BIT); - public const uint C_MASK = (uint)(1U << C_BIT); - public const uint V_MASK = (uint)(1U << V_BIT); - public const uint I_MASK = (uint)(1U << I_BIT); - public const uint F_MASK = (uint)(1U << F_BIT); - public const uint T_MASK = (uint)(1U << T_BIT); - - // Standard registers - private uint[] registers = new uint[16]; - private uint cpsr = 0; - - // Banked registers - private uint[] bankedFIQ = new uint[7]; - private uint[] bankedIRQ = new uint[2]; - private uint[] bankedSVC = new uint[2]; - private uint[] bankedABT = new uint[2]; - private uint[] bankedUND = new uint[2]; - - // Saved CPSR's - private uint spsrFIQ = 0; - private uint spsrIRQ = 0; - private uint spsrSVC = 0; - private uint spsrABT = 0; - private uint spsrUND = 0; - - private ushort keyState; - - private bool breakpointHit = false; - private bool cpuHalted = false; - - public ushort KeyState - { - set { this.keyState = value; } - } - - public int Cycles - { - get { return this.cycles; } - set { this.cycles = value; } - } - - public bool ArmState - { - get { return (this.cpsr & Arm7Processor.T_MASK) != Arm7Processor.T_MASK; } - } - - public uint[] Registers - { - get { return this.registers; } - } - - public uint CPSR - { - get { return this.cpsr; } - set { this.cpsr = value; } - } - - public bool SPSRExists - { - get - { - switch (this.cpsr & 0x1F) - { - case USR: - case SYS: - return false; - case FIQ: - case SVC: - case ABT: - case IRQ: - case UND: - return true; - default: - return false; - } - } - } - - public uint SPSR - { - get - { - switch (this.cpsr & 0x1F) - { - case USR: - case SYS: - return 0xFFFFFFFF; - case FIQ: - return this.spsrFIQ; - case SVC: - return this.spsrSVC; - case ABT: - return this.spsrABT; - case IRQ: - return this.spsrIRQ; - case UND: - return this.spsrUND; - default: - throw new Exception("Unhandled CPSR state..."); - } - } - set - { - switch (this.cpsr & 0x1F) - { - case USR: - case SYS: - break; - case FIQ: - this.spsrFIQ = value; - break; - case SVC: - this.spsrSVC = value; - break; - case ABT: - this.spsrABT = value; - break; - case IRQ: - this.spsrIRQ = value; - break; - case UND: - this.spsrUND = value; - break; - default: - throw new Exception("Unhandled CPSR state..."); - } - } - } - - public Dictionary Breakpoints - { - get - { - return this.breakpoints; - } - } - - public bool BreakpointHit - { - get { return this.breakpointHit; } - set { this.breakpointHit = value; } - } - - public Arm7Processor(Memory memory) - { - this.memory = memory; - this.memory.Processor = this; - this.armCore = new FastArmCore(this, this.memory); - this.thumbCore = new ThumbCore(this, this.memory); - this.breakpoints = new Dictionary(); - this.breakpointHit = false; - } - - private void SwapRegsHelper(uint[] swapRegs) - { - for (int i = 14; i > 14 - swapRegs.Length; i--) - { - uint tmp = this.registers[i]; - this.registers[i] = swapRegs[swapRegs.Length - (14 - i) - 1]; - swapRegs[swapRegs.Length - (14 - i) - 1] = tmp; - } - } - - private void SwapRegisters(uint bank) - { - switch (bank & 0x1F) - { - case FIQ: - this.SwapRegsHelper(this.bankedFIQ); - break; - case SVC: - this.SwapRegsHelper(this.bankedSVC); - break; - case ABT: - this.SwapRegsHelper(this.bankedABT); - break; - case IRQ: - this.SwapRegsHelper(this.bankedIRQ); - break; - case UND: - this.SwapRegsHelper(this.bankedUND); - break; - } - } - - public void WriteCpsr(uint newCpsr) - { - if ((newCpsr & 0x1F) != (this.cpsr & 0x1F)) - { - // Swap out the old registers - this.SwapRegisters(this.cpsr); - // Swap in the new registers - this.SwapRegisters(newCpsr); - } - - this.cpsr = newCpsr; - } - - public void EnterException(uint mode, uint vector, bool interruptsDisabled, bool fiqDisabled) - { - uint oldCpsr = this.cpsr; - - if ((oldCpsr & Arm7Processor.T_MASK) != 0) - { - registers[15] += 2U; - } - - // Clear T bit, and set mode - uint newCpsr = (oldCpsr & ~0x3FU) | mode; - if (interruptsDisabled) newCpsr |= 1 << 7; - if (fiqDisabled) newCpsr |= 1 << 6; - this.WriteCpsr(newCpsr); - - this.SPSR = oldCpsr; - registers[14] = registers[15]; - registers[15] = vector; - - this.ReloadQueue(); - } - - public void RequestIrq(int irq) - { - ushort iflag = Memory.ReadU16(this.memory.IORam, Memory.IF); - iflag |= (ushort)(1 << irq); - Memory.WriteU16(this.memory.IORam, Memory.IF, iflag); - } - - public void FireIrq() - { - ushort ime = Memory.ReadU16(this.memory.IORam, Memory.IME); - ushort ie = Memory.ReadU16(this.memory.IORam, Memory.IE); - ushort iflag = Memory.ReadU16(this.memory.IORam, Memory.IF); - - if ((ie & (iflag)) != 0 && (ime & 1) != 0 && (this.cpsr & (1 << 7)) == 0) - { - // Off to the irq exception vector - this.EnterException(Arm7Processor.IRQ, 0x18, true, false); - } - } - - public void Reset(bool skipBios) - { - this.breakpointHit = false; - this.cpuHalted = false; - - // Default to ARM state - this.cycles = 0; - this.timerCycles = 0; - this.soundCycles = 0; - - this.bankedSVC[0] = 0x03007FE0; - this.bankedIRQ[0] = 0x03007FA0; - - this.cpsr = SYS; - this.spsrSVC = this.cpsr; - for (int i = 0; i < 15; i++) this.registers[i] = 0; - - if (skipBios) - { - this.registers[15] = 0x8000000; - } - else - { - this.registers[15] = 0; - } - - this.armCore.BeginExecution(); - } - - public void Halt() - { - this.cpuHalted = true; - this.cycles = 0; - } - - public void Step() - { - this.breakpointHit = false; - - if ((this.cpsr & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbCore.Step(); - } - else - { - this.armCore.Step(); - } - - this.UpdateTimers(); - } - - public void ReloadQueue() - { - if ((this.cpsr & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbCore.BeginExecution(); - } - else - { - this.armCore.BeginExecution(); - } - } - - private void UpdateTimer(int timer, int cycles, bool countUp) - { - ushort control = Memory.ReadU16(this.memory.IORam, Memory.TM0CNT + (uint)(timer * 4)); - - // Make sure timer is enabled, or count up is disabled - if ((control & (1 << 7)) == 0) return; - if (!countUp && (control & (1 << 2)) != 0) return; - - if (!countUp) - { - switch (control & 3) - { - case 0: cycles *= 1 << 10; break; - case 1: cycles *= 1 << 4; break; - case 2: cycles *= 1 << 2; break; - // Don't need to do anything for case 3 - } - } - - this.memory.TimerCnt[timer] += (uint)cycles; - uint timerCnt = this.memory.TimerCnt[timer] >> 10; - - if (timerCnt > 0xffff) - { - ushort soundCntX = Memory.ReadU16(this.memory.IORam, Memory.SOUNDCNT_X); - if ((soundCntX & (1 << 7)) != 0) - { - ushort soundCntH = Memory.ReadU16(this.memory.IORam, Memory.SOUNDCNT_H); - if (timer == ((soundCntH >> 10) & 1)) - { - // FIFO A overflow - this.memory.SoundManager.DequeueA(); - if (this.memory.SoundManager.QueueSizeA < 16) - { - this.memory.FifoDma(1); - // TODO - if (this.memory.SoundManager.QueueSizeA < 16) - { - } - } - } - if (timer == ((soundCntH >> 14) & 1)) - { - // FIFO B overflow - this.memory.SoundManager.DequeueB(); - if (this.memory.SoundManager.QueueSizeB < 16) - { - this.memory.FifoDma(2); - } - } - } - - // Overflow, attempt to fire IRQ - if ((control & (1 << 6)) != 0) - { - this.RequestIrq(3 + timer); - } - - if (timer < 3) - { - ushort control2 = Memory.ReadU16(this.memory.IORam, Memory.TM0CNT + (uint)((timer + 1) * 4)); - if ((control2 & (1 << 2)) != 0) - { - // Count-up - this.UpdateTimer(timer + 1, (int)((timerCnt >> 16) << 10), true); - } - } - - // Reset the original value - uint count = Memory.ReadU16(this.memory.IORam, Memory.TM0D + (uint)(timer * 4)); - this.memory.TimerCnt[timer] = count << 10; - } - } - - public void UpdateTimers() - { - int cycles = this.timerCycles - this.cycles; - - for (int i = 0; i < 4; i++) - { - this.UpdateTimer(i, cycles, false); - } - - this.timerCycles = this.cycles; - } - - public void UpdateKeyState() - { - ushort KEYCNT = this.memory.ReadU16Debug(Memory.REG_BASE + Memory.KEYCNT); - - if ((KEYCNT & (1 << 14)) != 0) - { - if ((KEYCNT & (1 << 15)) != 0) - { - KEYCNT &= 0x3FF; - if (((~this.keyState) & KEYCNT) == KEYCNT) - this.RequestIrq(12); - } - else - { - KEYCNT &= 0x3FF; - if (((~this.keyState) & KEYCNT) != 0) - this.RequestIrq(12); - } - } - - this.memory.KeyState = this.keyState; - } - - public void UpdateSound() - { - this.memory.SoundManager.Mix(this.soundCycles); - this.soundCycles = 0; - } - - public void Execute(int cycles) - { - this.cycles += cycles; - this.timerCycles += cycles; - this.soundCycles += cycles; - this.breakpointHit = false; - - if (this.cpuHalted) - { - ushort ie = Memory.ReadU16(this.memory.IORam, Memory.IE); - ushort iflag = Memory.ReadU16(this.memory.IORam, Memory.IF); - - if ((ie & iflag) != 0) - { - this.cpuHalted = false; - } - else - { - this.cycles = 0; - this.UpdateTimers(); - this.UpdateSound(); - return; - } - } - - while (this.cycles > 0) - { - if ((this.cpsr & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbCore.Execute(); - } - else - { - this.armCore.Execute(); - } - - this.UpdateTimers(); - this.UpdateSound(); - - if (this.breakpointHit) - { - break; - } - } - } - } -} \ No newline at end of file diff --git a/attic/GarboDev/ArmCore.cs b/attic/GarboDev/ArmCore.cs deleted file mode 100644 index 5eda1e7a5d..0000000000 --- a/attic/GarboDev/ArmCore.cs +++ /dev/null @@ -1,1273 +0,0 @@ -//#define ARM_DEBUG - -namespace GarboDev -{ - using System; - - public class ArmCore - { - private const uint COND_EQ = 0; // Z set - private const uint COND_NE = 1; // Z clear - private const uint COND_CS = 2; // C set - private const uint COND_CC = 3; // C clear - private const uint COND_MI = 4; // N set - private const uint COND_PL = 5; // N clear - private const uint COND_VS = 6; // V set - private const uint COND_VC = 7; // V clear - private const uint COND_HI = 8; // C set and Z clear - private const uint COND_LS = 9; // C clear or Z set - private const uint COND_GE = 10; // N equals V - private const uint COND_LT = 11; // N not equal to V - private const uint COND_GT = 12; // Z clear AND (N equals V) - private const uint COND_LE = 13; // Z set OR (N not equal to V) - private const uint COND_AL = 14; // Always - private const uint COND_NV = 15; // Never execute - - private const uint OP_AND = 0x0; - private const uint OP_EOR = 0x1; - private const uint OP_SUB = 0x2; - private const uint OP_RSB = 0x3; - private const uint OP_ADD = 0x4; - private const uint OP_ADC = 0x5; - private const uint OP_SBC = 0x6; - private const uint OP_RSC = 0x7; - private const uint OP_TST = 0x8; - private const uint OP_TEQ = 0x9; - private const uint OP_CMP = 0xA; - private const uint OP_CMN = 0xB; - private const uint OP_ORR = 0xC; - private const uint OP_MOV = 0xD; - private const uint OP_BIC = 0xE; - private const uint OP_MVN = 0xF; - - private delegate void ExecuteInstruction(); - private ExecuteInstruction[] NormalOps = null; - - private Arm7Processor parent; - private Memory memory; - private uint[] registers; - - private uint instructionQueue; - private uint curInstruction; - - // CPU flags - private uint zero, carry, negative, overflow; - private uint shifterCarry; - - private bool thumbMode; - - public ArmCore(Arm7Processor parent, Memory memory) - { - this.parent = parent; - this.memory = memory; - this.registers = this.parent.Registers; - - this.NormalOps = new ExecuteInstruction[8] - { - this.DataProcessing, - this.DataProcessingImmed, - this.LoadStoreImmediate, - this.LoadStoreRegister, - this.LoadStoreMultiple, - this.Branch, - this.CoprocessorLoadStore, - this.SoftwareInterrupt - }; - } - - public void BeginExecution() - { - this.FlushQueue(); - } - - public void Step() - { - this.UnpackFlags(); - - this.curInstruction = this.instructionQueue; - this.instructionQueue = this.memory.ReadU32(registers[15]); - registers[15] += 4; - - uint cond = 0; - switch (this.curInstruction >> 28) - { - case COND_AL: cond = 1; break; - case COND_EQ: cond = zero; break; - case COND_NE: cond = 1 - zero; break; - case COND_CS: cond = carry; break; - case COND_CC: cond = 1 - carry; break; - case COND_MI: cond = negative; break; - case COND_PL: cond = 1 - negative; break; - case COND_VS: cond = overflow; break; - case COND_VC: cond = 1 - overflow; break; - case COND_HI: cond = carry & (1 - zero); break; - case COND_LS: cond = (1 - carry) | zero; break; - case COND_GE: cond = (1 - negative) ^ overflow; break; - case COND_LT: cond = negative ^ overflow; break; - case COND_GT: cond = (1 - zero) & (negative ^ (1 - overflow)); break; - case COND_LE: cond = (negative ^ overflow) | zero; break; - } - - if (cond == 1) - { - // Execute the instruction - this.NormalOps[(curInstruction >> 25) & 0x7](); - } - - this.parent.Cycles -= this.memory.WaitCycles; - - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.parent.ReloadQueue(); - } - - this.PackFlags(); - } - - public void Execute() - { - this.UnpackFlags(); - this.thumbMode = false; - - while (this.parent.Cycles > 0) - { - this.curInstruction = this.instructionQueue; - this.instructionQueue = this.memory.ReadU32Aligned(registers[15]); - registers[15] += 4; - - if ((this.curInstruction >> 28) == COND_AL) - { - this.NormalOps[(curInstruction >> 25) & 0x7](); - } - else - { - uint cond = 0; - switch (this.curInstruction >> 28) - { - case COND_EQ: cond = zero; break; - case COND_NE: cond = 1 - zero; break; - case COND_CS: cond = carry; break; - case COND_CC: cond = 1 - carry; break; - case COND_MI: cond = negative; break; - case COND_PL: cond = 1 - negative; break; - case COND_VS: cond = overflow; break; - case COND_VC: cond = 1 - overflow; break; - case COND_HI: cond = carry & (1 - zero); break; - case COND_LS: cond = (1 - carry) | zero; break; - case COND_GE: cond = (1 - negative) ^ overflow; break; - case COND_LT: cond = negative ^ overflow; break; - case COND_GT: cond = (1 - zero) & (negative ^ (1 - overflow)); break; - case COND_LE: cond = (negative ^ overflow) | zero; break; - } - - if (cond == 1) - { - // Execute the instruction - this.NormalOps[(curInstruction >> 25) & 0x7](); - } - } - - this.parent.Cycles -= this.memory.WaitCycles; - - if (this.thumbMode) - { - this.parent.ReloadQueue(); - break; - } - -#if ARM_DEBUG - // Check the current PC - if (this.parent.Breakpoints.ContainsKey(registers[15] - 4U)) - { - this.parent.BreakpointHit = true; - break; - } -#endif - } - - this.PackFlags(); - } - - #region Barrel Shifter - private const uint SHIFT_LSL = 0; - private const uint SHIFT_LSR = 1; - private const uint SHIFT_ASR = 2; - private const uint SHIFT_ROR = 3; - - private uint BarrelShifter(uint shifterOperand) - { - uint type = (shifterOperand >> 5) & 0x3; - - bool registerShift = (shifterOperand & (1 << 4)) == (1 << 4); - - uint rm = registers[shifterOperand & 0xF]; - - int amount; - if (registerShift) - { - uint rs = (shifterOperand >> 8) & 0xF; - if (rs == 15) - { - amount = (int)((registers[rs] + 0x4) & 0xFF); - } - else - { - amount = (int)(registers[rs] & 0xFF); - } - - if ((shifterOperand & 0xF) == 15) - { - rm += 4; - } - } - else - { - amount = (int)((shifterOperand >> 7) & 0x1F); - } - - if (registerShift) - { - if (amount == 0) - { - this.shifterCarry = this.carry; - return rm; - } - - switch (type) - { - case SHIFT_LSL: - if (amount < 32) - { - this.shifterCarry = (rm >> (32 - amount)) & 1; - return rm << amount; - } - else if (amount == 32) - { - this.shifterCarry = rm & 1; - return 0; - } - else - { - this.shifterCarry = 0; - return 0; - } - - case SHIFT_LSR: - if (amount < 32) - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return rm >> amount; - } - else if (amount == 32) - { - this.shifterCarry = (rm >> 31) & 1; - return 0; - } - else - { - this.shifterCarry = 0; - return 0; - } - - case SHIFT_ASR: - if (amount >= 32) - { - if ((rm & (1 << 31)) == 0) - { - this.shifterCarry = 0; - return 0; - } - else - { - this.shifterCarry = 1; - return 0xFFFFFFFF; - } - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return (uint)(((int)rm) >> amount); - } - - case SHIFT_ROR: - if ((amount & 0x1F) == 0) - { - this.shifterCarry = (rm >> 31) & 1; - return rm; - } - else - { - amount &= 0x1F; - this.shifterCarry = (rm >> amount) & 1; - return (rm >> amount) | (rm << (32 - amount)); - } - } - } - else - { - switch (type) - { - case SHIFT_LSL: - if (amount == 0) - { - this.shifterCarry = this.carry; - return rm; - } - else - { - this.shifterCarry = (rm >> (32 - amount)) & 1; - return rm << amount; - } - - case SHIFT_LSR: - if (amount == 0) - { - this.shifterCarry = (rm >> 31) & 1; - return 0; - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return rm >> amount; - } - - case SHIFT_ASR: - if (amount == 0) - { - if ((rm & (1 << 31)) == 0) - { - this.shifterCarry = 0; - return 0; - } - else - { - this.shifterCarry = 1; - return 0xFFFFFFFF; - } - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return (uint)(((int)rm) >> amount); - } - - case SHIFT_ROR: - if (amount == 0) - { - // Actually an RRX - this.shifterCarry = rm & 1; - return (this.carry << 31) | (rm >> 1); - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return (rm >> amount) | (rm << (32 - amount)); - } - } - } - - // Should never happen... - throw new Exception("Barrel Shifter has messed up."); - } - #endregion - - #region Flag helpers - public void OverflowCarryAdd(uint a, uint b, uint r) - { - overflow = ((a & b & ~r) | (~a & ~b & r)) >> 31; - carry = ((a & b) | (a & ~r) | (b & ~r)) >> 31; - } - - public void OverflowCarrySub(uint a, uint b, uint r) - { - overflow = ((a & ~b & ~r) | (~a & b & r)) >> 31; - carry = ((a & ~b) | (a & ~r) | (~b & ~r)) >> 31; - } - #endregion - - #region Opcodes - private void DoDataProcessing(uint shifterOperand) - { - uint rn = (this.curInstruction >> 16) & 0xF; - uint rd = (this.curInstruction >> 12) & 0xF; - uint alu; - - bool registerShift = (this.curInstruction & (1 << 4)) == (1 << 4); - if (rn == 15 && ((this.curInstruction >> 25) & 0x7) == 0 && registerShift) - { - rn = registers[rn] + 4; - } - else - { - rn = registers[rn]; - } - - uint opcode = (this.curInstruction >> 21) & 0xF; - - if (((this.curInstruction >> 20) & 1) == 1) - { - // Set flag bit set - switch (opcode) - { - case OP_ADC: - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - break; - - case OP_ADD: - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - break; - - case OP_AND: - registers[rd] = rn & shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_BIC: - registers[rd] = rn & ~shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_CMN: - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case OP_CMP: - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case OP_EOR: - registers[rd] = rn ^ shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_MOV: - registers[rd] = shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_MVN: - registers[rd] = ~shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_ORR: - registers[rd] = rn | shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_RSB: - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - break; - - case OP_RSC: - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - break; - - case OP_SBC: - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - break; - - case OP_SUB: - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - break; - - case OP_TEQ: - alu = rn ^ shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_TST: - alu = rn & shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - } - - if (rd == 15) - { - // Prevent writing if no SPSR exists (this will be true for USER or SYSTEM mode) - if (this.parent.SPSRExists) this.parent.WriteCpsr(this.parent.SPSR); - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - - // Otherwise, flush the instruction queue - this.FlushQueue(); - } - } - else - { - // Set flag bit not set - switch (opcode) - { - case OP_ADC: registers[rd] = rn + shifterOperand + carry; break; - case OP_ADD: registers[rd] = rn + shifterOperand; break; - case OP_AND: registers[rd] = rn & shifterOperand; break; - case OP_BIC: registers[rd] = rn & ~shifterOperand; break; - case OP_EOR: registers[rd] = rn ^ shifterOperand; break; - case OP_MOV: registers[rd] = shifterOperand; break; - case OP_MVN: registers[rd] = ~shifterOperand; break; - case OP_ORR: registers[rd] = rn | shifterOperand; break; - case OP_RSB: registers[rd] = shifterOperand - rn; break; - case OP_RSC: registers[rd] = shifterOperand - rn - (1U - carry); break; - case OP_SBC: registers[rd] = rn - shifterOperand - (1U - carry); break; - case OP_SUB: registers[rd] = rn - shifterOperand; break; - - case OP_CMN: - // MSR SPSR, shifterOperand - if ((this.curInstruction & (1 << 16)) == 1 << 16 && this.parent.SPSRExists) - { - this.parent.SPSR &= 0xFFFFFF00; - this.parent.SPSR |= shifterOperand & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17 && this.parent.SPSRExists) - { - this.parent.SPSR &= 0xFFFF00FF; - this.parent.SPSR |= shifterOperand & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18 && this.parent.SPSRExists) - { - this.parent.SPSR &= 0xFF00FFFF; - this.parent.SPSR |= shifterOperand & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19 && this.parent.SPSRExists) - { - this.parent.SPSR &= 0x00FFFFFF; - this.parent.SPSR |= shifterOperand & 0xFF000000; - } - - // Queue will be flushed since rd == 15, so adjust the PC - registers[15] -= 4; - break; - - case OP_CMP: - // MRS rd, SPSR - if (this.parent.SPSRExists) registers[rd] = this.parent.SPSR; - break; - - case OP_TEQ: - if (((this.curInstruction >> 4) & 0xf) == 1) - { - // BX - uint rm = this.curInstruction & 0xf; - - this.PackFlags(); - - this.parent.CPSR &= ~Arm7Processor.T_MASK; - this.parent.CPSR |= (registers[rm] & 1) << Arm7Processor.T_BIT; - - registers[15] = registers[rm] & (~1U); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - - // Queue will be flushed later because rd == 15 - } - else if (((this.curInstruction >> 4) & 0xf) == 0) - { - // MSR CPSR, shifterOperand - bool userMode = (this.parent.CPSR & 0x1F) == Arm7Processor.USR; - - this.PackFlags(); - - uint tmpCPSR = this.parent.CPSR; - - if ((this.curInstruction & (1 << 16)) == 1 << 16 && !userMode) - { - tmpCPSR &= 0xFFFFFF00; - tmpCPSR |= shifterOperand & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17 && !userMode) - { - tmpCPSR &= 0xFFFF00FF; - tmpCPSR |= shifterOperand & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18 && !userMode) - { - tmpCPSR &= 0xFF00FFFF; - tmpCPSR |= shifterOperand & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - tmpCPSR &= 0x00FFFFFF; - tmpCPSR |= shifterOperand & 0xFF000000; - } - - this.parent.WriteCpsr(tmpCPSR); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - - // Queue will be flushed since rd == 15, so adjust the PC - registers[15] -= 4; - } - break; - - case OP_TST: - // MRS rd, CPSR - this.PackFlags(); - registers[rd] = this.parent.CPSR; - break; - } - - if (rd == 15) - { - // Flush the queue - this.FlushQueue(); - } - } - } - - private void DataProcessing() - { - // Special instruction - switch ((this.curInstruction >> 4) & 0xF) - { - case 0x9: - // Multiply or swap instructions - this.MultiplyOrSwap(); - return; - case 0xB: - // Load/Store Unsigned halfword - this.LoadStoreHalfword(); - return; - case 0xD: - // Load/Store Signed byte - this.LoadStoreHalfword(); - return; - case 0xF: - // Load/Store Signed halfword - this.LoadStoreHalfword(); - return; - } - - this.DoDataProcessing(this.BarrelShifter(this.curInstruction)); - } - - private void DataProcessingImmed() - { - uint immed = this.curInstruction & 0xFF; - int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2); - - immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount)); - - if (rotateAmount == 0) - { - this.shifterCarry = this.carry; - } - else - { - this.shifterCarry = (immed >> 31) & 1; - } - - this.DoDataProcessing(immed); - } - - private void LoadStore(uint offset) - { - uint rn = (this.curInstruction >> 16) & 0xF; - uint rd = (this.curInstruction >> 12) & 0xF; - - uint address = registers[rn]; - - bool preIndexed = (this.curInstruction & (1 << 24)) == 1 << 24; - bool byteTransfer = (this.curInstruction & (1 << 22)) == 1 << 22; - bool writeback = (this.curInstruction & (1 << 21)) == 1 << 21; - - // Add or subtract offset - if ((this.curInstruction & (1 << 23)) != 1 << 23) offset = (uint)-offset; - - if (preIndexed) - { - address += offset; - - if (writeback) - { - registers[rn] = address; - } - } - - if ((this.curInstruction & (1 << 20)) == 1 << 20) - { - // Load - if (byteTransfer) - { - registers[rd] = this.memory.ReadU8(address); - } - else - { - registers[rd] = this.memory.ReadU32(address); - } - - // ARM9 fix here - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (!preIndexed) - { - if (rn != rd) - registers[rn] = address + offset; - } - } - else - { - // Store - uint amount = registers[rd]; - if (rd == 15) amount += 4; - - if (byteTransfer) - { - this.memory.WriteU8(address, (byte)(amount & 0xFF)); - } - else - { - this.memory.WriteU32(address, amount); - } - - if (!preIndexed) - { - registers[rn] = address + offset; - } - } - } - - private void LoadStoreImmediate() - { - this.LoadStore(this.curInstruction & 0xFFF); - } - - private void LoadStoreRegister() - { - // The barrel shifter expects a 0 in bit 4 for immediate shifts, this is implicit in - // the meaning of the instruction, so it is fine - this.LoadStore(this.BarrelShifter(this.curInstruction)); - } - - private void LoadStoreMultiple() - { - uint rn = (this.curInstruction >> 16) & 0xF; - - this.PackFlags(); - uint curCpsr = this.parent.CPSR; - - bool preIncrement = (this.curInstruction & (1 << 24)) != 0; - bool up = (this.curInstruction & (1 << 23)) != 0; - bool writeback = (this.curInstruction & (1 << 21)) != 0; - - uint address; - uint bitsSet = 0; - for (int i = 0; i < 16; i++) if (((this.curInstruction >> i) & 1) != 0) bitsSet++; - - if (preIncrement) - { - if (up) - { - // Increment before - address = this.registers[rn] + 4; - if (writeback) this.registers[rn] += bitsSet * 4; - } - else - { - // Decrement before - address = this.registers[rn] - (bitsSet * 4); - if (writeback) this.registers[rn] -= bitsSet * 4; - } - } - else - { - if (up) - { - // Increment after - address = this.registers[rn]; - if (writeback) this.registers[rn] += bitsSet * 4; - } - else - { - // Decrement after - address = this.registers[rn] - (bitsSet * 4) + 4; - if (writeback) this.registers[rn] -= bitsSet * 4; - } - } - - if ((this.curInstruction & (1 << 20)) != 0) - { - if ((this.curInstruction & (1 << 22)) != 0 && ((this.curInstruction >> 15) & 1) == 0) - { - // Switch to user mode temporarily - this.parent.WriteCpsr((curCpsr & ~0x1FU) | Arm7Processor.USR); - } - - // Load multiple - for (int i = 0; i < 15; i++) - { - if (((this.curInstruction >> i) & 1) != 1) continue; - this.registers[i] = this.memory.ReadU32Aligned(address & (~0x3U)); - address += 4; - } - - if (((this.curInstruction >> 15) & 1) == 1) - { - // Arm9 fix here - - this.registers[15] = this.memory.ReadU32Aligned(address & (~0x3U)); - - if ((this.curInstruction & (1 << 22)) != 0) - { - // Load the CPSR from the SPSR - if (this.parent.SPSRExists) - { - this.parent.WriteCpsr(this.parent.SPSR); - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - this.registers[15] &= ~0x1U; - return; - } - } - } - - this.registers[15] &= ~0x3U; - this.FlushQueue(); - } - else - { - if ((this.curInstruction & (1 << 22)) != 0) - { - // Switch back to the correct mode - this.parent.WriteCpsr(curCpsr); - this.UnpackFlags(); - - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - } - } - } - else - { - if ((this.curInstruction & (1 << 22)) != 0) - { - // Switch to user mode temporarily - this.parent.WriteCpsr((curCpsr & ~0x1FU) | Arm7Processor.USR); - } - - if (((this.curInstruction >> (int)rn) & 1) != 0 && writeback && - (this.curInstruction & ~(0xFFFFFFFF << (int)rn)) == 0) - { - // If the lowest register is also the writeback, we use the original value - // Does anybody do this???? - throw new Exception("Unhandled STM state"); - } - else - { - // Store multiple - for (int i = 0; i < 15; i++) - { - if (((this.curInstruction >> i) & 1) == 0) continue; - this.memory.WriteU32(address, this.registers[i]); - address += 4; - } - - if (((this.curInstruction >> 15) & 1) != 0) - { - this.memory.WriteU32(address, this.registers[15] + 4U); - } - } - - if ((this.curInstruction & (1 << 22)) != 0) - { - // Switch back to the correct mode - this.parent.WriteCpsr(curCpsr); - this.UnpackFlags(); - } - } - } - - private void Branch() - { - if ((this.curInstruction & (1 << 24)) != 0) - { - this.registers[14] = (this.registers[15] - 4U) & ~3U; - } - - uint branchOffset = this.curInstruction & 0x00FFFFFF; - if (branchOffset >> 23 == 1) branchOffset |= 0xFF000000; - - this.registers[15] += branchOffset << 2; - - this.FlushQueue(); - } - - private void CoprocessorLoadStore() - { - throw new Exception("Unhandled opcode - coproc load/store"); - } - - private void SoftwareInterrupt() - { - // Adjust PC for prefetch - this.registers[15] -= 4U; - this.parent.EnterException(Arm7Processor.SVC, 0x8, false, false); - } - - private void MultiplyOrSwap() - { - if ((this.curInstruction & (1 << 24)) == 1 << 24) - { - // Swap instruction - uint rn = (this.curInstruction >> 16) & 0xF; - uint rd = (this.curInstruction >> 12) & 0xF; - uint rm = this.curInstruction & 0xF; - - if ((this.curInstruction & (1 << 22)) != 0) - { - // SWPB - byte tmp = this.memory.ReadU8(registers[rn]); - this.memory.WriteU8(registers[rn], (byte)(registers[rm] & 0xFF)); - registers[rd] = tmp; - } - else - { - // SWP - uint tmp = this.memory.ReadU32(registers[rn]); - this.memory.WriteU32(registers[rn], registers[rm]); - registers[rd] = tmp; - } - } - else - { - // Multiply instruction - switch ((this.curInstruction >> 21) & 0x7) - { - case 0: - case 1: - { - // Multiply/Multiply + Accumulate - uint rd = (this.curInstruction >> 16) & 0xF; - uint rn = registers[(this.curInstruction >> 12) & 0xF]; - uint rs = (this.curInstruction >> 8) & 0xF; - uint rm = this.curInstruction & 0xF; - - int cycles = 4; - // Multiply cycle calculations - if ((registers[rs] & 0xFFFFFF00) == 0 || (registers[rs] & 0xFFFFFF00) == 0xFFFFFF00) - { - cycles = 1; - } - else if ((registers[rs] & 0xFFFF0000) == 0 || (registers[rs] & 0xFFFF0000) == 0xFFFF0000) - { - cycles = 2; - } - else if ((registers[rs] & 0xFF000000) == 0 || (registers[rs] & 0xFF000000) == 0xFF000000) - { - cycles = 3; - } - - registers[rd] = registers[rs] * registers[rm]; - this.parent.Cycles -= cycles; - - if ((this.curInstruction & (1 << 21)) == 1 << 21) - { - registers[rd] += rn; - this.parent.Cycles -= 1; - } - - if ((this.curInstruction & (1 << 20)) == 1 << 20) - { - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - break; - } - - case 2: - case 3: - throw new Exception("Invalid multiply"); - - case 4: - case 5: - case 6: - case 7: - { - // Multiply/Signed Multiply Long - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - uint rs = (this.curInstruction >> 8) & 0xF; - uint rm = this.curInstruction & 0xF; - - int cycles = 5; - // Multiply cycle calculations - if ((registers[rs] & 0xFFFFFF00) == 0 || (registers[rs] & 0xFFFFFF00) == 0xFFFFFF00) - { - cycles = 2; - } - else if ((registers[rs] & 0xFFFF0000) == 0 || (registers[rs] & 0xFFFF0000) == 0xFFFF0000) - { - cycles = 3; - } - else if ((registers[rs] & 0xFF000000) == 0 || (registers[rs] & 0xFF000000) == 0xFF000000) - { - cycles = 4; - } - - this.parent.Cycles -= cycles; - - switch ((this.curInstruction >> 21) & 0x3) - { - case 0: - { - // UMULL - ulong result = ((ulong)registers[rm]) * registers[rs]; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - break; - } - case 1: - { - // UMLAL - ulong accum = (((ulong)registers[rdhi]) << 32) | registers[rdlo]; - ulong result = ((ulong)registers[rm]) * registers[rs]; - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - break; - } - case 2: - { - // SMULL - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - break; - } - case 3: - { - // SMLAL - long accum = (((long)((int)registers[rdhi])) << 32) | registers[rdlo]; - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - break; - } - } - - if ((this.curInstruction & (1 << 20)) == 1 << 20) - { - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - } - break; - } - } - } - } - - private void LoadStoreHalfword() - { - uint rn = (this.curInstruction >> 16) & 0xF; - uint rd = (this.curInstruction >> 12) & 0xF; - - uint address = registers[rn]; - - bool preIndexed = (this.curInstruction & (1 << 24)) != 0; - bool byteTransfer = (this.curInstruction & (1 << 5)) == 0; - bool signedTransfer = (this.curInstruction & (1 << 6)) != 0; - bool writeback = (this.curInstruction & (1 << 21)) != 0; - - uint offset; - if ((this.curInstruction & (1 << 22)) != 0) - { - // Immediate offset - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - } - else - { - // Register offset - offset = this.registers[this.curInstruction & 0xF]; - } - - // Add or subtract offset - if ((this.curInstruction & (1 << 23)) == 0) offset = (uint)-offset; - - if (preIndexed) - { - address += offset; - - if (writeback) - { - registers[rn] = address; - } - } - - if ((this.curInstruction & (1 << 20)) != 0) - { - // Load - if (byteTransfer) - { - if (signedTransfer) - { - registers[rd] = this.memory.ReadU8(address); - if ((registers[rd] & 0x80) != 0) - { - registers[rd] |= 0xFFFFFF00; - } - } - else - { - registers[rd] = this.memory.ReadU8(address); - } - } - else - { - if (signedTransfer) - { - registers[rd] = this.memory.ReadU16(address); - if ((registers[rd] & 0x8000) != 0) - { - registers[rd] |= 0xFFFF0000; - } - } - else - { - registers[rd] = this.memory.ReadU16(address); - } - } - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (!preIndexed) - { - if (rn != rd) - registers[rn] = address + offset; - } - } - else - { - // Store - if (byteTransfer) - { - this.memory.WriteU8(address, (byte)(registers[rd] & 0xFF)); - } - else - { - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - } - - if (!preIndexed) - { - registers[rn] = address + offset; - } - } - } - #endregion Opcodes - - private void PackFlags() - { - this.parent.CPSR &= 0x0FFFFFFF; - this.parent.CPSR |= this.negative << Arm7Processor.N_BIT; - this.parent.CPSR |= this.zero << Arm7Processor.Z_BIT; - this.parent.CPSR |= this.carry << Arm7Processor.C_BIT; - this.parent.CPSR |= this.overflow << Arm7Processor.V_BIT; - } - - private void UnpackFlags() - { - this.negative = (this.parent.CPSR >> Arm7Processor.N_BIT) & 1; - this.zero = (this.parent.CPSR >> Arm7Processor.Z_BIT) & 1; - this.carry = (this.parent.CPSR >> Arm7Processor.C_BIT) & 1; - this.overflow = (this.parent.CPSR >> Arm7Processor.V_BIT) & 1; - } - - private void FlushQueue() - { - this.instructionQueue = this.memory.ReadU32(registers[15]); - registers[15] += 4; - } - } -} \ No newline at end of file diff --git a/attic/GarboDev/FastArmCore.cs b/attic/GarboDev/FastArmCore.cs deleted file mode 100644 index c944036fb1..0000000000 --- a/attic/GarboDev/FastArmCore.cs +++ /dev/null @@ -1,9916 +0,0 @@ -//#define ARM_DEBUG - -namespace GarboDev -{ - using System; - - public partial class FastArmCore - { - private const uint COND_EQ = 0; // Z set - private const uint COND_NE = 1; // Z clear - private const uint COND_CS = 2; // C set - private const uint COND_CC = 3; // C clear - private const uint COND_MI = 4; // N set - private const uint COND_PL = 5; // N clear - private const uint COND_VS = 6; // V set - private const uint COND_VC = 7; // V clear - private const uint COND_HI = 8; // C set and Z clear - private const uint COND_LS = 9; // C clear or Z set - private const uint COND_GE = 10; // N equals V - private const uint COND_LT = 11; // N not equal to V - private const uint COND_GT = 12; // Z clear AND (N equals V) - private const uint COND_LE = 13; // Z set OR (N not equal to V) - private const uint COND_AL = 14; // Always - private const uint COND_NV = 15; // Never execute - - private const uint OP_AND = 0x0; - private const uint OP_EOR = 0x1; - private const uint OP_SUB = 0x2; - private const uint OP_RSB = 0x3; - private const uint OP_ADD = 0x4; - private const uint OP_ADC = 0x5; - private const uint OP_SBC = 0x6; - private const uint OP_RSC = 0x7; - private const uint OP_TST = 0x8; - private const uint OP_TEQ = 0x9; - private const uint OP_CMP = 0xA; - private const uint OP_CMN = 0xB; - private const uint OP_ORR = 0xC; - private const uint OP_MOV = 0xD; - private const uint OP_BIC = 0xE; - private const uint OP_MVN = 0xF; - - private delegate void ExecuteInstructionDelegate(); - private ExecuteInstructionDelegate[] NormalOps = null; - - private Arm7Processor parent; - private Memory memory; - private uint[] registers; - - private uint instructionQueue; - private uint curInstruction; - - // CPU flags - private uint zero, carry, negative, overflow; - private uint shifterCarry; - - private bool thumbMode; - - public FastArmCore(Arm7Processor parent, Memory memory) - { - this.parent = parent; - this.memory = memory; - this.registers = this.parent.Registers; - - this.NormalOps = new ExecuteInstructionDelegate[8] - { - this.UndefinedInstruction, - this.UndefinedInstruction, - this.UndefinedInstruction, - this.UndefinedInstruction, - this.LoadStoreMultiple, - this.UndefinedInstruction, - this.CoprocessorLoadStore, - this.UndefinedInstruction - }; - - this.InitializeDispatchFunc(); - } - - public void BeginExecution() - { - this.FlushQueue(); - } - - public void Step() - { - this.UnpackFlags(); - - this.curInstruction = this.instructionQueue; - this.instructionQueue = this.memory.ReadU32(registers[15]); - registers[15] += 4; - - uint cond = 0; - switch (this.curInstruction >> 28) - { - case COND_AL: cond = 1; break; - case COND_EQ: cond = zero; break; - case COND_NE: cond = 1 - zero; break; - case COND_CS: cond = carry; break; - case COND_CC: cond = 1 - carry; break; - case COND_MI: cond = negative; break; - case COND_PL: cond = 1 - negative; break; - case COND_VS: cond = overflow; break; - case COND_VC: cond = 1 - overflow; break; - case COND_HI: cond = carry & (1 - zero); break; - case COND_LS: cond = (1 - carry) | zero; break; - case COND_GE: cond = (1 - negative) ^ overflow; break; - case COND_LT: cond = negative ^ overflow; break; - case COND_GT: cond = (1 - zero) & (negative ^ (1 - overflow)); break; - case COND_LE: cond = (negative ^ overflow) | zero; break; - } - - if (cond == 1) - { - // Execute the instruction - this.ExecuteInstruction((ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF))); - } - - this.parent.Cycles -= this.memory.WaitCycles; - - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.parent.ReloadQueue(); - } - - this.PackFlags(); - } - - public void Execute() - { - this.UnpackFlags(); - this.thumbMode = false; - - while (this.parent.Cycles > 0) - { - this.curInstruction = this.instructionQueue; - this.instructionQueue = this.memory.ReadU32Aligned(registers[15]); - registers[15] += 4; - - if ((this.curInstruction >> 28) == COND_AL) - { - this.fastDispatch[(ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF))](); -// this.ExecuteInstruction((ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF))); - } - else - { - uint cond = 0; - switch (this.curInstruction >> 28) - { - case COND_EQ: cond = zero; break; - case COND_NE: cond = 1 - zero; break; - case COND_CS: cond = carry; break; - case COND_CC: cond = 1 - carry; break; - case COND_MI: cond = negative; break; - case COND_PL: cond = 1 - negative; break; - case COND_VS: cond = overflow; break; - case COND_VC: cond = 1 - overflow; break; - case COND_HI: cond = carry & (1 - zero); break; - case COND_LS: cond = (1 - carry) | zero; break; - case COND_GE: cond = (1 - negative) ^ overflow; break; - case COND_LT: cond = negative ^ overflow; break; - case COND_GT: cond = (1 - zero) & (negative ^ (1 - overflow)); break; - case COND_LE: cond = (negative ^ overflow) | zero; break; - } - - if (cond == 1) - { - // Execute the instruction - this.fastDispatch[(ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF))](); -// this.ExecuteInstruction((ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF))); - } - } - - this.parent.Cycles -= this.memory.WaitCycles; - - if (this.thumbMode) - { - this.parent.ReloadQueue(); - break; - } - -#if ARM_DEBUG - // Check the current PC - if (this.parent.Breakpoints.ContainsKey(registers[15] - 4U)) - { - this.parent.BreakpointHit = true; - break; - } -#endif - } - - this.PackFlags(); - } - - private void DataProcessingWriteToR15() - { - // Prevent writing if no SPSR exists (this will be true for USER or SYSTEM mode) - if (this.parent.SPSRExists) this.parent.WriteCpsr(this.parent.SPSR); - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - - // Otherwise, flush the instruction queue - this.FlushQueue(); - } - - private uint BarrelShifterLslImmed() - { - // rm lsl immed - uint rm = registers[this.curInstruction & 0xF]; - int amount = (int)((this.curInstruction >> 7) & 0x1F); - - if (amount == 0) - { - this.shifterCarry = this.carry; - return rm; - } - else - { - this.shifterCarry = (rm >> (32 - amount)) & 1; - return rm << amount; - } - } - - private uint BarrelShifterLslReg() - { - // rm lsl rs - uint rm = registers[this.curInstruction & 0xF]; - uint rs = (this.curInstruction >> 8) & 0xF; - - int amount; - if (rs == 15) - { - amount = (int)((registers[rs] + 0x4) & 0xFF); - } - else - { - amount = (int)(registers[rs] & 0xFF); - } - - if ((this.curInstruction & 0xF) == 15) - { - rm += 4; - } - - if (amount == 0) - { - this.shifterCarry = this.carry; - return rm; - } - - if (amount < 32) - { - this.shifterCarry = (rm >> (32 - amount)) & 1; - return rm << amount; - } - else if (amount == 32) - { - this.shifterCarry = rm & 1; - return 0; - } - else - { - this.shifterCarry = 0; - return 0; - } - } - - private uint BarrelShifterLsrImmed() - { - // rm lsr immed - uint rm = registers[this.curInstruction & 0xF]; - int amount = (int)((this.curInstruction >> 7) & 0x1F); - - if (amount == 0) - { - this.shifterCarry = (rm >> 31) & 1; - return 0; - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return rm >> amount; - } - } - - private uint BarrelShifterLsrReg() - { - // rm lsr rs - uint rm = registers[this.curInstruction & 0xF]; - uint rs = (this.curInstruction >> 8) & 0xF; - - int amount; - if (rs == 15) - { - amount = (int)((registers[rs] + 0x4) & 0xFF); - } - else - { - amount = (int)(registers[rs] & 0xFF); - } - - if ((this.curInstruction & 0xF) == 15) - { - rm += 4; - } - - if (amount == 0) - { - this.shifterCarry = this.carry; - return rm; - } - - if (amount < 32) - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return rm >> amount; - } - else if (amount == 32) - { - this.shifterCarry = (rm >> 31) & 1; - return 0; - } - else - { - this.shifterCarry = 0; - return 0; - } - } - - private uint BarrelShifterAsrImmed() - { - // rm asr immed - uint rm = registers[this.curInstruction & 0xF]; - int amount = (int)((this.curInstruction >> 7) & 0x1F); - - if (amount == 0) - { - if ((rm & (1 << 31)) == 0) - { - this.shifterCarry = 0; - return 0; - } - else - { - this.shifterCarry = 1; - return 0xFFFFFFFF; - } - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return (uint)(((int)rm) >> amount); - } - } - - private uint BarrelShifterAsrReg() - { - // rm asr rs - uint rm = registers[this.curInstruction & 0xF]; - uint rs = (this.curInstruction >> 8) & 0xF; - - int amount; - if (rs == 15) - { - amount = (int)((registers[rs] + 0x4) & 0xFF); - } - else - { - amount = (int)(registers[rs] & 0xFF); - } - - if ((this.curInstruction & 0xF) == 15) - { - rm += 4; - } - - if (amount == 0) - { - this.shifterCarry = this.carry; - return rm; - } - - if (amount >= 32) - { - if ((rm & (1 << 31)) == 0) - { - this.shifterCarry = 0; - return 0; - } - else - { - this.shifterCarry = 1; - return 0xFFFFFFFF; - } - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return (uint)(((int)rm) >> amount); - } - } - - private uint BarrelShifterRorImmed() - { - // rm ror immed - uint rm = registers[this.curInstruction & 0xF]; - int amount = (int)((this.curInstruction >> 7) & 0x1F); - - if (amount == 0) - { - // Actually an RRX - this.shifterCarry = rm & 1; - return (this.carry << 31) | (rm >> 1); - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return (rm >> amount) | (rm << (32 - amount)); - } - } - - private uint BarrelShifterRorReg() - { - // rm ror rs - uint rm = registers[this.curInstruction & 0xF]; - uint rs = (this.curInstruction >> 8) & 0xF; - - int amount; - if (rs == 15) - { - amount = (int)((registers[rs] + 0x4) & 0xFF); - } - else - { - amount = (int)(registers[rs] & 0xFF); - } - - if ((this.curInstruction & 0xF) == 15) - { - rm += 4; - } - - if (amount == 0) - { - this.shifterCarry = this.carry; - return rm; - } - - if ((amount & 0x1F) == 0) - { - this.shifterCarry = (rm >> 31) & 1; - return rm; - } - else - { - amount &= 0x1F; - this.shifterCarry = (rm >> amount) & 1; - return (rm >> amount) | (rm << (32 - amount)); - } - } - - private uint BarrelShifterImmed() - { - uint immed = this.curInstruction & 0xFF; - int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2); - - if (rotateAmount == 0) - { - this.shifterCarry = this.carry; - return immed; - } - else - { - immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount)); - this.shifterCarry = (immed >> 31) & 1; - return immed; - } - } - - private int MultiplyCycleCalculation(uint rs) - { - // Multiply cycle calculations - if ((registers[rs] & 0xFFFFFF00) == 0 || (registers[rs] & 0xFFFFFF00) == 0xFFFFFF00) - { - return 1; - } - else if ((registers[rs] & 0xFFFF0000) == 0 || (registers[rs] & 0xFFFF0000) == 0xFFFF0000) - { - return 2; - } - else if ((registers[rs] & 0xFF000000) == 0 || (registers[rs] & 0xFF000000) == 0xFF000000) - { - return 3; - } - return 4; - } - - private void UndefinedInstruction() - { - // Do the undefined instruction dance here - throw new Exception("Undefined exception"); - } - - private void ExecuteInstruction(ushort op) - { - // Not emulating rn += 4 when register shift, in data operand when rn == pc - - uint rn, rd, rs, rm, address, offset, shifterOperand, alu; - int cycles; - - switch (op) - { - //////////////////////////////////////////////////////////////////////////////////////////// - // - // AND implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x000: - case 0x008: - // AND rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x001: - // AND rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x002: - case 0x00A: - // AND rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x003: - // AND rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x004: - case 0x00C: - // AND rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x005: - // AND rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x006: - case 0x00E: - // AND rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x007: - // AND rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x010: - case 0x018: - // ANDS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x011: - // ANDS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x012: - case 0x01A: - // ANDS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x013: - // ANDS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x014: - case 0x01C: - // ANDS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x015: - // ANDS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x016: - case 0x01E: - // ANDS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x017: - // ANDS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // Undefined instruction implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x00D: case 0x02D: case 0x04D: case 0x06D: - case 0x08D: case 0x0AD: case 0x0CD: case 0x0ED: - case 0x10D: case 0x12D: case 0x14D: case 0x16D: - case 0x18D: case 0x1AD: case 0x1CD: case 0x1ED: - case 0x00F: case 0x02F: case 0x04F: case 0x06F: - case 0x08F: case 0x0AF: case 0x0CF: case 0x0EF: - case 0x10F: case 0x12F: case 0x14F: case 0x16F: - case 0x18F: case 0x1AF: case 0x1CF: case 0x1EF: - UndefinedInstruction(); - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // MUL implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x009: - // MUL rd, rm, rs - rd = (this.curInstruction >> 16) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs); - - registers[rd] = registers[rs] * registers[rm]; - this.parent.Cycles -= cycles; - break; - - case 0x019: - // MULS rd, rm, rs - rd = (this.curInstruction >> 16) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs); - - registers[rd] = registers[rs] * registers[rm]; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - - this.parent.Cycles -= cycles; - break; - - case 0x029: - // MLA rd, rm, rs, rn - rd = (this.curInstruction >> 16) & 0xF; - rn = registers[(this.curInstruction >> 12) & 0xF]; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs); - - registers[rd] = registers[rs] * registers[rm] + rn; - this.parent.Cycles -= cycles + 1; - break; - - case 0x039: - // MLAS rd, rm, rs - rd = (this.curInstruction >> 16) & 0xF; - rn = registers[(this.curInstruction >> 12) & 0xF]; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs); - - registers[rd] = registers[rs] * registers[rm] + rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - - this.parent.Cycles -= cycles + 1; - break; - - case 0x089: - // UMULL rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 1; - - ulong result = ((ulong)registers[rm]) * registers[rs]; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - this.parent.Cycles -= cycles; - } - break; - - case 0x099: - // UMULLS rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 1; - - ulong result = ((ulong)registers[rm]) * registers[rs]; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - - this.parent.Cycles -= cycles; - } - break; - - case 0x0A9: - // UMLAL rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 2; - - ulong accum = (((ulong)registers[rdhi]) << 32) | registers[rdlo]; - ulong result = ((ulong)registers[rm]) * registers[rs]; - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - this.parent.Cycles -= cycles; - } - break; - - case 0x0B9: - // UMLALS rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 2; - - ulong accum = (((ulong)registers[rdhi]) << 32) | registers[rdlo]; - ulong result = ((ulong)registers[rm]) * registers[rs]; - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - - this.parent.Cycles -= cycles; - } - break; - - case 0x0C9: - // SMULL rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 1; - - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - this.parent.Cycles -= cycles; - } - break; - - case 0x0D9: - // SMULLS rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 1; - - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - - this.parent.Cycles -= cycles; - } - break; - - case 0x0E9: - // SMLAL rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 2; - - long accum = (((long)((int)registers[rdhi])) << 32) | registers[rdlo]; - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - this.parent.Cycles -= cycles; - } - break; - - case 0x0F9: - // SMLALS rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 2; - - long accum = (((long)((int)registers[rdhi])) << 32) | registers[rdlo]; - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - - this.parent.Cycles -= cycles; - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // STRH implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x00B: - // STRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - break; - - case 0x02B: - // Writeback bit set, instruction is unpredictable - // STRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - break; - - case 0x04B: - // STRH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - break; - - case 0x06B: - // Writeback bit set, instruction is unpredictable - // STRH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - break; - - case 0x08B: - // STRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - break; - - case 0x0AB: - // Writeback bit set, instruction is unpredictable - // STRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - break; - - case 0x0CB: - // STRH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - break; - - case 0x0EB: - // Writeback bit set, instruction is unpredictable - // STRH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - break; - - case 0x10B: - // STRH rd, [rn, -rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF)); - break; - - case 0x12B: - // STRH rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rn] += offset; - this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF)); - break; - - case 0x14B: - // STRH rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF)); - break; - - case 0x16B: - // STRH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rn] += offset; - this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF)); - break; - - case 0x18B: - // STRH rd, [rn, rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF)); - break; - - case 0x1AB: - // STRH rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rn] += offset; - this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF)); - break; - - case 0x1CB: - // STRH rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF)); - break; - - case 0x1EB: - // STRH rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rn] += offset; - this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF)); - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // LDRH implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x01B: - // LDRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x03B: - // Writeback bit set, instruction is unpredictable - // LDRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x05B: - // LDRH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x07B: - // Writeback bit set, instruction is unpredictable - // LDRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x09B: - // LDRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x0BB: - // Writeback bit set, instruction is unpredictable - // LDRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x0DB: - // LDRH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x0FB: - // Writeback bit set, instruction is unpredictable - // LDRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x11B: - // LDRH rd, [rn, -rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x13B: - // LDRH rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rn] += offset; - - registers[rd] = this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x15B: - // LDRH rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x17B: - // LDRH rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x19B: - // LDRH rd, [rn, rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x1BB: - // LDRH rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x1DB: - // LDRH rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x1FB: - // LDRH rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rn] += offset; - registers[rd] = this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // LDRSB implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x01D: - // LDRSB rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x03D: - // Writeback bit set, instruction is unpredictable - // LDRSB rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x05D: - // LDRSB rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x07D: - // Writeback bit set, instruction is unpredictable - // LDRSB rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x09D: - // LDRSB rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x0BD: - // Writeback bit set, instruction is unpredictable - // LDRSB rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x0DD: - // LDRSB rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x0FD: - // Writeback bit set, instruction is unpredictable - // LDRSB rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x11D: - // LDRSB rd, [rn, -rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x13D: - // LDRSB rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x15D: - // LDRSB rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x17D: - // LDRSB rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x19D: - // LDRSB rd, [rn, rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x1BD: - // LDRSB rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x1DD: - // LDRSB rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x1FD: - // LDRSB rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rn] += offset; - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // LDRSH implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x01F: - // LDRSH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x03F: - // Writeback bit set, instruction is unpredictable - // LDRSH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x05F: - // LDRSH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x07F: - // Writeback bit set, instruction is unpredictable - // LDRSH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x09F: - // LDRSH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x0BF: - // Writeback bit set, instruction is unpredictable - // LDRSH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x0DF: - // LDRSH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x0FF: - // Writeback bit set, instruction is unpredictable - // LDRSH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - break; - - case 0x11F: - // LDRSH rd, [rn, -rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x13F: - // LDRSH rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x15F: - // LDRSH rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x17F: - // LDRSH rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x19F: - // LDRSH rd, [rn, rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x1BF: - // LDRSH rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rn] += offset; - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x1DF: - // LDRSH rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x1FF: - // LDRSH rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rn] += offset; - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // EOR implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x020: - case 0x028: - // EOR rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x021: - // EOR rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x022: - case 0x02A: - // EOR rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x023: - // EOR rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x024: - case 0x02C: - // EOR rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x025: - // EOR rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x026: - case 0x02E: - // EOR rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x027: - // EOR rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x030: - case 0x038: - // EORS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x031: - // EORS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x032: - case 0x03A: - // EORS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x033: - // EORS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x034: - case 0x03C: - // EORS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x035: - // EORS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x036: - case 0x03E: - // EORS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x037: - // EORS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // SUB implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x040: - case 0x048: - // SUB rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x041: - // SUB rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x042: - case 0x04A: - // SUB rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x043: - // SUB rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x044: - case 0x04C: - // SUB rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x045: - // SUB rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x046: - case 0x04E: - // SUB rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x047: - // SUB rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x050: - case 0x058: - // SUBS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x051: - // SUBS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x052: - case 0x05A: - // SUBS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x053: - // SUBS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x054: - case 0x05C: - // SUBS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x055: - // SUBS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x056: - case 0x05E: - // SUBS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x057: - // SUBS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // RSB implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x060: - case 0x068: - // RSB rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x061: - // RSB rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslReg() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x062: - case 0x06A: - // RSB rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x063: - // RSB rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrReg() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x064: - case 0x06C: - // RSB rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x065: - // RSB rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrReg() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x066: - case 0x06E: - // RSB rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x067: - // RSB rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorReg() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x070: - case 0x078: - // RSBS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x071: - // RSBS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x072: - case 0x07A: - // RSBS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x073: - // RSBS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x074: - case 0x07C: - // RSBS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x075: - // RSBS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x076: - case 0x07E: - // RSBS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x077: - // RSBS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // ADD implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x080: - case 0x088: - // ADD rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x081: - // ADD rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x082: - case 0x08A: - // ADD rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x083: - // ADD rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x084: - case 0x08C: - // ADD rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x085: - // ADD rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x086: - case 0x08E: - // ADD rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x087: - // ADD rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x090: - case 0x098: - // ADDS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x091: - // ADDS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x092: - case 0x09A: - // ADDS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x093: - // ADDS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x094: - case 0x09C: - // ADDS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x095: - // ADDS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x096: - case 0x09E: - // ADDS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x097: - // ADDS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // ADC implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x0A0: - case 0x0A8: - // ADC rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLslImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0A1: - // ADC rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLslReg() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0A2: - case 0x0AA: - // ADC rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLsrImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0A3: - // ADC rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLsrReg() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0A4: - case 0x0AC: - // ADC rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterAsrImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0A5: - // ADC rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterAsrReg() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0A6: - case 0x0AE: - // ADC rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterRorImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0A7: - // ADC rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterRorReg() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0B0: - case 0x0B8: - // ADCS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0B1: - // ADCS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0B2: - case 0x0BA: - // ADCS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0B3: - // ADCS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0B4: - case 0x0BC: - // ADCS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0B5: - // ADCS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0B6: - case 0x0BE: - // ADCS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0B7: - // ADCS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // SBC implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x0C0: - case 0x0C8: - // SBC rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLslImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0C1: - // SBC rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLslReg() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0C2: - case 0x0CA: - // SBC rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLsrImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0C3: - // SBC rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLsrReg() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0C4: - case 0x0CC: - // SBC rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterAsrImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0C5: - // SBC rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterAsrReg() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0C6: - case 0x0CE: - // SBC rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterRorImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0C7: - // SBC rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterRorReg() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0D0: - case 0x0D8: - // SBCS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0D1: - // SBCS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0D2: - case 0x0DA: - // SBCS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0D3: - // SBCS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0D4: - case 0x0DC: - // SBCS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0D5: - // SBCS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0D6: - case 0x0DE: - // SBCS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0D7: - // SBCS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // RSC implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x0E0: - case 0x0E8: - // RSC rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0E1: - // RSC rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslReg() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0E2: - case 0x0EA: - // RSC rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0E3: - // RSC rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrReg() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0E4: - case 0x0EC: - // RSC rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0E5: - // RSC rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrReg() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0E6: - case 0x0EE: - // RSC rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0E7: - // RSC rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorReg() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x0F0: - case 0x0F8: - // RSCS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0F1: - // RSCS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0F2: - case 0x0FA: - // RSCS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0F3: - // RSCS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0F4: - case 0x0FC: - // RSCS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0F5: - // RSCS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0F6: - case 0x0FE: - // RSCS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x0F7: - // RSCS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // Misc. instructions (MSR, MRS, SWP, BX) - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x109: - // SWP rd, rm, [rn] - { - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - rm = this.curInstruction & 0xF; - uint tmp = this.memory.ReadU32(registers[rn]); - this.memory.WriteU32(registers[rn], registers[rm]); - registers[rd] = tmp; - - if (rd == 15) - { - this.FlushQueue(); - } - } - break; - - case 0x149: - // SWPB rd, rm, [rn] - { - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - rm = this.curInstruction & 0xF; - - byte tmp = this.memory.ReadU8(registers[rn]); - this.memory.WriteU8(registers[rn], (byte)(registers[rm] & 0xFF)); - registers[rd] = tmp; - - if (rd == 15) - { - this.FlushQueue(); - } - } - break; - - case 0x100: - // MRS rd, cpsr - rd = (this.curInstruction >> 12) & 0xF; - this.PackFlags(); - registers[rd] = this.parent.CPSR; - break; - - case 0x140: - // MRS rd, spsr - rd = (this.curInstruction >> 12) & 0xF; - if (this.parent.SPSRExists) registers[rd] = this.parent.SPSR; - break; - - case 0x120: - // MSR cpsr, rm - { - rm = registers[this.curInstruction & 0xF]; - bool userMode = (this.parent.CPSR & 0x1F) == Arm7Processor.USR; - - this.PackFlags(); - - uint tmpCPSR = this.parent.CPSR; - - if ((this.curInstruction & (1 << 16)) == 1 << 16 && !userMode) - { - tmpCPSR &= 0xFFFFFF00; - tmpCPSR |= rm & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17 && !userMode) - { - tmpCPSR &= 0xFFFF00FF; - tmpCPSR |= rm & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18 && !userMode) - { - tmpCPSR &= 0xFF00FFFF; - tmpCPSR |= rm & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - tmpCPSR &= 0x00FFFFFF; - tmpCPSR |= rm & 0xFF000000; - } - - this.parent.WriteCpsr(tmpCPSR); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - } - break; - - case 0x160: - // MSR spsr, rm - if (this.parent.SPSRExists) - { - rm = registers[this.curInstruction & 0xF]; - if ((this.curInstruction & (1 << 16)) == 1 << 16) - { - this.parent.SPSR &= 0xFFFFFF00; - this.parent.SPSR |= rm & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17) - { - this.parent.SPSR &= 0xFFFF00FF; - this.parent.SPSR |= rm & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18) - { - this.parent.SPSR &= 0xFF00FFFF; - this.parent.SPSR |= rm & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - this.parent.SPSR &= 0x00FFFFFF; - this.parent.SPSR |= rm & 0xFF000000; - } - } - break; - - case 0x320: - // MSR cpsr, immed - { - uint immed = this.curInstruction & 0xFF; - int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2); - - immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount)); - - bool userMode = (this.parent.CPSR & 0x1F) == Arm7Processor.USR; - - this.PackFlags(); - - uint tmpCPSR = this.parent.CPSR; - - if ((this.curInstruction & (1 << 16)) == 1 << 16 && !userMode) - { - tmpCPSR &= 0xFFFFFF00; - tmpCPSR |= immed & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17 && !userMode) - { - tmpCPSR &= 0xFFFF00FF; - tmpCPSR |= immed & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18 && !userMode) - { - tmpCPSR &= 0xFF00FFFF; - tmpCPSR |= immed & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - tmpCPSR &= 0x00FFFFFF; - tmpCPSR |= immed & 0xFF000000; - } - - this.parent.WriteCpsr(tmpCPSR); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - } - break; - - case 0x360: - // MSR spsr, immed - if (this.parent.SPSRExists) - { - uint immed = this.curInstruction & 0xFF; - int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2); - - immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount)); - - if ((this.curInstruction & (1 << 16)) == 1 << 16) - { - this.parent.SPSR &= 0xFFFFFF00; - this.parent.SPSR |= immed & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17) - { - this.parent.SPSR &= 0xFFFF00FF; - this.parent.SPSR |= immed & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18) - { - this.parent.SPSR &= 0xFF00FFFF; - this.parent.SPSR |= immed & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - this.parent.SPSR &= 0x00FFFFFF; - this.parent.SPSR |= immed & 0xFF000000; - } - } - break; - - case 0x121: - // BX rm - rm = this.curInstruction & 0xf; - - this.PackFlags(); - - this.parent.CPSR &= ~Arm7Processor.T_MASK; - this.parent.CPSR |= (registers[rm] & 1) << Arm7Processor.T_BIT; - - registers[15] = registers[rm] & (~1U); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - - this.FlushQueue(); - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // TST implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x110: - case 0x118: - // TSTS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterLslImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x111: - // TSTS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterLslReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x112: - case 0x11A: - // TSTS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterLsrImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x113: - // TSTS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterLsrReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x114: - case 0x11C: - // TSTS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterAsrImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x115: - // TSTS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterAsrReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x116: - case 0x11E: - // TSTS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterRorImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x117: - // TSTS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - alu = rn & BarrelShifterRorReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // TEQ implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x130: - case 0x138: - // TEQS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterLslImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x131: - // TEQS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterLslReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x132: - case 0x13A: - // TEQS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterLsrImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x133: - // TEQS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterLsrReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x134: - case 0x13C: - // TEQS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterAsrImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x135: - // TEQS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterAsrReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x136: - case 0x13E: - // TEQS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterRorImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x137: - // TEQS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - alu = rn ^ BarrelShifterRorReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // CMP implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x150: - case 0x158: - // CMP rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLslImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case 0x151: - // CMP rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLslReg(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case 0x152: - case 0x15A: - // CMP rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLsrImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case 0x153: - // CMP rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLsrReg(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case 0x154: - case 0x15C: - // CMP rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterAsrImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case 0x155: - // CMP rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterAsrReg(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case 0x156: - case 0x15E: - // CMP rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterRorImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case 0x157: - // CMP rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterRorReg(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // CMN implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x170: - case 0x178: - // CMN rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLslImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case 0x171: - // CMN rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLslReg(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case 0x172: - case 0x17A: - // CMN rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLsrImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case 0x173: - // CMN rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLsrReg(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case 0x174: - case 0x17C: - // CMN rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterAsrImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case 0x175: - // CMN rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterAsrReg(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case 0x176: - case 0x17E: - // CMN rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterRorImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case 0x177: - // CMN rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterRorReg(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // ORR implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x180: - case 0x188: - // ORR rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x181: - // ORR rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x182: - case 0x18A: - // ORR rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x183: - // ORR rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x184: - case 0x18C: - // ORR rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x185: - // ORR rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x186: - case 0x18E: - // ORR rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x187: - // ORR rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x190: - case 0x198: - // ORRS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x191: - // ORRS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x192: - case 0x19A: - // ORRS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x193: - // ORRS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x194: - case 0x19C: - // ORRS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x195: - // ORRS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x196: - case 0x19E: - // ORRS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x197: - // ORRS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // MOV implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x1A0: - case 0x1A8: - // MOV rd, rm lsl immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1A1: - // MOV rd, rm lsl rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1A2: - case 0x1AA: - // MOV rd, rm lsr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1A3: - // MOV rd, rm lsr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1A4: - case 0x1AC: - // MOV rd, rm asr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1A5: - // MOV rd, rm asr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1A6: - case 0x1AE: - // MOV rd, rm ror immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1A7: - // MOV rd, rm ror rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1B0: - case 0x1B8: - // MOVS rd, rm lsl immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1B1: - // MOVS rd, rm lsl rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1B2: - case 0x1BA: - // MOVS rd, rm lsr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1B3: - // MOVS rd, rn, rm lsr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1B4: - case 0x1BC: - // MOVS rd, rn, rm asr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1B5: - // MOVS rd, rn, rm asr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1B6: - case 0x1BE: - // MOVS rd, rn, rm ror immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1B7: - // MOVS rd, rn, rm ror rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // BIC implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x1C0: - case 0x1C8: - // BIC rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1C1: - // BIC rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1C2: - case 0x1CA: - // BIC rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1C3: - // BIC rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1C4: - case 0x1CC: - // BIC rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1C5: - // BIC rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1C6: - case 0x1CE: - // BIC rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1C7: - // BIC rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1D0: - case 0x1D8: - // BICS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1D1: - // BICS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1D2: - case 0x1DA: - // BICS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1D3: - // BICS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1D4: - case 0x1DC: - // BICS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1D5: - // BICS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1D6: - case 0x1DE: - // BICS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1D7: - // BICS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // MVN implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x1E0: - case 0x1E8: - // MVN rd, rm lsl immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1E1: - // MVN rd, rm lsl rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1E2: - case 0x1EA: - // MVN rd, rm lsr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1E3: - // MVN rd, rm lsr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1E4: - case 0x1EC: - // MVN rd, rm asr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1E5: - // MVN rd, rm asr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1E6: - case 0x1EE: - // MVN rd, rm ror immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1E7: - // MVN rd, rm ror rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x1F0: - case 0x1F8: - // MVNS rd, rm lsl immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1F1: - // MVNS rd, rm lsl rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1F2: - case 0x1FA: - // MVNS rd, rm lsr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1F3: - // MVNS rd, rn, rm lsr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1F4: - case 0x1FC: - // MVNS rd, rn, rm asr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1F5: - // MVNS rd, rn, rm asr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1F6: - case 0x1FE: - // MVNS rd, rn, rm ror immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x1F7: - // MVNS rd, rn, rm ror rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // Data processing immediate operand implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x200: case 0x201: case 0x202: case 0x203: case 0x204: case 0x205: case 0x206: case 0x207: - case 0x208: case 0x209: case 0x20A: case 0x20B: case 0x20C: case 0x20D: case 0x20E: case 0x20F: - // AND rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn & BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x210: case 0x211: case 0x212: case 0x213: case 0x214: case 0x215: case 0x216: case 0x217: - case 0x218: case 0x219: case 0x21A: case 0x21B: case 0x21C: case 0x21D: case 0x21E: case 0x21F: - // ANDS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn & BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x220: case 0x221: case 0x222: case 0x223: case 0x224: case 0x225: case 0x226: case 0x227: - case 0x228: case 0x229: case 0x22A: case 0x22B: case 0x22C: case 0x22D: case 0x22E: case 0x22F: - // EOR rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn ^ BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x230: case 0x231: case 0x232: case 0x233: case 0x234: case 0x235: case 0x236: case 0x237: - case 0x238: case 0x239: case 0x23A: case 0x23B: case 0x23C: case 0x23D: case 0x23E: case 0x23F: - // EORS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn ^ BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x240: case 0x241: case 0x242: case 0x243: case 0x244: case 0x245: case 0x246: case 0x247: - case 0x248: case 0x249: case 0x24A: case 0x24B: case 0x24C: case 0x24D: case 0x24E: case 0x24F: - // SUB rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn - BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x250: case 0x251: case 0x252: case 0x253: case 0x254: case 0x255: case 0x256: case 0x257: - case 0x258: case 0x259: case 0x25A: case 0x25B: case 0x25C: case 0x25D: case 0x25E: case 0x25F: - // SUBS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x260: case 0x261: case 0x262: case 0x263: case 0x264: case 0x265: case 0x266: case 0x267: - case 0x268: case 0x269: case 0x26A: case 0x26B: case 0x26C: case 0x26D: case 0x26E: case 0x26F: - // RSB rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = BarrelShifterImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x270: case 0x271: case 0x272: case 0x273: case 0x274: case 0x275: case 0x276: case 0x277: - case 0x278: case 0x279: case 0x27A: case 0x27B: case 0x27C: case 0x27D: case 0x27E: case 0x27F: - // RSBS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x280: case 0x281: case 0x282: case 0x283: case 0x284: case 0x285: case 0x286: case 0x287: - case 0x288: case 0x289: case 0x28A: case 0x28B: case 0x28C: case 0x28D: case 0x28E: case 0x28F: - // ADD rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn + BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x290: case 0x291: case 0x292: case 0x293: case 0x294: case 0x295: case 0x296: case 0x297: - case 0x298: case 0x299: case 0x29A: case 0x29B: case 0x29C: case 0x29D: case 0x29E: case 0x29F: - // ADDS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x2A0: case 0x2A1: case 0x2A2: case 0x2A3: case 0x2A4: case 0x2A5: case 0x2A6: case 0x2A7: - case 0x2A8: case 0x2A9: case 0x2AA: case 0x2AB: case 0x2AC: case 0x2AD: case 0x2AE: case 0x2AF: - // ADC rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn + BarrelShifterImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x2B0: case 0x2B1: case 0x2B2: case 0x2B3: case 0x2B4: case 0x2B5: case 0x2B6: case 0x2B7: - case 0x2B8: case 0x2B9: case 0x2BA: case 0x2BB: case 0x2BC: case 0x2BD: case 0x2BE: case 0x2BF: - // ADCS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x2C0: case 0x2C1: case 0x2C2: case 0x2C3: case 0x2C4: case 0x2C5: case 0x2C6: case 0x2C7: - case 0x2C8: case 0x2C9: case 0x2CA: case 0x2CB: case 0x2CC: case 0x2CD: case 0x2CE: case 0x2CF: - // SBC rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn - BarrelShifterImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x2D0: case 0x2D1: case 0x2D2: case 0x2D3: case 0x2D4: case 0x2D5: case 0x2D6: case 0x2D7: - case 0x2D8: case 0x2D9: case 0x2DA: case 0x2DB: case 0x2DC: case 0x2DD: case 0x2DE: case 0x2DF: - // SBCS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x2E0: case 0x2E1: case 0x2E2: case 0x2E3: case 0x2E4: case 0x2E5: case 0x2E6: case 0x2E7: - case 0x2E8: case 0x2E9: case 0x2EA: case 0x2EB: case 0x2EC: case 0x2ED: case 0x2EE: case 0x2EF: - // RSC rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = BarrelShifterImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x2F0: case 0x2F1: case 0x2F2: case 0x2F3: case 0x2F4: case 0x2F5: case 0x2F6: case 0x2F7: - case 0x2F8: case 0x2F9: case 0x2FA: case 0x2FB: case 0x2FC: case 0x2FD: case 0x2FE: case 0x2FF: - // RSCS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x310: case 0x311: case 0x312: case 0x313: case 0x314: case 0x315: case 0x316: case 0x317: - case 0x318: case 0x319: case 0x31A: case 0x31B: case 0x31C: case 0x31D: case 0x31E: case 0x31F: - // TSTS rn, immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x330: case 0x331: case 0x332: case 0x333: case 0x334: case 0x335: case 0x336: case 0x337: - case 0x338: case 0x339: case 0x33A: case 0x33B: case 0x33C: case 0x33D: case 0x33E: case 0x33F: - // TEQS rn, immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case 0x350: case 0x351: case 0x352: case 0x353: case 0x354: case 0x355: case 0x356: case 0x357: - case 0x358: case 0x359: case 0x35A: case 0x35B: case 0x35C: case 0x35D: case 0x35E: case 0x35F: - // CMP rn, immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case 0x370: case 0x371: case 0x372: case 0x373: case 0x374: case 0x375: case 0x376: case 0x377: - case 0x378: case 0x379: case 0x37A: case 0x37B: case 0x37C: case 0x37D: case 0x37E: case 0x37F: - // CMN rn, immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case 0x380: case 0x381: case 0x382: case 0x383: case 0x384: case 0x385: case 0x386: case 0x387: - case 0x388: case 0x389: case 0x38A: case 0x38B: case 0x38C: case 0x38D: case 0x38E: case 0x38F: - // ORR rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn | BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x390: case 0x391: case 0x392: case 0x393: case 0x394: case 0x395: case 0x396: case 0x397: - case 0x398: case 0x399: case 0x39A: case 0x39B: case 0x39C: case 0x39D: case 0x39E: case 0x39F: - // ORRS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn | BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x3A0: case 0x3A1: case 0x3A2: case 0x3A3: case 0x3A4: case 0x3A5: case 0x3A6: case 0x3A7: - case 0x3A8: case 0x3A9: case 0x3AA: case 0x3AB: case 0x3AC: case 0x3AD: case 0x3AE: case 0x3AF: - // MOV rd, immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x3B0: case 0x3B1: case 0x3B2: case 0x3B3: case 0x3B4: case 0x3B5: case 0x3B6: case 0x3B7: - case 0x3B8: case 0x3B9: case 0x3BA: case 0x3BB: case 0x3BC: case 0x3BD: case 0x3BE: case 0x3BF: - // MOVS rd, immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x3C0: case 0x3C1: case 0x3C2: case 0x3C3: case 0x3C4: case 0x3C5: case 0x3C6: case 0x3C7: - case 0x3C8: case 0x3C9: case 0x3CA: case 0x3CB: case 0x3CC: case 0x3CD: case 0x3CE: case 0x3CF: - // BIC rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn & ~BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x3D0: case 0x3D1: case 0x3D2: case 0x3D3: case 0x3D4: case 0x3D5: case 0x3D6: case 0x3D7: - case 0x3D8: case 0x3D9: case 0x3DA: case 0x3DB: case 0x3DC: case 0x3DD: case 0x3DE: case 0x3DF: - // BICS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn & ~BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - case 0x3E0: case 0x3E1: case 0x3E2: case 0x3E3: case 0x3E4: case 0x3E5: case 0x3E6: case 0x3E7: - case 0x3E8: case 0x3E9: case 0x3EA: case 0x3EB: case 0x3EC: case 0x3ED: case 0x3EE: case 0x3EF: - // MVN rd, immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - break; - - case 0x3F0: case 0x3F1: case 0x3F2: case 0x3F3: case 0x3F4: case 0x3F5: case 0x3F6: case 0x3F7: - case 0x3F8: case 0x3F9: case 0x3FA: case 0x3FB: case 0x3FC: case 0x3FD: case 0x3FE: case 0x3FF: - // MVNS rd, immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // STR immediate implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x400: case 0x401: case 0x402: case 0x403: case 0x404: case 0x405: case 0x406: case 0x407: - case 0x408: case 0x409: case 0x40A: case 0x40B: case 0x40C: case 0x40D: case 0x40E: case 0x40F: - // STR rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x420: case 0x421: case 0x422: case 0x423: case 0x424: case 0x425: case 0x426: case 0x427: - case 0x428: case 0x429: case 0x42A: case 0x42B: case 0x42C: case 0x42D: case 0x42E: case 0x42F: - // STRT rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x440: case 0x441: case 0x442: case 0x443: case 0x444: case 0x445: case 0x446: case 0x447: - case 0x448: case 0x449: case 0x44A: case 0x44B: case 0x44C: case 0x44D: case 0x44E: case 0x44F: - // STRB rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x460: case 0x461: case 0x462: case 0x463: case 0x464: case 0x465: case 0x466: case 0x467: - case 0x468: case 0x469: case 0x46A: case 0x46B: case 0x46C: case 0x46D: case 0x46E: case 0x46F: - // STRBT rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x480: case 0x481: case 0x482: case 0x483: case 0x484: case 0x485: case 0x486: case 0x487: - case 0x488: case 0x489: case 0x48A: case 0x48B: case 0x48C: case 0x48D: case 0x48E: case 0x48F: - // STR rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.curInstruction & 0xFFF; - break; - - case 0x4A0: case 0x4A1: case 0x4A2: case 0x4A3: case 0x4A4: case 0x4A5: case 0x4A6: case 0x4A7: - case 0x4A8: case 0x4A9: case 0x4AA: case 0x4AB: case 0x4AC: case 0x4AD: case 0x4AE: case 0x4AF: - // STRT rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.curInstruction & 0xFFF; - break; - - case 0x4C0: case 0x4C1: case 0x4C2: case 0x4C3: case 0x4C4: case 0x4C5: case 0x4C6: case 0x4C7: - case 0x4C8: case 0x4C9: case 0x4CA: case 0x4CB: case 0x4CC: case 0x4CD: case 0x4CE: case 0x4CF: - // STRB rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.curInstruction & 0xFFF; - break; - - case 0x4E0: case 0x4E1: case 0x4E2: case 0x4E3: case 0x4E4: case 0x4E5: case 0x4E6: case 0x4E7: - case 0x4E8: case 0x4E9: case 0x4EA: case 0x4EB: case 0x4EC: case 0x4ED: case 0x4EE: case 0x4EF: - // STRBT rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.curInstruction & 0xFFF; - break; - - case 0x500: case 0x501: case 0x502: case 0x503: case 0x504: case 0x505: case 0x506: case 0x507: - case 0x508: case 0x509: case 0x50A: case 0x50B: case 0x50C: case 0x50D: case 0x50E: case 0x50F: - // STR rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - break; - - case 0x520: case 0x521: case 0x522: case 0x523: case 0x524: case 0x525: case 0x526: case 0x527: - case 0x528: case 0x529: case 0x52A: case 0x52B: case 0x52C: case 0x52D: case 0x52E: case 0x52F: - // STR rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x540: case 0x541: case 0x542: case 0x543: case 0x544: case 0x545: case 0x546: case 0x547: - case 0x548: case 0x549: case 0x54A: case 0x54B: case 0x54C: case 0x54D: case 0x54E: case 0x54F: - // STRB rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - break; - - case 0x560: case 0x561: case 0x562: case 0x563: case 0x564: case 0x565: case 0x566: case 0x567: - case 0x568: case 0x569: case 0x56A: case 0x56B: case 0x56C: case 0x56D: case 0x56E: case 0x56F: - // STRB rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - case 0x580: case 0x581: case 0x582: case 0x583: case 0x584: case 0x585: case 0x586: case 0x587: - case 0x588: case 0x589: case 0x58A: case 0x58B: case 0x58C: case 0x58D: case 0x58E: case 0x58F: - // STR rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + (this.curInstruction & 0xFFF), alu); - break; - - case 0x5A0: case 0x5A1: case 0x5A2: case 0x5A3: case 0x5A4: case 0x5A5: case 0x5A6: case 0x5A7: - case 0x5A8: case 0x5A9: case 0x5AA: case 0x5AB: case 0x5AC: case 0x5AD: case 0x5AE: case 0x5AF: - // STRT rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.curInstruction & 0xFFF; - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x5C0: case 0x5C1: case 0x5C2: case 0x5C3: case 0x5C4: case 0x5C5: case 0x5C6: case 0x5C7: - case 0x5C8: case 0x5C9: case 0x5CA: case 0x5CB: case 0x5CC: case 0x5CD: case 0x5CE: case 0x5CF: - // STRB rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + (this.curInstruction & 0xFFF), (byte)(alu & 0xFF)); - break; - - case 0x5E0: case 0x5E1: case 0x5E2: case 0x5E3: case 0x5E4: case 0x5E5: case 0x5E6: case 0x5E7: - case 0x5E8: case 0x5E9: case 0x5EA: case 0x5EB: case 0x5EC: case 0x5ED: case 0x5EE: case 0x5EF: - // STRB rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.curInstruction & 0xFFF; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // LDR immediate implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x410: case 0x411: case 0x412: case 0x413: case 0x414: case 0x415: case 0x416: case 0x417: - case 0x418: case 0x419: case 0x41A: case 0x41B: case 0x41C: case 0x41D: case 0x41E: case 0x41F: - // LDR rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x430: case 0x431: case 0x432: case 0x433: case 0x434: case 0x435: case 0x436: case 0x437: - case 0x438: case 0x439: case 0x43A: case 0x43B: case 0x43C: case 0x43D: case 0x43E: case 0x43F: - // LDRT rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x450: case 0x451: case 0x452: case 0x453: case 0x454: case 0x455: case 0x456: case 0x457: - case 0x458: case 0x459: case 0x45A: case 0x45B: case 0x45C: case 0x45D: case 0x45E: case 0x45F: - // LDRB rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x470: case 0x471: case 0x472: case 0x473: case 0x474: case 0x475: case 0x476: case 0x477: - case 0x478: case 0x479: case 0x47A: case 0x47B: case 0x47C: case 0x47D: case 0x47E: case 0x47F: - // LDRBT rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x490: case 0x491: case 0x492: case 0x493: case 0x494: case 0x495: case 0x496: case 0x497: - case 0x498: case 0x499: case 0x49A: case 0x49B: case 0x49C: case 0x49D: case 0x49E: case 0x49F: - // LDR rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += this.curInstruction & 0xFFF; - break; - - case 0x4B0: case 0x4B1: case 0x4B2: case 0x4B3: case 0x4B4: case 0x4B5: case 0x4B6: case 0x4B7: - case 0x4B8: case 0x4B9: case 0x4BA: case 0x4BB: case 0x4BC: case 0x4BD: case 0x4BE: case 0x4BF: - // LDRT rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += this.curInstruction & 0xFFF; - break; - - case 0x4D0: case 0x4D1: case 0x4D2: case 0x4D3: case 0x4D4: case 0x4D5: case 0x4D6: case 0x4D7: - case 0x4D8: case 0x4D9: case 0x4DA: case 0x4DB: case 0x4DC: case 0x4DD: case 0x4DE: case 0x4DF: - // LDRB rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += this.curInstruction & 0xFFF; - break; - - case 0x4F0: case 0x4F1: case 0x4F2: case 0x4F3: case 0x4F4: case 0x4F5: case 0x4F6: case 0x4F7: - case 0x4F8: case 0x4F9: case 0x4FA: case 0x4FB: case 0x4FC: case 0x4FD: case 0x4FE: case 0x4FF: - // LDRBT rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += this.curInstruction & 0xFFF; - break; - - case 0x510: case 0x511: case 0x512: case 0x513: case 0x514: case 0x515: case 0x516: case 0x517: - case 0x518: case 0x519: case 0x51A: case 0x51B: case 0x51C: case 0x51D: case 0x51E: case 0x51F: - // LDR rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x530: case 0x531: case 0x532: case 0x533: case 0x534: case 0x535: case 0x536: case 0x537: - case 0x538: case 0x539: case 0x53A: case 0x53B: case 0x53C: case 0x53D: case 0x53E: case 0x53F: - // LDR rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x550: case 0x551: case 0x552: case 0x553: case 0x554: case 0x555: case 0x556: case 0x557: - case 0x558: case 0x559: case 0x55A: case 0x55B: case 0x55C: case 0x55D: case 0x55E: case 0x55F: - // LDRB rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x570: case 0x571: case 0x572: case 0x573: case 0x574: case 0x575: case 0x576: case 0x577: - case 0x578: case 0x579: case 0x57A: case 0x57B: case 0x57C: case 0x57D: case 0x57E: case 0x57F: - // LDRB rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x590: case 0x591: case 0x592: case 0x593: case 0x594: case 0x595: case 0x596: case 0x597: - case 0x598: case 0x599: case 0x59A: case 0x59B: case 0x59C: case 0x59D: case 0x59E: case 0x59F: - // LDR rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + (this.curInstruction & 0xFFF)); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x5B0: case 0x5B1: case 0x5B2: case 0x5B3: case 0x5B4: case 0x5B5: case 0x5B6: case 0x5B7: - case 0x5B8: case 0x5B9: case 0x5BA: case 0x5BB: case 0x5BC: case 0x5BD: case 0x5BE: case 0x5BF: - // LDR rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.curInstruction & 0xFFF; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x5D0: case 0x5D1: case 0x5D2: case 0x5D3: case 0x5D4: case 0x5D5: case 0x5D6: case 0x5D7: - case 0x5D8: case 0x5D9: case 0x5DA: case 0x5DB: case 0x5DC: case 0x5DD: case 0x5DE: case 0x5DF: - // LDRB rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + (this.curInstruction & 0xFFF)); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x5F0: case 0x5F1: case 0x5F2: case 0x5F3: case 0x5F4: case 0x5F5: case 0x5F6: case 0x5F7: - case 0x5F8: case 0x5F9: case 0x5FA: case 0x5FB: case 0x5FC: case 0x5FD: case 0x5FE: case 0x5FF: - // LDRB rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.curInstruction & 0xFFF; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // STR register shift implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x600: - case 0x608: - // STR rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x602: - case 0x60A: - // STR rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x604: - case 0x60C: - // STR rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x606: - case 0x60E: - // STR rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x620: - case 0x628: - // STRT rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x622: - case 0x62A: - // STRT rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x624: - case 0x62C: - // STRT rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x626: - case 0x62E: - // STRT rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - break; - - case 0x640: - case 0x648: - // STRB rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x642: - case 0x64A: - // STRB rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x644: - case 0x64C: - // STRB rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x646: - case 0x64E: - // STRB rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x660: - case 0x668: - // STRBT rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x662: - case 0x66A: - // STRBT rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x664: - case 0x66C: - // STRBT rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x666: - case 0x66E: - // STRBT rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - break; - - case 0x680: - case 0x688: - // STR rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterLslImmed(); - break; - - case 0x682: - case 0x68A: - // STR rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterLsrImmed(); - break; - - case 0x684: - case 0x68C: - // STR rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterAsrImmed(); - break; - - case 0x686: - case 0x68E: - // STR rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterRorImmed(); - break; - - case 0x6A0: - case 0x6A2: - // STRT rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterLslImmed(); - break; - - case 0x6A4: - case 0x6A6: - // STRT rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterLsrImmed(); - break; - - case 0x6A8: - case 0x6AA: - // STRT rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterAsrImmed(); - break; - - case 0x6AC: - case 0x6AE: - // STRT rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterRorImmed(); - break; - - case 0x6C0: - case 0x6C8: - // STRB rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterLslImmed(); - break; - - case 0x6C2: - case 0x6CA: - // STRB rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterLsrImmed(); - break; - - case 0x6C4: - case 0x6CC: - // STRB rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterAsrImmed(); - break; - - case 0x6C6: - case 0x6CE: - // STRB rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterRorImmed(); - break; - - case 0x6E0: - case 0x6E8: - // STRBT rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterLslImmed(); - break; - - case 0x6E2: - case 0x6EA: - // STRBT rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterLsrImmed(); - break; - - case 0x6E4: - case 0x6EC: - // STRBT rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterAsrImmed(); - break; - - case 0x6E6: - case 0x6EE: - // STRBT rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterRorImmed(); - break; - - case 0x700: - case 0x708: - // STR rd, [rn, -rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - break; - - case 0x702: - case 0x70A: - // STR rd, [rn, -rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - break; - - case 0x704: - case 0x70C: - // STR rd, [rn, -rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - break; - - case 0x706: - case 0x70E: - // STR rd, [rn, -rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - break; - - case 0x720: - case 0x728: - // STR rd, [rn, -rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x722: - case 0x72A: - // STR rd, [rn, -rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x724: - case 0x72C: - // STR rd, [rn, -rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x726: - case 0x72E: - // STR rd, [rn, -rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x740: - case 0x748: - // STRB rd, [rn, -rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - break; - - case 0x742: - case 0x74A: - // STRB rd, [rn, -rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - break; - - case 0x744: - case 0x74C: - // STRB rd, [rn, -rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - break; - - case 0x746: - case 0x74E: - // STRB rd, [rn, -rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - break; - - case 0x760: - case 0x768: - // STRB rd, [rn, -rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - case 0x762: - case 0x76A: - // STRB rd, [rn, -rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - case 0x764: - case 0x76C: - // STRB rd, [rn, -rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - case 0x766: - case 0x76E: - // STRB rd, [rn, -rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - case 0x780: - case 0x788: - // STR rd, [rn, rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + this.BarrelShifterLslImmed(), alu); - break; - - case 0x782: - case 0x78A: - // STR rd, [rn, rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + this.BarrelShifterLsrImmed(), alu); - break; - - case 0x784: - case 0x78C: - // STR rd, [rn, rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + this.BarrelShifterAsrImmed(), alu); - break; - - case 0x786: - case 0x78E: - // STR rd, [rn, rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + this.BarrelShifterRorImmed(), alu); - break; - - case 0x7A0: - case 0x7A8: - // STR rd, [rn, rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterLslImmed(); - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x7A2: - case 0x7AA: - // STR rd, [rn, rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterLsrImmed(); - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x7A4: - case 0x7AC: - // STR rd, [rn, rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterAsrImmed(); - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x7A6: - case 0x7AE: - // STR rd, [rn, rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterRorImmed(); - this.memory.WriteU32(registers[rn], alu); - break; - - case 0x7C0: - case 0x7C8: - // STRB rd, [rn, rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + this.BarrelShifterLslImmed(), (byte)(alu & 0xFF)); - break; - - case 0x7C2: - case 0x7CA: - // STRB rd, [rn, rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + this.BarrelShifterLsrImmed(), (byte)(alu & 0xFF)); - break; - - case 0x7C4: - case 0x7CC: - // STRB rd, [rn, rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + this.BarrelShifterAsrImmed(), (byte)(alu & 0xFF)); - break; - - case 0x7C6: - case 0x7CE: - // STRB rd, [rn, rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + this.BarrelShifterRorImmed(), (byte)(alu & 0xFF)); - break; - - case 0x7E0: - case 0x7E8: - // STRB rd, [rn, rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterLslImmed(); - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - case 0x7E2: - case 0x7EA: - // STRB rd, [rn, rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterLsrImmed(); - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - case 0x7E4: - case 0x7EC: - // STRB rd, [rn, rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterAsrImmed(); - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - case 0x7E6: - case 0x7EE: - // STRB rd, [rn, rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterRorImmed(); - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // LDR register shift implementations - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0x610: - case 0x618: - // LDR rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x612: - case 0x61A: - // LDR rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x614: - case 0x61C: - // LDR rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x616: - case 0x61E: - // LDR rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x630: - case 0x638: - // LDRT rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x632: - case 0x63A: - // LDRT rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x634: - case 0x63C: - // LDRT rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x636: - case 0x63E: - // LDRT rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x650: - case 0x658: - // LDRB rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x652: - case 0x65A: - // LDRB rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x654: - case 0x65C: - // LDRB rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x656: - case 0x65E: - // LDRB rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x670: - case 0x678: - // LDRBT rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x672: - case 0x67A: - // LDRBT rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x674: - case 0x67C: - // LDRBT rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x676: - case 0x67E: - // LDRBT rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x690: - case 0x698: - // LDR rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x692: - case 0x69A: - // LDR rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x694: - case 0x69C: - // LDR rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x696: - case 0x69E: - // LDR rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6B0: - case 0x6B8: - // LDRT rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6B2: - case 0x6BA: - // LDRT rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6B4: - case 0x6BC: - // LDRT rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6B6: - case 0x6BE: - // LDRT rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6D0: - case 0x6D8: - // LDRB rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6D2: - case 0x6DA: - // LDRB rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6D4: - case 0x6DC: - // LDRB rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6D6: - case 0x6DE: - // LDRB rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6F0: - case 0x6F8: - // LDRBT rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6F2: - case 0x6FA: - // LDRBT rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6F4: - case 0x6FC: - // LDRBT rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x6F6: - case 0x6FE: - // LDRBT rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - break; - - case 0x710: - case 0x718: - // LDR rd, [rn, -rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x712: - case 0x71A: - // LDR rd, [rn, -rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x714: - case 0x71C: - // LDR rd, [rn, -rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x716: - case 0x71E: - // LDR rd, [rn, -rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x730: - case 0x738: - // LDR rd, [rn, -rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x732: - case 0x73A: - // LDR rd, [rn, -rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x734: - case 0x73C: - // LDR rd, [rn, -rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x736: - case 0x73E: - // LDR rd, [rn, -rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x750: - case 0x758: - // LDRB rd, [rn, -rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x752: - case 0x75A: - // LDRB rd, [rn, -rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x754: - case 0x75C: - // LDRB rd, [rn, -rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x756: - case 0x75E: - // LDRB rd, [rn, -rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x770: - case 0x778: - // LDRB rd, [rn, -rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x772: - case 0x77A: - // LDRB rd, [rn, -rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x774: - case 0x77C: - // LDRB rd, [rn, -rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x776: - case 0x77E: - // LDRB rd, [rn, -rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x790: - case 0x798: - // LDR rd, [rn, rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterLslImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x792: - case 0x79A: - // LDR rd, [rn, rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterLsrImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x794: - case 0x79C: - // LDR rd, [rn, rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterAsrImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x796: - case 0x79E: - // LDR rd, [rn, rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterRorImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7B0: - case 0x7B8: - // LDR rd, [rn, rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7B2: - case 0x7BA: - // LDR rd, [rn, rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7B4: - case 0x7BC: - // LDR rd, [rn, rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7B6: - case 0x7BE: - // LDR rd, [rn, rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7D0: - case 0x7D8: - // LDRB rd, [rn, rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterLslImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7D2: - case 0x7DA: - // LDRB rd, [rn, rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterLsrImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7D4: - case 0x7DC: - // LDRB rd, [rn, rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterAsrImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7D6: - case 0x7DE: - // LDRB rd, [rn, rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterRorImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7F0: - case 0x7F8: - // LDRB rd, [rn, rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7F2: - case 0x7FA: - // LDRB rd, [rn, rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7F4: - case 0x7FC: - // LDRB rd, [rn, rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - case 0x7F6: - case 0x7FE: - // LDRB rd, [rn, rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // LDM implementations (TODO) - // - //////////////////////////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // STM implementations (TODO) - // - //////////////////////////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // B implementation - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0xA00: case 0xA01: case 0xA02: case 0xA03: case 0xA04: case 0xA05: case 0xA06: case 0xA07: - case 0xA08: case 0xA09: case 0xA0A: case 0xA0B: case 0xA0C: case 0xA0D: case 0xA0E: case 0xA0F: - case 0xA10: case 0xA11: case 0xA12: case 0xA13: case 0xA14: case 0xA15: case 0xA16: case 0xA17: - case 0xA18: case 0xA19: case 0xA1A: case 0xA1B: case 0xA1C: case 0xA1D: case 0xA1E: case 0xA1F: - case 0xA20: case 0xA21: case 0xA22: case 0xA23: case 0xA24: case 0xA25: case 0xA26: case 0xA27: - case 0xA28: case 0xA29: case 0xA2A: case 0xA2B: case 0xA2C: case 0xA2D: case 0xA2E: case 0xA2F: - case 0xA30: case 0xA31: case 0xA32: case 0xA33: case 0xA34: case 0xA35: case 0xA36: case 0xA37: - case 0xA38: case 0xA39: case 0xA3A: case 0xA3B: case 0xA3C: case 0xA3D: case 0xA3E: case 0xA3F: - case 0xA40: case 0xA41: case 0xA42: case 0xA43: case 0xA44: case 0xA45: case 0xA46: case 0xA47: - case 0xA48: case 0xA49: case 0xA4A: case 0xA4B: case 0xA4C: case 0xA4D: case 0xA4E: case 0xA4F: - case 0xA50: case 0xA51: case 0xA52: case 0xA53: case 0xA54: case 0xA55: case 0xA56: case 0xA57: - case 0xA58: case 0xA59: case 0xA5A: case 0xA5B: case 0xA5C: case 0xA5D: case 0xA5E: case 0xA5F: - case 0xA60: case 0xA61: case 0xA62: case 0xA63: case 0xA64: case 0xA65: case 0xA66: case 0xA67: - case 0xA68: case 0xA69: case 0xA6A: case 0xA6B: case 0xA6C: case 0xA6D: case 0xA6E: case 0xA6F: - case 0xA70: case 0xA71: case 0xA72: case 0xA73: case 0xA74: case 0xA75: case 0xA76: case 0xA77: - case 0xA78: case 0xA79: case 0xA7A: case 0xA7B: case 0xA7C: case 0xA7D: case 0xA7E: case 0xA7F: - case 0xA80: case 0xA81: case 0xA82: case 0xA83: case 0xA84: case 0xA85: case 0xA86: case 0xA87: - case 0xA88: case 0xA89: case 0xA8A: case 0xA8B: case 0xA8C: case 0xA8D: case 0xA8E: case 0xA8F: - case 0xA90: case 0xA91: case 0xA92: case 0xA93: case 0xA94: case 0xA95: case 0xA96: case 0xA97: - case 0xA98: case 0xA99: case 0xA9A: case 0xA9B: case 0xA9C: case 0xA9D: case 0xA9E: case 0xA9F: - case 0xAA0: case 0xAA1: case 0xAA2: case 0xAA3: case 0xAA4: case 0xAA5: case 0xAA6: case 0xAA7: - case 0xAA8: case 0xAA9: case 0xAAA: case 0xAAB: case 0xAAC: case 0xAAD: case 0xAAE: case 0xAAF: - case 0xAB0: case 0xAB1: case 0xAB2: case 0xAB3: case 0xAB4: case 0xAB5: case 0xAB6: case 0xAB7: - case 0xAB8: case 0xAB9: case 0xABA: case 0xABB: case 0xABC: case 0xABD: case 0xABE: case 0xABF: - case 0xAC0: case 0xAC1: case 0xAC2: case 0xAC3: case 0xAC4: case 0xAC5: case 0xAC6: case 0xAC7: - case 0xAC8: case 0xAC9: case 0xACA: case 0xACB: case 0xACC: case 0xACD: case 0xACE: case 0xACF: - case 0xAD0: case 0xAD1: case 0xAD2: case 0xAD3: case 0xAD4: case 0xAD5: case 0xAD6: case 0xAD7: - case 0xAD8: case 0xAD9: case 0xADA: case 0xADB: case 0xADC: case 0xADD: case 0xADE: case 0xADF: - case 0xAE0: case 0xAE1: case 0xAE2: case 0xAE3: case 0xAE4: case 0xAE5: case 0xAE6: case 0xAE7: - case 0xAE8: case 0xAE9: case 0xAEA: case 0xAEB: case 0xAEC: case 0xAED: case 0xAEE: case 0xAEF: - case 0xAF0: case 0xAF1: case 0xAF2: case 0xAF3: case 0xAF4: case 0xAF5: case 0xAF6: case 0xAF7: - case 0xAF8: case 0xAF9: case 0xAFA: case 0xAFB: case 0xAFC: case 0xAFD: case 0xAFE: case 0xAFF: - { - uint branchOffset = this.curInstruction & 0x00FFFFFF; - if (branchOffset >> 23 == 1) branchOffset |= 0xFF000000; - - this.registers[15] += branchOffset << 2; - - this.FlushQueue(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // BL implementation - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0xB00: case 0xB01: case 0xB02: case 0xB03: case 0xB04: case 0xB05: case 0xB06: case 0xB07: - case 0xB08: case 0xB09: case 0xB0A: case 0xB0B: case 0xB0C: case 0xB0D: case 0xB0E: case 0xB0F: - case 0xB10: case 0xB11: case 0xB12: case 0xB13: case 0xB14: case 0xB15: case 0xB16: case 0xB17: - case 0xB18: case 0xB19: case 0xB1A: case 0xB1B: case 0xB1C: case 0xB1D: case 0xB1E: case 0xB1F: - case 0xB20: case 0xB21: case 0xB22: case 0xB23: case 0xB24: case 0xB25: case 0xB26: case 0xB27: - case 0xB28: case 0xB29: case 0xB2A: case 0xB2B: case 0xB2C: case 0xB2D: case 0xB2E: case 0xB2F: - case 0xB30: case 0xB31: case 0xB32: case 0xB33: case 0xB34: case 0xB35: case 0xB36: case 0xB37: - case 0xB38: case 0xB39: case 0xB3A: case 0xB3B: case 0xB3C: case 0xB3D: case 0xB3E: case 0xB3F: - case 0xB40: case 0xB41: case 0xB42: case 0xB43: case 0xB44: case 0xB45: case 0xB46: case 0xB47: - case 0xB48: case 0xB49: case 0xB4A: case 0xB4B: case 0xB4C: case 0xB4D: case 0xB4E: case 0xB4F: - case 0xB50: case 0xB51: case 0xB52: case 0xB53: case 0xB54: case 0xB55: case 0xB56: case 0xB57: - case 0xB58: case 0xB59: case 0xB5A: case 0xB5B: case 0xB5C: case 0xB5D: case 0xB5E: case 0xB5F: - case 0xB60: case 0xB61: case 0xB62: case 0xB63: case 0xB64: case 0xB65: case 0xB66: case 0xB67: - case 0xB68: case 0xB69: case 0xB6A: case 0xB6B: case 0xB6C: case 0xB6D: case 0xB6E: case 0xB6F: - case 0xB70: case 0xB71: case 0xB72: case 0xB73: case 0xB74: case 0xB75: case 0xB76: case 0xB77: - case 0xB78: case 0xB79: case 0xB7A: case 0xB7B: case 0xB7C: case 0xB7D: case 0xB7E: case 0xB7F: - case 0xB80: case 0xB81: case 0xB82: case 0xB83: case 0xB84: case 0xB85: case 0xB86: case 0xB87: - case 0xB88: case 0xB89: case 0xB8A: case 0xB8B: case 0xB8C: case 0xB8D: case 0xB8E: case 0xB8F: - case 0xB90: case 0xB91: case 0xB92: case 0xB93: case 0xB94: case 0xB95: case 0xB96: case 0xB97: - case 0xB98: case 0xB99: case 0xB9A: case 0xB9B: case 0xB9C: case 0xB9D: case 0xB9E: case 0xB9F: - case 0xBA0: case 0xBA1: case 0xBA2: case 0xBA3: case 0xBA4: case 0xBA5: case 0xBA6: case 0xBA7: - case 0xBA8: case 0xBA9: case 0xBAA: case 0xBAB: case 0xBAC: case 0xBAD: case 0xBAE: case 0xBAF: - case 0xBB0: case 0xBB1: case 0xBB2: case 0xBB3: case 0xBB4: case 0xBB5: case 0xBB6: case 0xBB7: - case 0xBB8: case 0xBB9: case 0xBBA: case 0xBBB: case 0xBBC: case 0xBBD: case 0xBBE: case 0xBBF: - case 0xBC0: case 0xBC1: case 0xBC2: case 0xBC3: case 0xBC4: case 0xBC5: case 0xBC6: case 0xBC7: - case 0xBC8: case 0xBC9: case 0xBCA: case 0xBCB: case 0xBCC: case 0xBCD: case 0xBCE: case 0xBCF: - case 0xBD0: case 0xBD1: case 0xBD2: case 0xBD3: case 0xBD4: case 0xBD5: case 0xBD6: case 0xBD7: - case 0xBD8: case 0xBD9: case 0xBDA: case 0xBDB: case 0xBDC: case 0xBDD: case 0xBDE: case 0xBDF: - case 0xBE0: case 0xBE1: case 0xBE2: case 0xBE3: case 0xBE4: case 0xBE5: case 0xBE6: case 0xBE7: - case 0xBE8: case 0xBE9: case 0xBEA: case 0xBEB: case 0xBEC: case 0xBED: case 0xBEE: case 0xBEF: - case 0xBF0: case 0xBF1: case 0xBF2: case 0xBF3: case 0xBF4: case 0xBF5: case 0xBF6: case 0xBF7: - case 0xBF8: case 0xBF9: case 0xBFA: case 0xBFB: case 0xBFC: case 0xBFD: case 0xBFE: case 0xBFF: - { - uint branchOffset = this.curInstruction & 0x00FFFFFF; - if (branchOffset >> 23 == 1) branchOffset |= 0xFF000000; - - this.registers[14] = this.registers[15] - 4U; - this.registers[15] += branchOffset << 2; - - this.FlushQueue(); - } - break; - - //////////////////////////////////////////////////////////////////////////////////////////// - // - // SWI implementation - // - //////////////////////////////////////////////////////////////////////////////////////////// - case 0xF00: case 0xF01: case 0xF02: case 0xF03: case 0xF04: case 0xF05: case 0xF06: case 0xF07: - case 0xF08: case 0xF09: case 0xF0A: case 0xF0B: case 0xF0C: case 0xF0D: case 0xF0E: case 0xF0F: - case 0xF10: case 0xF11: case 0xF12: case 0xF13: case 0xF14: case 0xF15: case 0xF16: case 0xF17: - case 0xF18: case 0xF19: case 0xF1A: case 0xF1B: case 0xF1C: case 0xF1D: case 0xF1E: case 0xF1F: - case 0xF20: case 0xF21: case 0xF22: case 0xF23: case 0xF24: case 0xF25: case 0xF26: case 0xF27: - case 0xF28: case 0xF29: case 0xF2A: case 0xF2B: case 0xF2C: case 0xF2D: case 0xF2E: case 0xF2F: - case 0xF30: case 0xF31: case 0xF32: case 0xF33: case 0xF34: case 0xF35: case 0xF36: case 0xF37: - case 0xF38: case 0xF39: case 0xF3A: case 0xF3B: case 0xF3C: case 0xF3D: case 0xF3E: case 0xF3F: - case 0xF40: case 0xF41: case 0xF42: case 0xF43: case 0xF44: case 0xF45: case 0xF46: case 0xF47: - case 0xF48: case 0xF49: case 0xF4A: case 0xF4B: case 0xF4C: case 0xF4D: case 0xF4E: case 0xF4F: - case 0xF50: case 0xF51: case 0xF52: case 0xF53: case 0xF54: case 0xF55: case 0xF56: case 0xF57: - case 0xF58: case 0xF59: case 0xF5A: case 0xF5B: case 0xF5C: case 0xF5D: case 0xF5E: case 0xF5F: - case 0xF60: case 0xF61: case 0xF62: case 0xF63: case 0xF64: case 0xF65: case 0xF66: case 0xF67: - case 0xF68: case 0xF69: case 0xF6A: case 0xF6B: case 0xF6C: case 0xF6D: case 0xF6E: case 0xF6F: - case 0xF70: case 0xF71: case 0xF72: case 0xF73: case 0xF74: case 0xF75: case 0xF76: case 0xF77: - case 0xF78: case 0xF79: case 0xF7A: case 0xF7B: case 0xF7C: case 0xF7D: case 0xF7E: case 0xF7F: - case 0xF80: case 0xF81: case 0xF82: case 0xF83: case 0xF84: case 0xF85: case 0xF86: case 0xF87: - case 0xF88: case 0xF89: case 0xF8A: case 0xF8B: case 0xF8C: case 0xF8D: case 0xF8E: case 0xF8F: - case 0xF90: case 0xF91: case 0xF92: case 0xF93: case 0xF94: case 0xF95: case 0xF96: case 0xF97: - case 0xF98: case 0xF99: case 0xF9A: case 0xF9B: case 0xF9C: case 0xF9D: case 0xF9E: case 0xF9F: - case 0xFA0: case 0xFA1: case 0xFA2: case 0xFA3: case 0xFA4: case 0xFA5: case 0xFA6: case 0xFA7: - case 0xFA8: case 0xFA9: case 0xFAA: case 0xFAB: case 0xFAC: case 0xFAD: case 0xFAE: case 0xFAF: - case 0xFB0: case 0xFB1: case 0xFB2: case 0xFB3: case 0xFB4: case 0xFB5: case 0xFB6: case 0xFB7: - case 0xFB8: case 0xFB9: case 0xFBA: case 0xFBB: case 0xFBC: case 0xFBD: case 0xFBE: case 0xFBF: - case 0xFC0: case 0xFC1: case 0xFC2: case 0xFC3: case 0xFC4: case 0xFC5: case 0xFC6: case 0xFC7: - case 0xFC8: case 0xFC9: case 0xFCA: case 0xFCB: case 0xFCC: case 0xFCD: case 0xFCE: case 0xFCF: - case 0xFD0: case 0xFD1: case 0xFD2: case 0xFD3: case 0xFD4: case 0xFD5: case 0xFD6: case 0xFD7: - case 0xFD8: case 0xFD9: case 0xFDA: case 0xFDB: case 0xFDC: case 0xFDD: case 0xFDE: case 0xFDF: - case 0xFE0: case 0xFE1: case 0xFE2: case 0xFE3: case 0xFE4: case 0xFE5: case 0xFE6: case 0xFE7: - case 0xFE8: case 0xFE9: case 0xFEA: case 0xFEB: case 0xFEC: case 0xFED: case 0xFEE: case 0xFEF: - case 0xFF0: case 0xFF1: case 0xFF2: case 0xFF3: case 0xFF4: case 0xFF5: case 0xFF6: case 0xFF7: - case 0xFF8: case 0xFF9: case 0xFFA: case 0xFFB: case 0xFFC: case 0xFFD: case 0xFFE: case 0xFFF: - this.registers[15] -= 4U; - this.parent.EnterException(Arm7Processor.SVC, 0x8, false, false); - break; - - default: - this.NormalOps[(curInstruction >> 25) & 0x7](); - break; - } - } - - #region Barrel Shifter - private const uint SHIFT_LSL = 0; - private const uint SHIFT_LSR = 1; - private const uint SHIFT_ASR = 2; - private const uint SHIFT_ROR = 3; - - private uint BarrelShifter(uint shifterOperand) - { - uint type = (shifterOperand >> 5) & 0x3; - - bool registerShift = (shifterOperand & (1 << 4)) == (1 << 4); - - uint rm = registers[shifterOperand & 0xF]; - - int amount; - if (registerShift) - { - uint rs = (shifterOperand >> 8) & 0xF; - if (rs == 15) - { - amount = (int)((registers[rs] + 0x4) & 0xFF); - } - else - { - amount = (int)(registers[rs] & 0xFF); - } - - if ((shifterOperand & 0xF) == 15) - { - rm += 4; - } - } - else - { - amount = (int)((shifterOperand >> 7) & 0x1F); - } - - if (registerShift) - { - if (amount == 0) - { - this.shifterCarry = this.carry; - return rm; - } - - switch (type) - { - case SHIFT_LSL: - if (amount < 32) - { - this.shifterCarry = (rm >> (32 - amount)) & 1; - return rm << amount; - } - else if (amount == 32) - { - this.shifterCarry = rm & 1; - return 0; - } - else - { - this.shifterCarry = 0; - return 0; - } - - case SHIFT_LSR: - if (amount < 32) - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return rm >> amount; - } - else if (amount == 32) - { - this.shifterCarry = (rm >> 31) & 1; - return 0; - } - else - { - this.shifterCarry = 0; - return 0; - } - - case SHIFT_ASR: - if (amount >= 32) - { - if ((rm & (1 << 31)) == 0) - { - this.shifterCarry = 0; - return 0; - } - else - { - this.shifterCarry = 1; - return 0xFFFFFFFF; - } - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return (uint)(((int)rm) >> amount); - } - - case SHIFT_ROR: - if ((amount & 0x1F) == 0) - { - this.shifterCarry = (rm >> 31) & 1; - return rm; - } - else - { - amount &= 0x1F; - this.shifterCarry = (rm >> amount) & 1; - return (rm >> amount) | (rm << (32 - amount)); - } - } - } - else - { - switch (type) - { - case SHIFT_LSL: - if (amount == 0) - { - this.shifterCarry = this.carry; - return rm; - } - else - { - this.shifterCarry = (rm >> (32 - amount)) & 1; - return rm << amount; - } - - case SHIFT_LSR: - if (amount == 0) - { - this.shifterCarry = (rm >> 31) & 1; - return 0; - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return rm >> amount; - } - - case SHIFT_ASR: - if (amount == 0) - { - if ((rm & (1 << 31)) == 0) - { - this.shifterCarry = 0; - return 0; - } - else - { - this.shifterCarry = 1; - return 0xFFFFFFFF; - } - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return (uint)(((int)rm) >> amount); - } - - case SHIFT_ROR: - if (amount == 0) - { - // Actually an RRX - this.shifterCarry = rm & 1; - return (this.carry << 31) | (rm >> 1); - } - else - { - this.shifterCarry = (rm >> (amount - 1)) & 1; - return (rm >> amount) | (rm << (32 - amount)); - } - } - } - - // Should never happen... - throw new Exception("Barrel Shifter has messed up."); - } - #endregion - - #region Flag helpers - public void OverflowCarryAdd(uint a, uint b, uint r) - { - overflow = ((a & b & ~r) | (~a & ~b & r)) >> 31; - carry = ((a & b) | (a & ~r) | (b & ~r)) >> 31; - } - - public void OverflowCarrySub(uint a, uint b, uint r) - { - overflow = ((a & ~b & ~r) | (~a & b & r)) >> 31; - carry = ((a & ~b) | (a & ~r) | (~b & ~r)) >> 31; - } - #endregion - #region Opcodes - private void DoDataProcessing(uint shifterOperand) - { - uint rn = (this.curInstruction >> 16) & 0xF; - uint rd = (this.curInstruction >> 12) & 0xF; - uint alu; - - bool registerShift = (this.curInstruction & (1 << 4)) == (1 << 4); - if (rn == 15 && ((this.curInstruction >> 25) & 0x7) == 0 && registerShift) - { - rn = registers[rn] + 4; - } - else - { - rn = registers[rn]; - } - - uint opcode = (this.curInstruction >> 21) & 0xF; - - if (((this.curInstruction >> 20) & 1) == 1) - { - // Set flag bit set - switch (opcode) - { - case OP_ADC: - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - break; - - case OP_ADD: - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - break; - - case OP_AND: - registers[rd] = rn & shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_BIC: - registers[rd] = rn & ~shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_CMN: - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - break; - - case OP_CMP: - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - break; - - case OP_EOR: - registers[rd] = rn ^ shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_MOV: - registers[rd] = shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_MVN: - registers[rd] = ~shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_ORR: - registers[rd] = rn | shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_RSB: - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - break; - - case OP_RSC: - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - break; - - case OP_SBC: - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - break; - - case OP_SUB: - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - break; - - case OP_TEQ: - alu = rn ^ shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - - case OP_TST: - alu = rn & shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - break; - } - - if (rd == 15) - { - // Prevent writing if no SPSR exists (this will be true for USER or SYSTEM mode) - if (this.parent.SPSRExists) this.parent.WriteCpsr(this.parent.SPSR); - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - - // Otherwise, flush the instruction queue - this.FlushQueue(); - } - } - else - { - // Set flag bit not set - switch (opcode) - { - case OP_ADC: registers[rd] = rn + shifterOperand + carry; break; - case OP_ADD: registers[rd] = rn + shifterOperand; break; - case OP_AND: registers[rd] = rn & shifterOperand; break; - case OP_BIC: registers[rd] = rn & ~shifterOperand; break; - case OP_EOR: registers[rd] = rn ^ shifterOperand; break; - case OP_MOV: registers[rd] = shifterOperand; break; - case OP_MVN: registers[rd] = ~shifterOperand; break; - case OP_ORR: registers[rd] = rn | shifterOperand; break; - case OP_RSB: registers[rd] = shifterOperand - rn; break; - case OP_RSC: registers[rd] = shifterOperand - rn - (1U - carry); break; - case OP_SBC: registers[rd] = rn - shifterOperand - (1U - carry); break; - case OP_SUB: registers[rd] = rn - shifterOperand; break; - - case OP_CMN: - // MSR SPSR, shifterOperand - if ((this.curInstruction & (1 << 16)) == 1 << 16 && this.parent.SPSRExists) - { - this.parent.SPSR &= 0xFFFFFF00; - this.parent.SPSR |= shifterOperand & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17 && this.parent.SPSRExists) - { - this.parent.SPSR &= 0xFFFF00FF; - this.parent.SPSR |= shifterOperand & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18 && this.parent.SPSRExists) - { - this.parent.SPSR &= 0xFF00FFFF; - this.parent.SPSR |= shifterOperand & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19 && this.parent.SPSRExists) - { - this.parent.SPSR &= 0x00FFFFFF; - this.parent.SPSR |= shifterOperand & 0xFF000000; - } - - // Queue will be flushed since rd == 15, so adjust the PC - registers[15] -= 4; - break; - - case OP_CMP: - // MRS rd, SPSR - if (this.parent.SPSRExists) registers[rd] = this.parent.SPSR; - break; - - case OP_TEQ: - if (((this.curInstruction >> 4) & 0xf) == 1) - { - // BX - uint rm = this.curInstruction & 0xf; - - this.PackFlags(); - - this.parent.CPSR &= ~Arm7Processor.T_MASK; - this.parent.CPSR |= (registers[rm] & 1) << Arm7Processor.T_BIT; - - registers[15] = registers[rm] & (~1U); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - - // Queue will be flushed later because rd == 15 - } - else if (((this.curInstruction >> 4) & 0xf) == 0) - { - // MSR CPSR, shifterOperand - bool userMode = (this.parent.CPSR & 0x1F) == Arm7Processor.USR; - - this.PackFlags(); - - uint tmpCPSR = this.parent.CPSR; - - if ((this.curInstruction & (1 << 16)) == 1 << 16 && !userMode) - { - tmpCPSR &= 0xFFFFFF00; - tmpCPSR |= shifterOperand & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17 && !userMode) - { - tmpCPSR &= 0xFFFF00FF; - tmpCPSR |= shifterOperand & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18 && !userMode) - { - tmpCPSR &= 0xFF00FFFF; - tmpCPSR |= shifterOperand & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - tmpCPSR &= 0x00FFFFFF; - tmpCPSR |= shifterOperand & 0xFF000000; - } - - this.parent.WriteCpsr(tmpCPSR); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - - // Queue will be flushed since rd == 15, so adjust the PC - registers[15] -= 4; - } - break; - - case OP_TST: - // MRS rd, CPSR - this.PackFlags(); - registers[rd] = this.parent.CPSR; - break; - } - - if (rd == 15) - { - // Flush the queue - this.FlushQueue(); - } - } - } - - private void DataProcessing() - { - // Special instruction - switch ((this.curInstruction >> 4) & 0xF) - { - case 0x9: - // Multiply or swap instructions - this.MultiplyOrSwap(); - return; - case 0xB: - // Load/Store Unsigned halfword - this.LoadStoreHalfword(); - return; - case 0xD: - // Load/Store Signed byte - this.LoadStoreHalfword(); - return; - case 0xF: - // Load/Store Signed halfword - this.LoadStoreHalfword(); - return; - } - - this.DoDataProcessing(this.BarrelShifter(this.curInstruction)); - } - - private void DataProcessingImmed() - { - uint immed = this.curInstruction & 0xFF; - int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2); - - immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount)); - - if (rotateAmount == 0) - { - this.shifterCarry = this.carry; - } - else - { - this.shifterCarry = (immed >> 31) & 1; - } - - this.DoDataProcessing(immed); - } - - private void LoadStore(uint offset) - { - uint rn = (this.curInstruction >> 16) & 0xF; - uint rd = (this.curInstruction >> 12) & 0xF; - - uint address = registers[rn]; - - bool preIndexed = (this.curInstruction & (1 << 24)) == 1 << 24; - bool byteTransfer = (this.curInstruction & (1 << 22)) == 1 << 22; - bool writeback = (this.curInstruction & (1 << 21)) == 1 << 21; - - // Add or subtract offset - if ((this.curInstruction & (1 << 23)) != 1 << 23) offset = (uint)-offset; - - if (preIndexed) - { - address += offset; - - if (writeback) - { - registers[rn] = address; - } - } - - if ((this.curInstruction & (1 << 20)) == 1 << 20) - { - // Load - if (byteTransfer) - { - registers[rd] = this.memory.ReadU8(address); - } - else - { - registers[rd] = this.memory.ReadU32(address); - } - - // ARM9 fix here - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (!preIndexed) - { - if (rn != rd) - registers[rn] = address + offset; - } - } - else - { - // Store - uint amount = registers[rd]; - if (rd == 15) amount += 4; - - if (byteTransfer) - { - this.memory.WriteU8(address, (byte)(amount & 0xFF)); - } - else - { - this.memory.WriteU32(address, amount); - } - - if (!preIndexed) - { - registers[rn] = address + offset; - } - } - } - - private void LoadStoreImmediate() - { - this.LoadStore(this.curInstruction & 0xFFF); - } - - private void LoadStoreRegister() - { - // The barrel shifter expects a 0 in bit 4 for immediate shifts, this is implicit in - // the meaning of the instruction, so it is fine - this.LoadStore(this.BarrelShifter(this.curInstruction)); - } - - private void LoadStoreMultiple() - { - uint rn = (this.curInstruction >> 16) & 0xF; - - this.PackFlags(); - uint curCpsr = this.parent.CPSR; - - bool preIncrement = (this.curInstruction & (1 << 24)) != 0; - bool up = (this.curInstruction & (1 << 23)) != 0; - bool writeback = (this.curInstruction & (1 << 21)) != 0; - - uint address; - uint bitsSet = 0; - for (int i = 0; i < 16; i++) if (((this.curInstruction >> i) & 1) != 0) bitsSet++; - - if (preIncrement) - { - if (up) - { - // Increment before - address = this.registers[rn] + 4; - if (writeback) this.registers[rn] += bitsSet * 4; - } - else - { - // Decrement before - address = this.registers[rn] - (bitsSet * 4); - if (writeback) this.registers[rn] -= bitsSet * 4; - } - } - else - { - if (up) - { - // Increment after - address = this.registers[rn]; - if (writeback) this.registers[rn] += bitsSet * 4; - } - else - { - // Decrement after - address = this.registers[rn] - (bitsSet * 4) + 4; - if (writeback) this.registers[rn] -= bitsSet * 4; - } - } - - if ((this.curInstruction & (1 << 20)) != 0) - { - if ((this.curInstruction & (1 << 22)) != 0 && ((this.curInstruction >> 15) & 1) == 0) - { - // Switch to user mode temporarily - this.parent.WriteCpsr((curCpsr & ~0x1FU) | Arm7Processor.USR); - } - - // Load multiple - for (int i = 0; i < 15; i++) - { - if (((this.curInstruction >> i) & 1) != 1) continue; - this.registers[i] = this.memory.ReadU32Aligned(address & (~0x3U)); - address += 4; - } - - if (((this.curInstruction >> 15) & 1) == 1) - { - // Arm9 fix here - - this.registers[15] = this.memory.ReadU32Aligned(address & (~0x3U)); - - if ((this.curInstruction & (1 << 22)) != 0) - { - // Load the CPSR from the SPSR - if (this.parent.SPSRExists) - { - this.parent.WriteCpsr(this.parent.SPSR); - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - this.registers[15] &= ~0x1U; - return; - } - } - } - - this.registers[15] &= ~0x3U; - this.FlushQueue(); - } - else - { - if ((this.curInstruction & (1 << 22)) != 0) - { - // Switch back to the correct mode - this.parent.WriteCpsr(curCpsr); - this.UnpackFlags(); - - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - } - } - } - else - { - if ((this.curInstruction & (1 << 22)) != 0) - { - // Switch to user mode temporarily - this.parent.WriteCpsr((curCpsr & ~0x1FU) | Arm7Processor.USR); - } - -/* if (((this.curInstruction >> (int)rn) & 1) != 0 && writeback && - (this.curInstruction & ~(0xFFFFFFFF << (int)rn)) == 0) - { - // If the lowest register is also the writeback, we use the original value - // Does anybody do this???? - throw new Exception("Unhandled STM state"); - } - else*/ - { - // Store multiple - for (int i = 0; i < 15; i++) - { - if (((this.curInstruction >> i) & 1) == 0) continue; - this.memory.WriteU32(address, this.registers[i]); - address += 4; - } - - if (((this.curInstruction >> 15) & 1) != 0) - { - this.memory.WriteU32(address, this.registers[15] + 4U); - } - } - - if ((this.curInstruction & (1 << 22)) != 0) - { - // Switch back to the correct mode - this.parent.WriteCpsr(curCpsr); - this.UnpackFlags(); - } - } - } - - private void Branch() - { - if ((this.curInstruction & (1 << 24)) != 0) - { - this.registers[14] = (this.registers[15] - 4U) & ~3U; - } - - uint branchOffset = this.curInstruction & 0x00FFFFFF; - if (branchOffset >> 23 == 1) branchOffset |= 0xFF000000; - - this.registers[15] += branchOffset << 2; - - this.FlushQueue(); - } - - private void CoprocessorLoadStore() - { - throw new Exception("Unhandled opcode - coproc load/store"); - } - - private void SoftwareInterrupt() - { - // Adjust PC for prefetch - this.registers[15] -= 4U; - this.parent.EnterException(Arm7Processor.SVC, 0x8, false, false); - } - - private void MultiplyOrSwap() - { - if ((this.curInstruction & (1 << 24)) == 1 << 24) - { - // Swap instruction - uint rn = (this.curInstruction >> 16) & 0xF; - uint rd = (this.curInstruction >> 12) & 0xF; - uint rm = this.curInstruction & 0xF; - - if ((this.curInstruction & (1 << 22)) != 0) - { - // SWPB - byte tmp = this.memory.ReadU8(registers[rn]); - this.memory.WriteU8(registers[rn], (byte)(registers[rm] & 0xFF)); - registers[rd] = tmp; - } - else - { - // SWP - uint tmp = this.memory.ReadU32(registers[rn]); - this.memory.WriteU32(registers[rn], registers[rm]); - registers[rd] = tmp; - } - } - else - { - // Multiply instruction - switch ((this.curInstruction >> 21) & 0x7) - { - case 0: - case 1: - { - // Multiply/Multiply + Accumulate - uint rd = (this.curInstruction >> 16) & 0xF; - uint rn = registers[(this.curInstruction >> 12) & 0xF]; - uint rs = (this.curInstruction >> 8) & 0xF; - uint rm = this.curInstruction & 0xF; - - int cycles = 4; - // Multiply cycle calculations - if ((registers[rs] & 0xFFFFFF00) == 0 || (registers[rs] & 0xFFFFFF00) == 0xFFFFFF00) - { - cycles = 1; - } - else if ((registers[rs] & 0xFFFF0000) == 0 || (registers[rs] & 0xFFFF0000) == 0xFFFF0000) - { - cycles = 2; - } - else if ((registers[rs] & 0xFF000000) == 0 || (registers[rs] & 0xFF000000) == 0xFF000000) - { - cycles = 3; - } - - registers[rd] = registers[rs] * registers[rm]; - this.parent.Cycles -= cycles; - - if ((this.curInstruction & (1 << 21)) == 1 << 21) - { - registers[rd] += rn; - this.parent.Cycles -= 1; - } - - if ((this.curInstruction & (1 << 20)) == 1 << 20) - { - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - break; - } - - case 2: - case 3: - throw new Exception("Invalid multiply"); - - case 4: - case 5: - case 6: - case 7: - { - // Multiply/Signed Multiply Long - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - uint rs = (this.curInstruction >> 8) & 0xF; - uint rm = this.curInstruction & 0xF; - - int cycles = 5; - // Multiply cycle calculations - if ((registers[rs] & 0xFFFFFF00) == 0 || (registers[rs] & 0xFFFFFF00) == 0xFFFFFF00) - { - cycles = 2; - } - else if ((registers[rs] & 0xFFFF0000) == 0 || (registers[rs] & 0xFFFF0000) == 0xFFFF0000) - { - cycles = 3; - } - else if ((registers[rs] & 0xFF000000) == 0 || (registers[rs] & 0xFF000000) == 0xFF000000) - { - cycles = 4; - } - - this.parent.Cycles -= cycles; - - switch ((this.curInstruction >> 21) & 0x3) - { - case 0: - { - // UMULL - ulong result = ((ulong)registers[rm]) * registers[rs]; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - break; - } - case 1: - { - // UMLAL - ulong accum = (((ulong)registers[rdhi]) << 32) | registers[rdlo]; - ulong result = ((ulong)registers[rm]) * registers[rs]; - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - break; - } - case 2: - { - // SMULL - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - break; - } - case 3: - { - // SMLAL - long accum = (((long)((int)registers[rdhi])) << 32) | registers[rdlo]; - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - break; - } - } - - if ((this.curInstruction & (1 << 20)) == 1 << 20) - { - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - } - break; - } - } - } - } - - private void LoadStoreHalfword() - { - uint rn = (this.curInstruction >> 16) & 0xF; - uint rd = (this.curInstruction >> 12) & 0xF; - - uint address = registers[rn]; - - bool preIndexed = (this.curInstruction & (1 << 24)) != 0; - bool byteTransfer = (this.curInstruction & (1 << 5)) == 0; - bool signedTransfer = (this.curInstruction & (1 << 6)) != 0; - bool writeback = (this.curInstruction & (1 << 21)) != 0; - - uint offset; - if ((this.curInstruction & (1 << 22)) != 0) - { - // Immediate offset - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - } - else - { - // Register offset - offset = this.registers[this.curInstruction & 0xF]; - } - - // Add or subtract offset - if ((this.curInstruction & (1 << 23)) == 0) offset = (uint)-offset; - - if (preIndexed) - { - address += offset; - - if (writeback) - { - registers[rn] = address; - } - } - - if ((this.curInstruction & (1 << 20)) != 0) - { - // Load - if (byteTransfer) - { - if (signedTransfer) - { - registers[rd] = this.memory.ReadU8(address); - if ((registers[rd] & 0x80) != 0) - { - registers[rd] |= 0xFFFFFF00; - } - } - else - { - registers[rd] = this.memory.ReadU8(address); - } - } - else - { - if (signedTransfer) - { - registers[rd] = this.memory.ReadU16(address); - if ((registers[rd] & 0x8000) != 0) - { - registers[rd] |= 0xFFFF0000; - } - } - else - { - registers[rd] = this.memory.ReadU16(address); - } - } - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (!preIndexed) - { - if (rn != rd) - registers[rn] = address + offset; - } - } - else - { - // Store - if (byteTransfer) - { - this.memory.WriteU8(address, (byte)(registers[rd] & 0xFF)); - } - else - { - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - } - - if (!preIndexed) - { - registers[rn] = address + offset; - } - } - } - #endregion Opcodes - - private void PackFlags() - { - this.parent.CPSR &= 0x0FFFFFFF; - this.parent.CPSR |= this.negative << Arm7Processor.N_BIT; - this.parent.CPSR |= this.zero << Arm7Processor.Z_BIT; - this.parent.CPSR |= this.carry << Arm7Processor.C_BIT; - this.parent.CPSR |= this.overflow << Arm7Processor.V_BIT; - } - - private void UnpackFlags() - { - this.negative = (this.parent.CPSR >> Arm7Processor.N_BIT) & 1; - this.zero = (this.parent.CPSR >> Arm7Processor.Z_BIT) & 1; - this.carry = (this.parent.CPSR >> Arm7Processor.C_BIT) & 1; - this.overflow = (this.parent.CPSR >> Arm7Processor.V_BIT) & 1; - } - - private void FlushQueue() - { - this.instructionQueue = this.memory.ReadU32(registers[15]); - registers[15] += 4; - } - } -} \ No newline at end of file diff --git a/attic/GarboDev/FastDispatchCore.cs b/attic/GarboDev/FastDispatchCore.cs deleted file mode 100644 index cb2c5e6a0f..0000000000 --- a/attic/GarboDev/FastDispatchCore.cs +++ /dev/null @@ -1,8469 +0,0 @@ -namespace GarboDev -{ - partial class FastArmCore - { - #region Delegate Dispatcher - private void DispatchFunc0() - { - uint rn, rd; - // AND rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc1() - { - uint rn, rd; - // AND rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc2() - { - uint rn, rd; - // AND rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc3() - { - uint rn, rd; - // AND rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc4() - { - uint rn, rd; - // AND rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc5() - { - uint rn, rd; - // AND rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc6() - { - uint rn, rd; - // AND rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc7() - { - uint rn, rd; - // AND rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc8() - { - uint rn, rd; - // ANDS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc9() - { - uint rn, rd; - // ANDS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc10() - { - uint rn, rd; - // ANDS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc11() - { - uint rn, rd; - // ANDS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc12() - { - uint rn, rd; - // ANDS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc13() - { - uint rn, rd; - // ANDS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc14() - { - uint rn, rd; - // ANDS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc15() - { - uint rn, rd; - // ANDS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc16() - { - UndefinedInstruction(); - } - private void DispatchFunc17() - { - uint rd, rs, rm; - int cycles; - // MUL rd, rm, rs - rd = (this.curInstruction >> 16) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs); - - registers[rd] = registers[rs] * registers[rm]; - this.parent.Cycles -= cycles; - } - private void DispatchFunc18() - { - uint rd, rs, rm; - int cycles; - // MULS rd, rm, rs - rd = (this.curInstruction >> 16) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs); - - registers[rd] = registers[rs] * registers[rm]; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - - this.parent.Cycles -= cycles; - } - private void DispatchFunc19() - { - uint rn, rd, rs, rm; - int cycles; - // MLA rd, rm, rs, rn - rd = (this.curInstruction >> 16) & 0xF; - rn = registers[(this.curInstruction >> 12) & 0xF]; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs); - - registers[rd] = registers[rs] * registers[rm] + rn; - this.parent.Cycles -= cycles + 1; - } - private void DispatchFunc20() - { - uint rn, rd, rs, rm; - int cycles; - // MLAS rd, rm, rs - rd = (this.curInstruction >> 16) & 0xF; - rn = registers[(this.curInstruction >> 12) & 0xF]; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs); - - registers[rd] = registers[rs] * registers[rm] + rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - - this.parent.Cycles -= cycles + 1; - } - private void DispatchFunc21() - { - uint rs, rm; - int cycles; - // UMULL rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 1; - - ulong result = ((ulong)registers[rm]) * registers[rs]; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - this.parent.Cycles -= cycles; - } - } - private void DispatchFunc22() - { - uint rs, rm; - int cycles; - // UMULLS rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 1; - - ulong result = ((ulong)registers[rm]) * registers[rs]; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - - this.parent.Cycles -= cycles; - } - } - private void DispatchFunc23() - { - uint rs, rm; - int cycles; - // UMLAL rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 2; - - ulong accum = (((ulong)registers[rdhi]) << 32) | registers[rdlo]; - ulong result = ((ulong)registers[rm]) * registers[rs]; - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - this.parent.Cycles -= cycles; - } - } - private void DispatchFunc24() - { - uint rs, rm; - int cycles; - // UMLALS rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 2; - - ulong accum = (((ulong)registers[rdhi]) << 32) | registers[rdlo]; - ulong result = ((ulong)registers[rm]) * registers[rs]; - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - - this.parent.Cycles -= cycles; - } - } - private void DispatchFunc25() - { - uint rs, rm; - int cycles; - // SMULL rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 1; - - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - this.parent.Cycles -= cycles; - } - } - private void DispatchFunc26() - { - uint rs, rm; - int cycles; - // SMULLS rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 1; - - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - - this.parent.Cycles -= cycles; - } - } - private void DispatchFunc27() - { - uint rs, rm; - int cycles; - // SMLAL rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 2; - - long accum = (((long)((int)registers[rdhi])) << 32) | registers[rdlo]; - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - this.parent.Cycles -= cycles; - } - } - private void DispatchFunc28() - { - uint rs, rm; - int cycles; - // SMLALS rdlo, rdhi, rm, rs - { - uint rdhi = (this.curInstruction >> 16) & 0xF; - uint rdlo = (this.curInstruction >> 12) & 0xF; - rs = (this.curInstruction >> 8) & 0xF; - rm = this.curInstruction & 0xF; - - cycles = this.MultiplyCycleCalculation(rs) + 2; - - long accum = (((long)((int)registers[rdhi])) << 32) | registers[rdlo]; - long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs])); - result += accum; - registers[rdhi] = (uint)(result >> 32); - registers[rdlo] = (uint)(result & 0xFFFFFFFF); - - negative = registers[rdhi] >> 31; - zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U; - - this.parent.Cycles -= cycles; - } - } - private void DispatchFunc29() - { - uint rn, rd, address, offset; - // STRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - } - private void DispatchFunc30() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // STRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - } - private void DispatchFunc31() - { - uint rn, rd, address, offset; - // STRH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - } - private void DispatchFunc32() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // STRH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - } - private void DispatchFunc33() - { - uint rn, rd, address, offset; - // STRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - } - private void DispatchFunc34() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // STRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - } - private void DispatchFunc35() - { - uint rn, rd, address, offset; - // STRH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - } - private void DispatchFunc36() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // STRH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF)); - registers[rn] = address + offset; - } - private void DispatchFunc37() - { - uint rn, rd, offset; - // STRH rd, [rn, -rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF)); - } - private void DispatchFunc38() - { - uint rn, rd, offset; - // STRH rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rn] += offset; - this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF)); - } - private void DispatchFunc39() - { - uint rn, rd, offset; - // STRH rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF)); - } - private void DispatchFunc40() - { - uint rn, rd, offset; - // STRH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rn] += offset; - this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF)); - } - private void DispatchFunc41() - { - uint rn, rd, offset; - // STRH rd, [rn, rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF)); - } - private void DispatchFunc42() - { - uint rn, rd, offset; - // STRH rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rn] += offset; - this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF)); - } - private void DispatchFunc43() - { - uint rn, rd, offset; - // STRH rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF)); - } - private void DispatchFunc44() - { - uint rn, rd, offset; - // STRH rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rn] += offset; - this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF)); - } - private void DispatchFunc45() - { - uint rn, rd, address, offset; - // LDRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc46() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc47() - { - uint rn, rd, address, offset; - // LDRH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc48() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc49() - { - uint rn, rd, address, offset; - // LDRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc50() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc51() - { - uint rn, rd, address, offset; - // LDRH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc52() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc53() - { - uint rn, rd, offset; - // LDRH rd, [rn, -rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc54() - { - uint rn, rd, offset; - // LDRH rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rn] += offset; - - registers[rd] = this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc55() - { - uint rn, rd, offset; - // LDRH rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc56() - { - uint rn, rd, offset; - // LDRH rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc57() - { - uint rn, rd, offset; - // LDRH rd, [rn, rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc58() - { - uint rn, rd, offset; - // LDRH rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc59() - { - uint rn, rd, offset; - // LDRH rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc60() - { - uint rn, rd, offset; - // LDRH rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rn] += offset; - registers[rd] = this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc61() - { - uint rn, rd, address, offset; - // LDRSB rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc62() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRSB rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc63() - { - uint rn, rd, address, offset; - // LDRSB rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc64() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRSB rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc65() - { - uint rn, rd, address, offset; - // LDRSB rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc66() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRSB rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc67() - { - uint rn, rd, address, offset; - // LDRSB rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc68() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRSB rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc69() - { - uint rn, rd, offset; - // LDRSB rd, [rn, -rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc70() - { - uint rn, rd, offset; - // LDRSB rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc71() - { - uint rn, rd, offset; - // LDRSB rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc72() - { - uint rn, rd, offset; - // LDRSB rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc73() - { - uint rn, rd, offset; - // LDRSB rd, [rn, rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc74() - { - uint rn, rd, offset; - // LDRSB rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc75() - { - uint rn, rd, offset; - // LDRSB rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc76() - { - uint rn, rd, offset; - // LDRSB rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rn] += offset; - registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc77() - { - uint rn, rd, address, offset; - // LDRSH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc78() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRSH rd, [rn], -rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc79() - { - uint rn, rd, address, offset; - // LDRSH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc80() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRSH rd, [rn], -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc81() - { - uint rn, rd, address, offset; - // LDRSH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc82() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRSH rd, [rn], rm - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc83() - { - uint rn, rd, address, offset; - // LDRSH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc84() - { - uint rn, rd, address, offset; - // Writeback bit set, instruction is unpredictable - // LDRSH rd, [rn], immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - address = registers[rn]; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(short)this.memory.ReadU16(address); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] = address + offset; - } - private void DispatchFunc85() - { - uint rn, rd, offset; - // LDRSH rd, [rn, -rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc86() - { - uint rn, rd, offset; - // LDRSH rd, [rn, -rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc87() - { - uint rn, rd, offset; - // LDRSH rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc88() - { - uint rn, rd, offset; - // LDRSH rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc89() - { - uint rn, rd, offset; - // LDRSH rd, [rn, rm] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc90() - { - uint rn, rd, offset; - // LDRSH rd, [rn, rm]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.registers[this.curInstruction & 0xF]; - - registers[rn] += offset; - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc91() - { - uint rn, rd, offset; - // LDRSH rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc92() - { - uint rn, rd, offset; - // LDRSH rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF); - - registers[rn] += offset; - registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc93() - { - uint rn, rd; - // EOR rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc94() - { - uint rn, rd; - // EOR rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc95() - { - uint rn, rd; - // EOR rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc96() - { - uint rn, rd; - // EOR rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc97() - { - uint rn, rd; - // EOR rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc98() - { - uint rn, rd; - // EOR rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc99() - { - uint rn, rd; - // EOR rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc100() - { - uint rn, rd; - // EOR rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc101() - { - uint rn, rd; - // EORS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc102() - { - uint rn, rd; - // EORS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc103() - { - uint rn, rd; - // EORS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc104() - { - uint rn, rd; - // EORS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc105() - { - uint rn, rd; - // EORS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc106() - { - uint rn, rd; - // EORS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc107() - { - uint rn, rd; - // EORS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc108() - { - uint rn, rd; - // EORS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn ^ BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc109() - { - uint rn, rd; - // SUB rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc110() - { - uint rn, rd; - // SUB rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc111() - { - uint rn, rd; - // SUB rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc112() - { - uint rn, rd; - // SUB rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc113() - { - uint rn, rd; - // SUB rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc114() - { - uint rn, rd; - // SUB rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc115() - { - uint rn, rd; - // SUB rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc116() - { - uint rn, rd; - // SUB rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc117() - { - uint rn, rd, shifterOperand; - // SUBS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc118() - { - uint rn, rd, shifterOperand; - // SUBS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc119() - { - uint rn, rd, shifterOperand; - // SUBS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc120() - { - uint rn, rd, shifterOperand; - // SUBS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc121() - { - uint rn, rd, shifterOperand; - // SUBS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc122() - { - uint rn, rd, shifterOperand; - // SUBS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc123() - { - uint rn, rd, shifterOperand; - // SUBS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc124() - { - uint rn, rd, shifterOperand; - // SUBS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc125() - { - uint rn, rd; - // RSB rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc126() - { - uint rn, rd; - // RSB rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslReg() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc127() - { - uint rn, rd; - // RSB rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc128() - { - uint rn, rd; - // RSB rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrReg() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc129() - { - uint rn, rd; - // RSB rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc130() - { - uint rn, rd; - // RSB rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrReg() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc131() - { - uint rn, rd; - // RSB rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc132() - { - uint rn, rd; - // RSB rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorReg() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc133() - { - uint rn, rd, shifterOperand; - // RSBS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc134() - { - uint rn, rd, shifterOperand; - // RSBS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc135() - { - uint rn, rd, shifterOperand; - // RSBS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc136() - { - uint rn, rd, shifterOperand; - // RSBS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc137() - { - uint rn, rd, shifterOperand; - // RSBS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc138() - { - uint rn, rd, shifterOperand; - // RSBS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc139() - { - uint rn, rd, shifterOperand; - // RSBS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc140() - { - uint rn, rd, shifterOperand; - // RSBS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc141() - { - uint rn, rd; - // ADD rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc142() - { - uint rn, rd; - // ADD rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc143() - { - uint rn, rd; - // ADD rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc144() - { - uint rn, rd; - // ADD rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc145() - { - uint rn, rd; - // ADD rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc146() - { - uint rn, rd; - // ADD rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc147() - { - uint rn, rd; - // ADD rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc148() - { - uint rn, rd; - // ADD rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc149() - { - uint rn, rd, shifterOperand; - // ADDS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc150() - { - uint rn, rd, shifterOperand; - // ADDS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc151() - { - uint rn, rd, shifterOperand; - // ADDS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc152() - { - uint rn, rd, shifterOperand; - // ADDS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc153() - { - uint rn, rd, shifterOperand; - // ADDS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc154() - { - uint rn, rd, shifterOperand; - // ADDS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc155() - { - uint rn, rd, shifterOperand; - // ADDS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc156() - { - uint rn, rd, shifterOperand; - // ADDS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc157() - { - uint rn, rd; - // ADC rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLslImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc158() - { - uint rn, rd; - // ADC rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLslReg() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc159() - { - uint rn, rd; - // ADC rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLsrImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc160() - { - uint rn, rd; - // ADC rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterLsrReg() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc161() - { - uint rn, rd; - // ADC rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterAsrImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc162() - { - uint rn, rd; - // ADC rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterAsrReg() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc163() - { - uint rn, rd; - // ADC rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterRorImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc164() - { - uint rn, rd; - // ADC rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn + BarrelShifterRorReg() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc165() - { - uint rn, rd, shifterOperand; - // ADCS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc166() - { - uint rn, rd, shifterOperand; - // ADCS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc167() - { - uint rn, rd, shifterOperand; - // ADCS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc168() - { - uint rn, rd, shifterOperand; - // ADCS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc169() - { - uint rn, rd, shifterOperand; - // ADCS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc170() - { - uint rn, rd, shifterOperand; - // ADCS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc171() - { - uint rn, rd, shifterOperand; - // ADCS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc172() - { - uint rn, rd, shifterOperand; - // ADCS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc173() - { - uint rn, rd; - // SBC rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLslImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc174() - { - uint rn, rd; - // SBC rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLslReg() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc175() - { - uint rn, rd; - // SBC rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLsrImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc176() - { - uint rn, rd; - // SBC rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterLsrReg() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc177() - { - uint rn, rd; - // SBC rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterAsrImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc178() - { - uint rn, rd; - // SBC rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterAsrReg() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc179() - { - uint rn, rd; - // SBC rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterRorImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc180() - { - uint rn, rd; - // SBC rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn - BarrelShifterRorReg() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc181() - { - uint rn, rd, shifterOperand; - // SBCS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc182() - { - uint rn, rd, shifterOperand; - // SBCS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc183() - { - uint rn, rd, shifterOperand; - // SBCS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc184() - { - uint rn, rd, shifterOperand; - // SBCS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc185() - { - uint rn, rd, shifterOperand; - // SBCS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc186() - { - uint rn, rd, shifterOperand; - // SBCS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc187() - { - uint rn, rd, shifterOperand; - // SBCS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc188() - { - uint rn, rd, shifterOperand; - // SBCS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc189() - { - uint rn, rd; - // RSC rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc190() - { - uint rn, rd; - // RSC rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslReg() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc191() - { - uint rn, rd; - // RSC rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc192() - { - uint rn, rd; - // RSC rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrReg() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc193() - { - uint rn, rd; - // RSC rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc194() - { - uint rn, rd; - // RSC rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrReg() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc195() - { - uint rn, rd; - // RSC rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc196() - { - uint rn, rd; - // RSC rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorReg() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc197() - { - uint rn, rd, shifterOperand; - // RSCS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc198() - { - uint rn, rd, shifterOperand; - // RSCS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLslReg(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc199() - { - uint rn, rd, shifterOperand; - // RSCS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc200() - { - uint rn, rd, shifterOperand; - // RSCS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterLsrReg(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc201() - { - uint rn, rd, shifterOperand; - // RSCS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc202() - { - uint rn, rd, shifterOperand; - // RSCS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterAsrReg(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc203() - { - uint rn, rd, shifterOperand; - // RSCS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc204() - { - uint rn, rd, shifterOperand; - // RSCS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - shifterOperand = BarrelShifterRorReg(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc205() - { - uint rn, rd, rm; - // SWP rd, rm, [rn] - { - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - rm = this.curInstruction & 0xF; - uint tmp = this.memory.ReadU32(registers[rn]); - this.memory.WriteU32(registers[rn], registers[rm]); - registers[rd] = tmp; - - if (rd == 15) - { - this.FlushQueue(); - } - } - } - private void DispatchFunc206() - { - uint rn, rd, rm; - // SWPB rd, rm, [rn] - { - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - rm = this.curInstruction & 0xF; - - byte tmp = this.memory.ReadU8(registers[rn]); - this.memory.WriteU8(registers[rn], (byte)(registers[rm] & 0xFF)); - registers[rd] = tmp; - - if (rd == 15) - { - this.FlushQueue(); - } - } - } - private void DispatchFunc207() - { - uint rd; - // MRS rd, cpsr - rd = (this.curInstruction >> 12) & 0xF; - this.PackFlags(); - registers[rd] = this.parent.CPSR; - } - private void DispatchFunc208() - { - uint rd; - // MRS rd, spsr - rd = (this.curInstruction >> 12) & 0xF; - if (this.parent.SPSRExists) registers[rd] = this.parent.SPSR; - } - private void DispatchFunc209() - { - uint rm; - // MSR cpsr, rm - { - rm = registers[this.curInstruction & 0xF]; - bool userMode = (this.parent.CPSR & 0x1F) == Arm7Processor.USR; - - this.PackFlags(); - - uint tmpCPSR = this.parent.CPSR; - - if ((this.curInstruction & (1 << 16)) == 1 << 16 && !userMode) - { - tmpCPSR &= 0xFFFFFF00; - tmpCPSR |= rm & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17 && !userMode) - { - tmpCPSR &= 0xFFFF00FF; - tmpCPSR |= rm & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18 && !userMode) - { - tmpCPSR &= 0xFF00FFFF; - tmpCPSR |= rm & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - tmpCPSR &= 0x00FFFFFF; - tmpCPSR |= rm & 0xFF000000; - } - - this.parent.WriteCpsr(tmpCPSR); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - } - } - private void DispatchFunc210() - { - uint rm; - // MSR spsr, rm - if (this.parent.SPSRExists) - { - rm = registers[this.curInstruction & 0xF]; - if ((this.curInstruction & (1 << 16)) == 1 << 16) - { - this.parent.SPSR &= 0xFFFFFF00; - this.parent.SPSR |= rm & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17) - { - this.parent.SPSR &= 0xFFFF00FF; - this.parent.SPSR |= rm & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18) - { - this.parent.SPSR &= 0xFF00FFFF; - this.parent.SPSR |= rm & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - this.parent.SPSR &= 0x00FFFFFF; - this.parent.SPSR |= rm & 0xFF000000; - } - } - } - private void DispatchFunc211() - { - // MSR cpsr, immed - { - uint immed = this.curInstruction & 0xFF; - int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2); - - immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount)); - - bool userMode = (this.parent.CPSR & 0x1F) == Arm7Processor.USR; - - this.PackFlags(); - - uint tmpCPSR = this.parent.CPSR; - - if ((this.curInstruction & (1 << 16)) == 1 << 16 && !userMode) - { - tmpCPSR &= 0xFFFFFF00; - tmpCPSR |= immed & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17 && !userMode) - { - tmpCPSR &= 0xFFFF00FF; - tmpCPSR |= immed & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18 && !userMode) - { - tmpCPSR &= 0xFF00FFFF; - tmpCPSR |= immed & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - tmpCPSR &= 0x00FFFFFF; - tmpCPSR |= immed & 0xFF000000; - } - - this.parent.WriteCpsr(tmpCPSR); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - } - } - private void DispatchFunc212() - { - // MSR spsr, immed - if (this.parent.SPSRExists) - { - uint immed = this.curInstruction & 0xFF; - int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2); - - immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount)); - - if ((this.curInstruction & (1 << 16)) == 1 << 16) - { - this.parent.SPSR &= 0xFFFFFF00; - this.parent.SPSR |= immed & 0x000000FF; - } - if ((this.curInstruction & (1 << 17)) == 1 << 17) - { - this.parent.SPSR &= 0xFFFF00FF; - this.parent.SPSR |= immed & 0x0000FF00; - } - if ((this.curInstruction & (1 << 18)) == 1 << 18) - { - this.parent.SPSR &= 0xFF00FFFF; - this.parent.SPSR |= immed & 0x00FF0000; - } - if ((this.curInstruction & (1 << 19)) == 1 << 19) - { - this.parent.SPSR &= 0x00FFFFFF; - this.parent.SPSR |= immed & 0xFF000000; - } - } - } - private void DispatchFunc213() - { - uint rm; - // BX rm - rm = this.curInstruction & 0xf; - - this.PackFlags(); - - this.parent.CPSR &= ~Arm7Processor.T_MASK; - this.parent.CPSR |= (registers[rm] & 1) << Arm7Processor.T_BIT; - - registers[15] = registers[rm] & (~1U); - - this.UnpackFlags(); - - // Check for branch back to Thumb Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK) - { - this.thumbMode = true; - return; - } - - this.FlushQueue(); - } - private void DispatchFunc214() - { - uint rn, alu; - // TSTS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterLslImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc215() - { - uint rn, alu; - // TSTS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterLslReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc216() - { - uint rn, alu; - // TSTS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterLsrImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc217() - { - uint rn, alu; - // TSTS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterLsrReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc218() - { - uint rn, alu; - // TSTS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterAsrImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc219() - { - uint rn, alu; - // TSTS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterAsrReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc220() - { - uint rn, alu; - // TSTS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterRorImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc221() - { - uint rn, rd, alu; - // TSTS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - alu = rn & BarrelShifterRorReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc222() - { - uint rn, alu; - // TEQS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterLslImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc223() - { - uint rn, alu; - // TEQS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterLslReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc224() - { - uint rn, alu; - // TEQS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterLsrImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc225() - { - uint rn, alu; - // TEQS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterLsrReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc226() - { - uint rn, alu; - // TEQS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterAsrImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc227() - { - uint rn, alu; - // TEQS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterAsrReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc228() - { - uint rn, alu; - // TEQS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterRorImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc229() - { - uint rn, rd, alu; - // TEQS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - alu = rn ^ BarrelShifterRorReg(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc230() - { - uint rn, shifterOperand, alu; - // CMP rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLslImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - } - private void DispatchFunc231() - { - uint rn, shifterOperand, alu; - // CMP rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLslReg(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - } - private void DispatchFunc232() - { - uint rn, shifterOperand, alu; - // CMP rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLsrImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - } - private void DispatchFunc233() - { - uint rn, shifterOperand, alu; - // CMP rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLsrReg(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - } - private void DispatchFunc234() - { - uint rn, shifterOperand, alu; - // CMP rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterAsrImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - } - private void DispatchFunc235() - { - uint rn, shifterOperand, alu; - // CMP rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterAsrReg(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - } - private void DispatchFunc236() - { - uint rn, shifterOperand, alu; - // CMP rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterRorImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - } - private void DispatchFunc237() - { - uint rn, shifterOperand, alu; - // CMP rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterRorReg(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - } - private void DispatchFunc238() - { - uint rn, shifterOperand, alu; - // CMN rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLslImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - } - private void DispatchFunc239() - { - uint rn, shifterOperand, alu; - // CMN rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLslReg(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - } - private void DispatchFunc240() - { - uint rn, shifterOperand, alu; - // CMN rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLsrImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - } - private void DispatchFunc241() - { - uint rn, shifterOperand, alu; - // CMN rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterLsrReg(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - } - private void DispatchFunc242() - { - uint rn, shifterOperand, alu; - // CMN rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterAsrImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - } - private void DispatchFunc243() - { - uint rn, shifterOperand, alu; - // CMN rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterAsrReg(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - } - private void DispatchFunc244() - { - uint rn, shifterOperand, alu; - // CMN rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterRorImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - } - private void DispatchFunc245() - { - uint rn, shifterOperand, alu; - // CMN rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterRorReg(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - } - private void DispatchFunc246() - { - uint rn, rd; - // ORR rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc247() - { - uint rn, rd; - // ORR rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc248() - { - uint rn, rd; - // ORR rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc249() - { - uint rn, rd; - // ORR rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc250() - { - uint rn, rd; - // ORR rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc251() - { - uint rn, rd; - // ORR rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc252() - { - uint rn, rd; - // ORR rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc253() - { - uint rn, rd; - // ORR rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc254() - { - uint rn, rd; - // ORRS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc255() - { - uint rn, rd; - // ORRS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc256() - { - uint rn, rd; - // ORRS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc257() - { - uint rn, rd; - // ORRS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc258() - { - uint rn, rd; - // ORRS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc259() - { - uint rn, rd; - // ORRS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc260() - { - uint rn, rd; - // ORRS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc261() - { - uint rn, rd; - // ORRS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn | BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc262() - { - uint rd; - // MOV rd, rm lsl immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc263() - { - uint rd; - // MOV rd, rm lsl rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc264() - { - uint rd; - // MOV rd, rm lsr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc265() - { - uint rd; - // MOV rd, rm lsr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc266() - { - uint rd; - // MOV rd, rm asr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc267() - { - uint rd; - // MOV rd, rm asr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc268() - { - uint rd; - // MOV rd, rm ror immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc269() - { - uint rd; - // MOV rd, rm ror rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc270() - { - uint rd; - // MOVS rd, rm lsl immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc271() - { - uint rd; - // MOVS rd, rm lsl rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc272() - { - uint rd; - // MOVS rd, rm lsr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc273() - { - uint rd; - // MOVS rd, rn, rm lsr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc274() - { - uint rd; - // MOVS rd, rn, rm asr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc275() - { - uint rd; - // MOVS rd, rn, rm asr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc276() - { - uint rd; - // MOVS rd, rn, rm ror immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc277() - { - uint rd; - // MOVS rd, rn, rm ror rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc278() - { - uint rn, rd; - // BIC rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc279() - { - uint rn, rd; - // BIC rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc280() - { - uint rn, rd; - // BIC rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc281() - { - uint rn, rd; - // BIC rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc282() - { - uint rn, rd; - // BIC rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc283() - { - uint rn, rd; - // BIC rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc284() - { - uint rn, rd; - // BIC rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc285() - { - uint rn, rd; - // BIC rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc286() - { - uint rn, rd; - // BICS rd, rn, rm lsl immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc287() - { - uint rn, rd; - // BICS rd, rn, rm lsl rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc288() - { - uint rn, rd; - // BICS rd, rn, rm lsr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc289() - { - uint rn, rd; - // BICS rd, rn, rm lsr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc290() - { - uint rn, rd; - // BICS rd, rn, rm asr immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc291() - { - uint rn, rd; - // BICS rd, rn, rm asr rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc292() - { - uint rn, rd; - // BICS rd, rn, rm ror immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc293() - { - uint rn, rd; - // BICS rd, rn, rm ror rs - rn = registers[(this.curInstruction >> 16) & 0xF]; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = rn & ~BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc294() - { - uint rd; - // MVN rd, rm lsl immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLslImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc295() - { - uint rd; - // MVN rd, rm lsl rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLslReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc296() - { - uint rd; - // MVN rd, rm lsr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc297() - { - uint rd; - // MVN rd, rm lsr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc298() - { - uint rd; - // MVN rd, rm asr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterAsrImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc299() - { - uint rd; - // MVN rd, rm asr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterAsrReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc300() - { - uint rd; - // MVN rd, rm ror immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterRorImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc301() - { - uint rd; - // MVN rd, rm ror rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterRorReg(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc302() - { - uint rd; - // MVNS rd, rm lsl immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLslImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc303() - { - uint rd; - // MVNS rd, rm lsl rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLslReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc304() - { - uint rd; - // MVNS rd, rm lsr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc305() - { - uint rd; - // MVNS rd, rn, rm lsr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterLsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc306() - { - uint rd; - // MVNS rd, rn, rm asr immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterAsrImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc307() - { - uint rd; - // MVNS rd, rn, rm asr rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterAsrReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc308() - { - uint rd; - // MVNS rd, rn, rm ror immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterRorImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc309() - { - uint rd; - // MVNS rd, rn, rm ror rs - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterRorReg(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc310() - { - uint rn, rd; - // AND rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn & BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc311() - { - uint rn, rd; - // ANDS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn & BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc312() - { - uint rn, rd; - // EOR rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn ^ BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc313() - { - uint rn, rd; - // EORS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn ^ BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc314() - { - uint rn, rd; - // SUB rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn - BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc315() - { - uint rn, rd, shifterOperand; - // SUBS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = rn - shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc316() - { - uint rn, rd; - // RSB rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = BarrelShifterImmed() - rn; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc317() - { - uint rn, rd, shifterOperand; - // RSBS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = shifterOperand - rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc318() - { - uint rn, rd; - // ADD rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn + BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc319() - { - uint rn, rd, shifterOperand; - // ADDS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = rn + shifterOperand; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc320() - { - uint rn, rd; - // ADC rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn + BarrelShifterImmed() + carry; - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc321() - { - uint rn, rd, shifterOperand; - // ADCS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = rn + shifterOperand + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc322() - { - uint rn, rd; - // SBC rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn - BarrelShifterImmed() - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc323() - { - uint rn, rd, shifterOperand; - // SBCS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = rn - shifterOperand - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc324() - { - uint rn, rd; - // RSC rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = BarrelShifterImmed() - rn - (1U - carry); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc325() - { - uint rn, rd, shifterOperand; - // RSCS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - registers[rd] = shifterOperand - rn - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(shifterOperand, rn, registers[rd]); - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc326() - { - uint rn, alu; - // TSTS rn, immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn & BarrelShifterImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc327() - { - uint rn, alu; - // TEQS rn, immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - alu = rn ^ BarrelShifterImmed(); - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - carry = this.shifterCarry; - } - private void DispatchFunc328() - { - uint rn, shifterOperand, alu; - // CMP rn, immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - alu = rn - shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(rn, shifterOperand, alu); - } - private void DispatchFunc329() - { - uint rn, shifterOperand, alu; - // CMN rn, immed - rn = registers[(this.curInstruction >> 16) & 0xF]; - - shifterOperand = BarrelShifterImmed(); - alu = rn + shifterOperand; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(rn, shifterOperand, alu); - } - private void DispatchFunc330() - { - uint rn, rd; - // ORR rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn | BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc331() - { - uint rn, rd; - // ORRS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn | BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc332() - { - uint rd; - // MOV rd, immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc333() - { - uint rd; - // MOVS rd, immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc334() - { - uint rn, rd; - // BIC rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn & ~BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc335() - { - uint rn, rd; - // BICS rd, rn, immed - rd = (this.curInstruction >> 12) & 0xF; - rn = registers[(this.curInstruction >> 16) & 0xF]; - - registers[rd] = rn & ~BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc336() - { - uint rd; - // MVN rd, immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterImmed(); - - if (rd == 15) - { - this.FlushQueue(); - } - } - private void DispatchFunc337() - { - uint rd; - // MVNS rd, immed - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = ~BarrelShifterImmed(); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - carry = this.shifterCarry; - - if (rd == 15) - { - this.DataProcessingWriteToR15(); - } - } - private void DispatchFunc338() - { - uint rn, rd, offset, alu; - // STR rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc339() - { - uint rn, rd, offset, alu; - // STRT rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc340() - { - uint rn, rd, offset, alu; - // STRB rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc341() - { - uint rn, rd, offset, alu; - // STRBT rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc342() - { - uint rn, rd, alu; - // STR rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.curInstruction & 0xFFF; - } - private void DispatchFunc343() - { - uint rn, rd, alu; - // STRT rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.curInstruction & 0xFFF; - } - private void DispatchFunc344() - { - uint rn, rd, alu; - // STRB rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.curInstruction & 0xFFF; - } - private void DispatchFunc345() - { - uint rn, rd, alu; - // STRBT rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.curInstruction & 0xFFF; - } - private void DispatchFunc346() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - } - private void DispatchFunc347() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc348() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - } - private void DispatchFunc349() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc350() - { - uint rn, rd, alu; - // STR rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + (this.curInstruction & 0xFFF), alu); - } - private void DispatchFunc351() - { - uint rn, rd, alu; - // STRT rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.curInstruction & 0xFFF; - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc352() - { - uint rn, rd, alu; - // STRB rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + (this.curInstruction & 0xFFF), (byte)(alu & 0xFF)); - } - private void DispatchFunc353() - { - uint rn, rd, alu; - // STRB rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.curInstruction & 0xFFF; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc354() - { - uint rn, rd, offset; - // LDR rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc355() - { - uint rn, rd, offset; - // LDRT rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc356() - { - uint rn, rd, offset; - // LDRB rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc357() - { - uint rn, rd, offset; - // LDRBT rd, rn, -immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc358() - { - uint rn, rd; - // LDR rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += this.curInstruction & 0xFFF; - } - private void DispatchFunc359() - { - uint rn, rd; - // LDRT rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += this.curInstruction & 0xFFF; - } - private void DispatchFunc360() - { - uint rn, rd; - // LDRB rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += this.curInstruction & 0xFFF; - } - private void DispatchFunc361() - { - uint rn, rd; - // LDRBT rd, rn, immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += this.curInstruction & 0xFFF; - } - private void DispatchFunc362() - { - uint rn, rd, offset; - // LDR rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc363() - { - uint rn, rd, offset; - // LDR rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc364() - { - uint rn, rd, offset; - // LDRB rd, [rn, -immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc365() - { - uint rn, rd, offset; - // LDRB rd, [rn, -immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.curInstruction & 0xFFF; - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc366() - { - uint rn, rd; - // LDR rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + (this.curInstruction & 0xFFF)); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc367() - { - uint rn, rd; - // LDR rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.curInstruction & 0xFFF; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc368() - { - uint rn, rd; - // LDRB rd, [rn, immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + (this.curInstruction & 0xFFF)); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc369() - { - uint rn, rd; - // LDRB rd, [rn, immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.curInstruction & 0xFFF; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc370() - { - uint rn, rd, offset, alu; - // STR rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc371() - { - uint rn, rd, offset, alu; - // STR rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc372() - { - uint rn, rd, offset, alu; - // STR rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc373() - { - uint rn, rd, offset, alu; - // STR rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc374() - { - uint rn, rd, offset, alu; - // STRT rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc375() - { - uint rn, rd, offset, alu; - // STRT rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc376() - { - uint rn, rd, offset, alu; - // STRT rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc377() - { - uint rn, rd, offset, alu; - // STRT rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += offset; - } - private void DispatchFunc378() - { - uint rn, rd, offset, alu; - // STRB rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc379() - { - uint rn, rd, offset, alu; - // STRB rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc380() - { - uint rn, rd, offset, alu; - // STRB rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc381() - { - uint rn, rd, offset, alu; - // STRB rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc382() - { - uint rn, rd, offset, alu; - // STRBT rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc383() - { - uint rn, rd, offset, alu; - // STRBT rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc384() - { - uint rn, rd, offset, alu; - // STRBT rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc385() - { - uint rn, rd, offset, alu; - // STRBT rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += offset; - } - private void DispatchFunc386() - { - uint rn, rd, alu; - // STR rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterLslImmed(); - } - private void DispatchFunc387() - { - uint rn, rd, alu; - // STR rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterLsrImmed(); - } - private void DispatchFunc388() - { - uint rn, rd, alu; - // STR rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterAsrImmed(); - } - private void DispatchFunc389() - { - uint rn, rd, alu; - // STR rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterRorImmed(); - } - private void DispatchFunc390() - { - uint rn, rd, alu; - // STRT rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterLslImmed(); - } - private void DispatchFunc391() - { - uint rn, rd, alu; - // STRT rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterLsrImmed(); - } - private void DispatchFunc392() - { - uint rn, rd, alu; - // STRT rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterAsrImmed(); - } - private void DispatchFunc393() - { - uint rn, rd, alu; - // STRT rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn], alu); - registers[rn] += this.BarrelShifterRorImmed(); - } - private void DispatchFunc394() - { - uint rn, rd, alu; - // STRB rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterLslImmed(); - } - private void DispatchFunc395() - { - uint rn, rd, alu; - // STRB rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterLsrImmed(); - } - private void DispatchFunc396() - { - uint rn, rd, alu; - // STRB rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterAsrImmed(); - } - private void DispatchFunc397() - { - uint rn, rd, alu; - // STRB rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterRorImmed(); - } - private void DispatchFunc398() - { - uint rn, rd, alu; - // STRBT rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterLslImmed(); - } - private void DispatchFunc399() - { - uint rn, rd, alu; - // STRBT rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterLsrImmed(); - } - private void DispatchFunc400() - { - uint rn, rd, alu; - // STRBT rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterAsrImmed(); - } - private void DispatchFunc401() - { - uint rn, rd, alu; - // STRBT rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - registers[rn] += this.BarrelShifterRorImmed(); - } - private void DispatchFunc402() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - } - private void DispatchFunc403() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - } - private void DispatchFunc404() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - } - private void DispatchFunc405() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + offset, alu); - } - private void DispatchFunc406() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc407() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc408() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc409() - { - uint rn, rd, offset, alu; - // STR rd, [rn, -rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc410() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - } - private void DispatchFunc411() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - } - private void DispatchFunc412() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - } - private void DispatchFunc413() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF)); - } - private void DispatchFunc414() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc415() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc416() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc417() - { - uint rn, rd, offset, alu; - // STRB rd, [rn, -rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += offset; - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc418() - { - uint rn, rd, alu; - // STR rd, [rn, rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + this.BarrelShifterLslImmed(), alu); - } - private void DispatchFunc419() - { - uint rn, rd, alu; - // STR rd, [rn, rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + this.BarrelShifterLsrImmed(), alu); - } - private void DispatchFunc420() - { - uint rn, rd, alu; - // STR rd, [rn, rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + this.BarrelShifterAsrImmed(), alu); - } - private void DispatchFunc421() - { - uint rn, rd, alu; - // STR rd, [rn, rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU32(registers[rn] + this.BarrelShifterRorImmed(), alu); - } - private void DispatchFunc422() - { - uint rn, rd, alu; - // STR rd, [rn, rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterLslImmed(); - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc423() - { - uint rn, rd, alu; - // STR rd, [rn, rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterLsrImmed(); - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc424() - { - uint rn, rd, alu; - // STR rd, [rn, rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterAsrImmed(); - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc425() - { - uint rn, rd, alu; - // STR rd, [rn, rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterRorImmed(); - this.memory.WriteU32(registers[rn], alu); - } - private void DispatchFunc426() - { - uint rn, rd, alu; - // STRB rd, [rn, rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + this.BarrelShifterLslImmed(), (byte)(alu & 0xFF)); - } - private void DispatchFunc427() - { - uint rn, rd, alu; - // STRB rd, [rn, rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + this.BarrelShifterLsrImmed(), (byte)(alu & 0xFF)); - } - private void DispatchFunc428() - { - uint rn, rd, alu; - // STRB rd, [rn, rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + this.BarrelShifterAsrImmed(), (byte)(alu & 0xFF)); - } - private void DispatchFunc429() - { - uint rn, rd, alu; - // STRB rd, [rn, rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - this.memory.WriteU8(registers[rn] + this.BarrelShifterRorImmed(), (byte)(alu & 0xFF)); - } - private void DispatchFunc430() - { - uint rn, rd, alu; - // STRB rd, [rn, rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterLslImmed(); - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc431() - { - uint rn, rd, alu; - // STRB rd, [rn, rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterLsrImmed(); - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc432() - { - uint rn, rd, alu; - // STRB rd, [rn, rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterAsrImmed(); - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc433() - { - uint rn, rd, alu; - // STRB rd, [rn, rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - alu = registers[rd]; - if (rd == 15) alu += 4; - - registers[rn] += this.BarrelShifterRorImmed(); - this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF)); - } - private void DispatchFunc434() - { - uint rn, rd, offset; - // LDR rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc435() - { - uint rn, rd, offset; - // LDR rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc436() - { - uint rn, rd, offset; - // LDR rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc437() - { - uint rn, rd, offset; - // LDR rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc438() - { - uint rn, rd, offset; - // LDRT rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc439() - { - uint rn, rd, offset; - // LDRT rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc440() - { - uint rn, rd, offset; - // LDRT rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc441() - { - uint rn, rd, offset; - // LDRT rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc442() - { - uint rn, rd, offset; - // LDRB rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc443() - { - uint rn, rd, offset; - // LDRB rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc444() - { - uint rn, rd, offset; - // LDRB rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc445() - { - uint rn, rd, offset; - // LDRB rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc446() - { - uint rn, rd, offset; - // LDRBT rd, rn, -rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc447() - { - uint rn, rd, offset; - // LDRBT rd, rn, -rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc448() - { - uint rn, rd, offset; - // LDRBT rd, rn, -rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc449() - { - uint rn, rd, offset; - // LDRBT rd, rn, -rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc450() - { - uint rn, rd, offset; - // LDR rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc451() - { - uint rn, rd, offset; - // LDR rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc452() - { - uint rn, rd, offset; - // LDR rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc453() - { - uint rn, rd, offset; - // LDR rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc454() - { - uint rn, rd, offset; - // LDRT rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc455() - { - uint rn, rd, offset; - // LDRT rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc456() - { - uint rn, rd, offset; - // LDRT rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc457() - { - uint rn, rd, offset; - // LDRT rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc458() - { - uint rn, rd, offset; - // LDRB rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc459() - { - uint rn, rd, offset; - // LDRB rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc460() - { - uint rn, rd, offset; - // LDRB rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc461() - { - uint rn, rd, offset; - // LDRB rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc462() - { - uint rn, rd, offset; - // LDRBT rd, rn, rm lsl immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc463() - { - uint rn, rd, offset; - // LDRBT rd, rn, rm lsr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc464() - { - uint rn, rd, offset; - // LDRBT rd, rn, rm asr immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc465() - { - uint rn, rd, offset; - // LDRBT rd, rn, rm ror immed - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - - if (rn != rd) - registers[rn] += offset; - } - private void DispatchFunc466() - { - uint rn, rd, offset; - // LDR rd, [rn, -rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc467() - { - uint rn, rd, offset; - // LDR rd, [rn, -rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc468() - { - uint rn, rd, offset; - // LDR rd, [rn, -rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc469() - { - uint rn, rd, offset; - // LDR rd, [rn, -rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU32(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc470() - { - uint rn, rd, offset; - // LDR rd, [rn, -rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc471() - { - uint rn, rd, offset; - // LDR rd, [rn, -rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc472() - { - uint rn, rd, offset; - // LDR rd, [rn, -rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc473() - { - uint rn, rd, offset; - // LDR rd, [rn, -rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc474() - { - uint rn, rd, offset; - // LDRB rd, [rn, -rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc475() - { - uint rn, rd, offset; - // LDRB rd, [rn, -rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc476() - { - uint rn, rd, offset; - // LDRB rd, [rn, -rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc477() - { - uint rn, rd, offset; - // LDRB rd, [rn, -rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rd] = this.memory.ReadU8(registers[rn] + offset); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc478() - { - uint rn, rd, offset; - // LDRB rd, [rn, -rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLslImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc479() - { - uint rn, rd, offset; - // LDRB rd, [rn, -rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterLsrImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc480() - { - uint rn, rd, offset; - // LDRB rd, [rn, -rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterAsrImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc481() - { - uint rn, rd, offset; - // LDRB rd, [rn, -rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - offset = this.BarrelShifterRorImmed(); - offset = (uint)-offset; - - registers[rn] += offset; - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc482() - { - uint rn, rd; - // LDR rd, [rn, rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterLslImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc483() - { - uint rn, rd; - // LDR rd, [rn, rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterLsrImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc484() - { - uint rn, rd; - // LDR rd, [rn, rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterAsrImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc485() - { - uint rn, rd; - // LDR rd, [rn, rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterRorImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc486() - { - uint rn, rd; - // LDR rd, [rn, rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc487() - { - uint rn, rd; - // LDR rd, [rn, rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc488() - { - uint rn, rd; - // LDR rd, [rn, rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc489() - { - uint rn, rd; - // LDR rd, [rn, rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU32(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc490() - { - uint rn, rd; - // LDRB rd, [rn, rm lsl immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterLslImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc491() - { - uint rn, rd; - // LDRB rd, [rn, rm lsr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterLsrImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc492() - { - uint rn, rd; - // LDRB rd, [rn, rm asr immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterAsrImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc493() - { - uint rn, rd; - // LDRB rd, [rn, rm ror immed] - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterRorImmed()); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc494() - { - uint rn, rd; - // LDRB rd, [rn, rm lsl immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterLslImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc495() - { - uint rn, rd; - // LDRB rd, [rn, rm lsr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterLsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc496() - { - uint rn, rd; - // LDRB rd, [rn, rm asr immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterAsrImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc497() - { - uint rn, rd; - // LDRB rd, [rn, rm ror immed]! - rn = (this.curInstruction >> 16) & 0xF; - rd = (this.curInstruction >> 12) & 0xF; - - registers[rn] += this.BarrelShifterRorImmed(); - registers[rd] = this.memory.ReadU8(registers[rn]); - - if (rd == 15) - { - registers[rd] &= ~3U; - this.FlushQueue(); - } - } - private void DispatchFunc498() - { - { - uint branchOffset = this.curInstruction & 0x00FFFFFF; - if (branchOffset >> 23 == 1) branchOffset |= 0xFF000000; - - this.registers[15] += branchOffset << 2; - - this.FlushQueue(); - } - } - private void DispatchFunc499() - { - { - uint branchOffset = this.curInstruction & 0x00FFFFFF; - if (branchOffset >> 23 == 1) branchOffset |= 0xFF000000; - - this.registers[14] = this.registers[15] - 4U; - this.registers[15] += branchOffset << 2; - - this.FlushQueue(); - } - } - private void DispatchFunc500() - { - this.registers[15] -= 4U; - this.parent.EnterException(Arm7Processor.SVC, 0x8, false, false); - } - private void DefaultDispatchFunc() { this.NormalOps[(curInstruction >> 25) & 0x7](); } - private ExecuteInstructionDelegate[] fastDispatch = null; - private void InitializeDispatchFunc() - { - this.fastDispatch = new ExecuteInstructionDelegate[] { -DispatchFunc0,DispatchFunc1,DispatchFunc2,DispatchFunc3,DispatchFunc4,DispatchFunc5,DispatchFunc6,DispatchFunc7,DispatchFunc0,DispatchFunc17,DispatchFunc2,DispatchFunc29,DispatchFunc4,DispatchFunc16,DispatchFunc6,DispatchFunc16,DispatchFunc8,DispatchFunc9,DispatchFunc10,DispatchFunc11,DispatchFunc12 -,DispatchFunc13,DispatchFunc14,DispatchFunc15,DispatchFunc8,DispatchFunc18,DispatchFunc10,DispatchFunc45,DispatchFunc12,DispatchFunc61,DispatchFunc14,DispatchFunc77,DispatchFunc93,DispatchFunc94,DispatchFunc95,DispatchFunc96,DispatchFunc97,DispatchFunc98,DispatchFunc99,DispatchFunc100,DispatchFunc93 -,DispatchFunc19,DispatchFunc95,DispatchFunc30,DispatchFunc97,DispatchFunc16,DispatchFunc99,DispatchFunc16,DispatchFunc101,DispatchFunc102,DispatchFunc103,DispatchFunc104,DispatchFunc105,DispatchFunc106,DispatchFunc107,DispatchFunc108,DispatchFunc101,DispatchFunc20,DispatchFunc103,DispatchFunc46,DispatchFunc105 -,DispatchFunc62,DispatchFunc107,DispatchFunc78,DispatchFunc109,DispatchFunc110,DispatchFunc111,DispatchFunc112,DispatchFunc113,DispatchFunc114,DispatchFunc115,DispatchFunc116,DispatchFunc109,DefaultDispatchFunc,DispatchFunc111,DispatchFunc31,DispatchFunc113,DispatchFunc16,DispatchFunc115,DispatchFunc16,DispatchFunc117 -,DispatchFunc118,DispatchFunc119,DispatchFunc120,DispatchFunc121,DispatchFunc122,DispatchFunc123,DispatchFunc124,DispatchFunc117,DefaultDispatchFunc,DispatchFunc119,DispatchFunc47,DispatchFunc121,DispatchFunc63,DispatchFunc123,DispatchFunc79,DispatchFunc125,DispatchFunc126,DispatchFunc127,DispatchFunc128,DispatchFunc129 -,DispatchFunc130,DispatchFunc131,DispatchFunc132,DispatchFunc125,DefaultDispatchFunc,DispatchFunc127,DispatchFunc32,DispatchFunc129,DispatchFunc16,DispatchFunc131,DispatchFunc16,DispatchFunc133,DispatchFunc134,DispatchFunc135,DispatchFunc136,DispatchFunc137,DispatchFunc138,DispatchFunc139,DispatchFunc140,DispatchFunc133 -,DefaultDispatchFunc,DispatchFunc135,DispatchFunc48,DispatchFunc137,DispatchFunc64,DispatchFunc139,DispatchFunc80,DispatchFunc141,DispatchFunc142,DispatchFunc143,DispatchFunc144,DispatchFunc145,DispatchFunc146,DispatchFunc147,DispatchFunc148,DispatchFunc141,DispatchFunc21,DispatchFunc143,DispatchFunc33,DispatchFunc145 -,DispatchFunc16,DispatchFunc147,DispatchFunc16,DispatchFunc149,DispatchFunc150,DispatchFunc151,DispatchFunc152,DispatchFunc153,DispatchFunc154,DispatchFunc155,DispatchFunc156,DispatchFunc149,DispatchFunc22,DispatchFunc151,DispatchFunc49,DispatchFunc153,DispatchFunc65,DispatchFunc155,DispatchFunc81,DispatchFunc157 -,DispatchFunc158,DispatchFunc159,DispatchFunc160,DispatchFunc161,DispatchFunc162,DispatchFunc163,DispatchFunc164,DispatchFunc157,DispatchFunc23,DispatchFunc159,DispatchFunc34,DispatchFunc161,DispatchFunc16,DispatchFunc163,DispatchFunc16,DispatchFunc165,DispatchFunc166,DispatchFunc167,DispatchFunc168,DispatchFunc169 -,DispatchFunc170,DispatchFunc171,DispatchFunc172,DispatchFunc165,DispatchFunc24,DispatchFunc167,DispatchFunc50,DispatchFunc169,DispatchFunc66,DispatchFunc171,DispatchFunc82,DispatchFunc173,DispatchFunc174,DispatchFunc175,DispatchFunc176,DispatchFunc177,DispatchFunc178,DispatchFunc179,DispatchFunc180,DispatchFunc173 -,DispatchFunc25,DispatchFunc175,DispatchFunc35,DispatchFunc177,DispatchFunc16,DispatchFunc179,DispatchFunc16,DispatchFunc181,DispatchFunc182,DispatchFunc183,DispatchFunc184,DispatchFunc185,DispatchFunc186,DispatchFunc187,DispatchFunc188,DispatchFunc181,DispatchFunc26,DispatchFunc183,DispatchFunc51,DispatchFunc185 -,DispatchFunc67,DispatchFunc187,DispatchFunc83,DispatchFunc189,DispatchFunc190,DispatchFunc191,DispatchFunc192,DispatchFunc193,DispatchFunc194,DispatchFunc195,DispatchFunc196,DispatchFunc189,DispatchFunc27,DispatchFunc191,DispatchFunc36,DispatchFunc193,DispatchFunc16,DispatchFunc195,DispatchFunc16,DispatchFunc197 -,DispatchFunc198,DispatchFunc199,DispatchFunc200,DispatchFunc201,DispatchFunc202,DispatchFunc203,DispatchFunc204,DispatchFunc197,DispatchFunc28,DispatchFunc199,DispatchFunc52,DispatchFunc201,DispatchFunc68,DispatchFunc203,DispatchFunc84,DispatchFunc207,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc205,DefaultDispatchFunc,DispatchFunc37,DefaultDispatchFunc,DispatchFunc16,DefaultDispatchFunc,DispatchFunc16,DispatchFunc214,DispatchFunc215,DispatchFunc216,DispatchFunc217,DispatchFunc218,DispatchFunc219,DispatchFunc220,DispatchFunc221,DispatchFunc214 -,DefaultDispatchFunc,DispatchFunc216,DispatchFunc53,DispatchFunc218,DispatchFunc69,DispatchFunc220,DispatchFunc85,DispatchFunc209,DispatchFunc213,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc38,DefaultDispatchFunc -,DispatchFunc16,DefaultDispatchFunc,DispatchFunc16,DispatchFunc222,DispatchFunc223,DispatchFunc224,DispatchFunc225,DispatchFunc226,DispatchFunc227,DispatchFunc228,DispatchFunc229,DispatchFunc222,DefaultDispatchFunc,DispatchFunc224,DispatchFunc54,DispatchFunc226,DispatchFunc70,DispatchFunc228,DispatchFunc86,DispatchFunc208 -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc206,DefaultDispatchFunc,DispatchFunc39,DefaultDispatchFunc,DispatchFunc16,DefaultDispatchFunc,DispatchFunc16,DispatchFunc230,DispatchFunc231,DispatchFunc232,DispatchFunc233,DispatchFunc234 -,DispatchFunc235,DispatchFunc236,DispatchFunc237,DispatchFunc230,DefaultDispatchFunc,DispatchFunc232,DispatchFunc55,DispatchFunc234,DispatchFunc71,DispatchFunc236,DispatchFunc87,DispatchFunc210,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc40,DefaultDispatchFunc,DispatchFunc16,DefaultDispatchFunc,DispatchFunc16,DispatchFunc238,DispatchFunc239,DispatchFunc240,DispatchFunc241,DispatchFunc242,DispatchFunc243,DispatchFunc244,DispatchFunc245,DispatchFunc238,DefaultDispatchFunc,DispatchFunc240,DispatchFunc56,DispatchFunc242 -,DispatchFunc72,DispatchFunc244,DispatchFunc88,DispatchFunc246,DispatchFunc247,DispatchFunc248,DispatchFunc249,DispatchFunc250,DispatchFunc251,DispatchFunc252,DispatchFunc253,DispatchFunc246,DefaultDispatchFunc,DispatchFunc248,DispatchFunc41,DispatchFunc250,DispatchFunc16,DispatchFunc252,DispatchFunc16,DispatchFunc254 -,DispatchFunc255,DispatchFunc256,DispatchFunc257,DispatchFunc258,DispatchFunc259,DispatchFunc260,DispatchFunc261,DispatchFunc254,DefaultDispatchFunc,DispatchFunc256,DispatchFunc57,DispatchFunc258,DispatchFunc73,DispatchFunc260,DispatchFunc89,DispatchFunc262,DispatchFunc263,DispatchFunc264,DispatchFunc265,DispatchFunc266 -,DispatchFunc267,DispatchFunc268,DispatchFunc269,DispatchFunc262,DefaultDispatchFunc,DispatchFunc264,DispatchFunc42,DispatchFunc266,DispatchFunc16,DispatchFunc268,DispatchFunc16,DispatchFunc270,DispatchFunc271,DispatchFunc272,DispatchFunc273,DispatchFunc274,DispatchFunc275,DispatchFunc276,DispatchFunc277,DispatchFunc270 -,DefaultDispatchFunc,DispatchFunc272,DispatchFunc58,DispatchFunc274,DispatchFunc74,DispatchFunc276,DispatchFunc90,DispatchFunc278,DispatchFunc279,DispatchFunc280,DispatchFunc281,DispatchFunc282,DispatchFunc283,DispatchFunc284,DispatchFunc285,DispatchFunc278,DefaultDispatchFunc,DispatchFunc280,DispatchFunc43,DispatchFunc282 -,DispatchFunc16,DispatchFunc284,DispatchFunc16,DispatchFunc286,DispatchFunc287,DispatchFunc288,DispatchFunc289,DispatchFunc290,DispatchFunc291,DispatchFunc292,DispatchFunc293,DispatchFunc286,DefaultDispatchFunc,DispatchFunc288,DispatchFunc59,DispatchFunc290,DispatchFunc75,DispatchFunc292,DispatchFunc91,DispatchFunc294 -,DispatchFunc295,DispatchFunc296,DispatchFunc297,DispatchFunc298,DispatchFunc299,DispatchFunc300,DispatchFunc301,DispatchFunc294,DefaultDispatchFunc,DispatchFunc296,DispatchFunc44,DispatchFunc298,DispatchFunc16,DispatchFunc300,DispatchFunc16,DispatchFunc302,DispatchFunc303,DispatchFunc304,DispatchFunc305,DispatchFunc306 -,DispatchFunc307,DispatchFunc308,DispatchFunc309,DispatchFunc302,DefaultDispatchFunc,DispatchFunc304,DispatchFunc60,DispatchFunc306,DispatchFunc76,DispatchFunc308,DispatchFunc92,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310 -,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc310,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc311 -,DispatchFunc311,DispatchFunc311,DispatchFunc311,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc312,DispatchFunc313 -,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc313,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314 -,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc314,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315 -,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc315,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc316 -,DispatchFunc316,DispatchFunc316,DispatchFunc316,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc317,DispatchFunc318 -,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc318,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319 -,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc319,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320 -,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc320,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc321 -,DispatchFunc321,DispatchFunc321,DispatchFunc321,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc322,DispatchFunc323 -,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc323,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324 -,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc324,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325 -,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325,DispatchFunc325,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc326,DispatchFunc211 -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327 -,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327,DispatchFunc327,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc328 -,DispatchFunc328,DispatchFunc328,DispatchFunc328,DispatchFunc212,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc329 -,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc329,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330 -,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc330,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331 -,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc331,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc332 -,DispatchFunc332,DispatchFunc332,DispatchFunc332,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc333,DispatchFunc334 -,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc334,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335 -,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc335,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336 -,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc336,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc337 -,DispatchFunc337,DispatchFunc337,DispatchFunc337,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc338,DispatchFunc354 -,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc354,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339 -,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc339,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355 -,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc355,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc340 -,DispatchFunc340,DispatchFunc340,DispatchFunc340,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc356,DispatchFunc341 -,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc341,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357 -,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc357,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342 -,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc342,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc358 -,DispatchFunc358,DispatchFunc358,DispatchFunc358,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc343,DispatchFunc359 -,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc359,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344 -,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc344,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360 -,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc360,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc345 -,DispatchFunc345,DispatchFunc345,DispatchFunc345,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc361,DispatchFunc346 -,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc346,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362 -,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc362,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347 -,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc347,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc363 -,DispatchFunc363,DispatchFunc363,DispatchFunc363,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc348,DispatchFunc364 -,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc364,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349 -,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc349,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365 -,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc365,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc350 -,DispatchFunc350,DispatchFunc350,DispatchFunc350,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc366,DispatchFunc351 -,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc351,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367 -,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc367,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352 -,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc352,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc368 -,DispatchFunc368,DispatchFunc368,DispatchFunc368,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc353,DispatchFunc369 -,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc369,DispatchFunc370,DefaultDispatchFunc,DispatchFunc371,DefaultDispatchFunc,DispatchFunc372 -,DefaultDispatchFunc,DispatchFunc373,DefaultDispatchFunc,DispatchFunc370,DefaultDispatchFunc,DispatchFunc371,DefaultDispatchFunc,DispatchFunc372,DefaultDispatchFunc,DispatchFunc373,DefaultDispatchFunc,DispatchFunc434,DefaultDispatchFunc,DispatchFunc435,DefaultDispatchFunc,DispatchFunc436,DefaultDispatchFunc,DispatchFunc437,DefaultDispatchFunc,DispatchFunc434 -,DefaultDispatchFunc,DispatchFunc435,DefaultDispatchFunc,DispatchFunc436,DefaultDispatchFunc,DispatchFunc437,DefaultDispatchFunc,DispatchFunc374,DefaultDispatchFunc,DispatchFunc375,DefaultDispatchFunc,DispatchFunc376,DefaultDispatchFunc,DispatchFunc377,DefaultDispatchFunc,DispatchFunc374,DefaultDispatchFunc,DispatchFunc375,DefaultDispatchFunc,DispatchFunc376 -,DefaultDispatchFunc,DispatchFunc377,DefaultDispatchFunc,DispatchFunc438,DefaultDispatchFunc,DispatchFunc439,DefaultDispatchFunc,DispatchFunc440,DefaultDispatchFunc,DispatchFunc441,DefaultDispatchFunc,DispatchFunc438,DefaultDispatchFunc,DispatchFunc439,DefaultDispatchFunc,DispatchFunc440,DefaultDispatchFunc,DispatchFunc441,DefaultDispatchFunc,DispatchFunc378 -,DefaultDispatchFunc,DispatchFunc379,DefaultDispatchFunc,DispatchFunc380,DefaultDispatchFunc,DispatchFunc381,DefaultDispatchFunc,DispatchFunc378,DefaultDispatchFunc,DispatchFunc379,DefaultDispatchFunc,DispatchFunc380,DefaultDispatchFunc,DispatchFunc381,DefaultDispatchFunc,DispatchFunc442,DefaultDispatchFunc,DispatchFunc443,DefaultDispatchFunc,DispatchFunc444 -,DefaultDispatchFunc,DispatchFunc445,DefaultDispatchFunc,DispatchFunc442,DefaultDispatchFunc,DispatchFunc443,DefaultDispatchFunc,DispatchFunc444,DefaultDispatchFunc,DispatchFunc445,DefaultDispatchFunc,DispatchFunc382,DefaultDispatchFunc,DispatchFunc383,DefaultDispatchFunc,DispatchFunc384,DefaultDispatchFunc,DispatchFunc385,DefaultDispatchFunc,DispatchFunc382 -,DefaultDispatchFunc,DispatchFunc383,DefaultDispatchFunc,DispatchFunc384,DefaultDispatchFunc,DispatchFunc385,DefaultDispatchFunc,DispatchFunc446,DefaultDispatchFunc,DispatchFunc447,DefaultDispatchFunc,DispatchFunc448,DefaultDispatchFunc,DispatchFunc449,DefaultDispatchFunc,DispatchFunc446,DefaultDispatchFunc,DispatchFunc447,DefaultDispatchFunc,DispatchFunc448 -,DefaultDispatchFunc,DispatchFunc449,DefaultDispatchFunc,DispatchFunc386,DefaultDispatchFunc,DispatchFunc387,DefaultDispatchFunc,DispatchFunc388,DefaultDispatchFunc,DispatchFunc389,DefaultDispatchFunc,DispatchFunc386,DefaultDispatchFunc,DispatchFunc387,DefaultDispatchFunc,DispatchFunc388,DefaultDispatchFunc,DispatchFunc389,DefaultDispatchFunc,DispatchFunc450 -,DefaultDispatchFunc,DispatchFunc451,DefaultDispatchFunc,DispatchFunc452,DefaultDispatchFunc,DispatchFunc453,DefaultDispatchFunc,DispatchFunc450,DefaultDispatchFunc,DispatchFunc451,DefaultDispatchFunc,DispatchFunc452,DefaultDispatchFunc,DispatchFunc453,DefaultDispatchFunc,DispatchFunc390,DefaultDispatchFunc,DispatchFunc390,DefaultDispatchFunc,DispatchFunc391 -,DefaultDispatchFunc,DispatchFunc391,DefaultDispatchFunc,DispatchFunc392,DefaultDispatchFunc,DispatchFunc392,DefaultDispatchFunc,DispatchFunc393,DefaultDispatchFunc,DispatchFunc393,DefaultDispatchFunc,DispatchFunc454,DefaultDispatchFunc,DispatchFunc455,DefaultDispatchFunc,DispatchFunc456,DefaultDispatchFunc,DispatchFunc457,DefaultDispatchFunc,DispatchFunc454 -,DefaultDispatchFunc,DispatchFunc455,DefaultDispatchFunc,DispatchFunc456,DefaultDispatchFunc,DispatchFunc457,DefaultDispatchFunc,DispatchFunc394,DefaultDispatchFunc,DispatchFunc395,DefaultDispatchFunc,DispatchFunc396,DefaultDispatchFunc,DispatchFunc397,DefaultDispatchFunc,DispatchFunc394,DefaultDispatchFunc,DispatchFunc395,DefaultDispatchFunc,DispatchFunc396 -,DefaultDispatchFunc,DispatchFunc397,DefaultDispatchFunc,DispatchFunc458,DefaultDispatchFunc,DispatchFunc459,DefaultDispatchFunc,DispatchFunc460,DefaultDispatchFunc,DispatchFunc461,DefaultDispatchFunc,DispatchFunc458,DefaultDispatchFunc,DispatchFunc459,DefaultDispatchFunc,DispatchFunc460,DefaultDispatchFunc,DispatchFunc461,DefaultDispatchFunc,DispatchFunc398 -,DefaultDispatchFunc,DispatchFunc399,DefaultDispatchFunc,DispatchFunc400,DefaultDispatchFunc,DispatchFunc401,DefaultDispatchFunc,DispatchFunc398,DefaultDispatchFunc,DispatchFunc399,DefaultDispatchFunc,DispatchFunc400,DefaultDispatchFunc,DispatchFunc401,DefaultDispatchFunc,DispatchFunc462,DefaultDispatchFunc,DispatchFunc463,DefaultDispatchFunc,DispatchFunc464 -,DefaultDispatchFunc,DispatchFunc465,DefaultDispatchFunc,DispatchFunc462,DefaultDispatchFunc,DispatchFunc463,DefaultDispatchFunc,DispatchFunc464,DefaultDispatchFunc,DispatchFunc465,DefaultDispatchFunc,DispatchFunc402,DefaultDispatchFunc,DispatchFunc403,DefaultDispatchFunc,DispatchFunc404,DefaultDispatchFunc,DispatchFunc405,DefaultDispatchFunc,DispatchFunc402 -,DefaultDispatchFunc,DispatchFunc403,DefaultDispatchFunc,DispatchFunc404,DefaultDispatchFunc,DispatchFunc405,DefaultDispatchFunc,DispatchFunc466,DefaultDispatchFunc,DispatchFunc467,DefaultDispatchFunc,DispatchFunc468,DefaultDispatchFunc,DispatchFunc469,DefaultDispatchFunc,DispatchFunc466,DefaultDispatchFunc,DispatchFunc467,DefaultDispatchFunc,DispatchFunc468 -,DefaultDispatchFunc,DispatchFunc469,DefaultDispatchFunc,DispatchFunc406,DefaultDispatchFunc,DispatchFunc407,DefaultDispatchFunc,DispatchFunc408,DefaultDispatchFunc,DispatchFunc409,DefaultDispatchFunc,DispatchFunc406,DefaultDispatchFunc,DispatchFunc407,DefaultDispatchFunc,DispatchFunc408,DefaultDispatchFunc,DispatchFunc409,DefaultDispatchFunc,DispatchFunc470 -,DefaultDispatchFunc,DispatchFunc471,DefaultDispatchFunc,DispatchFunc472,DefaultDispatchFunc,DispatchFunc473,DefaultDispatchFunc,DispatchFunc470,DefaultDispatchFunc,DispatchFunc471,DefaultDispatchFunc,DispatchFunc472,DefaultDispatchFunc,DispatchFunc473,DefaultDispatchFunc,DispatchFunc410,DefaultDispatchFunc,DispatchFunc411,DefaultDispatchFunc,DispatchFunc412 -,DefaultDispatchFunc,DispatchFunc413,DefaultDispatchFunc,DispatchFunc410,DefaultDispatchFunc,DispatchFunc411,DefaultDispatchFunc,DispatchFunc412,DefaultDispatchFunc,DispatchFunc413,DefaultDispatchFunc,DispatchFunc474,DefaultDispatchFunc,DispatchFunc475,DefaultDispatchFunc,DispatchFunc476,DefaultDispatchFunc,DispatchFunc477,DefaultDispatchFunc,DispatchFunc474 -,DefaultDispatchFunc,DispatchFunc475,DefaultDispatchFunc,DispatchFunc476,DefaultDispatchFunc,DispatchFunc477,DefaultDispatchFunc,DispatchFunc414,DefaultDispatchFunc,DispatchFunc415,DefaultDispatchFunc,DispatchFunc416,DefaultDispatchFunc,DispatchFunc417,DefaultDispatchFunc,DispatchFunc414,DefaultDispatchFunc,DispatchFunc415,DefaultDispatchFunc,DispatchFunc416 -,DefaultDispatchFunc,DispatchFunc417,DefaultDispatchFunc,DispatchFunc478,DefaultDispatchFunc,DispatchFunc479,DefaultDispatchFunc,DispatchFunc480,DefaultDispatchFunc,DispatchFunc481,DefaultDispatchFunc,DispatchFunc478,DefaultDispatchFunc,DispatchFunc479,DefaultDispatchFunc,DispatchFunc480,DefaultDispatchFunc,DispatchFunc481,DefaultDispatchFunc,DispatchFunc418 -,DefaultDispatchFunc,DispatchFunc419,DefaultDispatchFunc,DispatchFunc420,DefaultDispatchFunc,DispatchFunc421,DefaultDispatchFunc,DispatchFunc418,DefaultDispatchFunc,DispatchFunc419,DefaultDispatchFunc,DispatchFunc420,DefaultDispatchFunc,DispatchFunc421,DefaultDispatchFunc,DispatchFunc482,DefaultDispatchFunc,DispatchFunc483,DefaultDispatchFunc,DispatchFunc484 -,DefaultDispatchFunc,DispatchFunc485,DefaultDispatchFunc,DispatchFunc482,DefaultDispatchFunc,DispatchFunc483,DefaultDispatchFunc,DispatchFunc484,DefaultDispatchFunc,DispatchFunc485,DefaultDispatchFunc,DispatchFunc422,DefaultDispatchFunc,DispatchFunc423,DefaultDispatchFunc,DispatchFunc424,DefaultDispatchFunc,DispatchFunc425,DefaultDispatchFunc,DispatchFunc422 -,DefaultDispatchFunc,DispatchFunc423,DefaultDispatchFunc,DispatchFunc424,DefaultDispatchFunc,DispatchFunc425,DefaultDispatchFunc,DispatchFunc486,DefaultDispatchFunc,DispatchFunc487,DefaultDispatchFunc,DispatchFunc488,DefaultDispatchFunc,DispatchFunc489,DefaultDispatchFunc,DispatchFunc486,DefaultDispatchFunc,DispatchFunc487,DefaultDispatchFunc,DispatchFunc488 -,DefaultDispatchFunc,DispatchFunc489,DefaultDispatchFunc,DispatchFunc426,DefaultDispatchFunc,DispatchFunc427,DefaultDispatchFunc,DispatchFunc428,DefaultDispatchFunc,DispatchFunc429,DefaultDispatchFunc,DispatchFunc426,DefaultDispatchFunc,DispatchFunc427,DefaultDispatchFunc,DispatchFunc428,DefaultDispatchFunc,DispatchFunc429,DefaultDispatchFunc,DispatchFunc490 -,DefaultDispatchFunc,DispatchFunc491,DefaultDispatchFunc,DispatchFunc492,DefaultDispatchFunc,DispatchFunc493,DefaultDispatchFunc,DispatchFunc490,DefaultDispatchFunc,DispatchFunc491,DefaultDispatchFunc,DispatchFunc492,DefaultDispatchFunc,DispatchFunc493,DefaultDispatchFunc,DispatchFunc430,DefaultDispatchFunc,DispatchFunc431,DefaultDispatchFunc,DispatchFunc432 -,DefaultDispatchFunc,DispatchFunc433,DefaultDispatchFunc,DispatchFunc430,DefaultDispatchFunc,DispatchFunc431,DefaultDispatchFunc,DispatchFunc432,DefaultDispatchFunc,DispatchFunc433,DefaultDispatchFunc,DispatchFunc494,DefaultDispatchFunc,DispatchFunc495,DefaultDispatchFunc,DispatchFunc496,DefaultDispatchFunc,DispatchFunc497,DefaultDispatchFunc,DispatchFunc494 -,DefaultDispatchFunc,DispatchFunc495,DefaultDispatchFunc,DispatchFunc496,DefaultDispatchFunc,DispatchFunc497,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498 -,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc498,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499 -,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DispatchFunc499,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc -,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DefaultDispatchFunc,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500,DispatchFunc500 -}; - } - #endregion Delegate Dispatcher - } -} diff --git a/attic/GarboDev/GbaManager.cs b/attic/GarboDev/GbaManager.cs deleted file mode 100644 index b03dd4852c..0000000000 --- a/attic/GarboDev/GbaManager.cs +++ /dev/null @@ -1,469 +0,0 @@ -//#define ARM_DEBUG - -namespace GarboDev -{ - using System; - using System.IO; - using System.Threading; - using System.Timers; - using System.Windows.Forms; - using System.Collections.Generic; - - using BizHawk.Emulation; - using BizHawk; - - public class GbaManager : IEmulator, ISyncSoundProvider, IVideoProvider - { - public const int cpuFreq = 16 * 1024 * 1024; - - private int framesRendered; - - private Arm7Processor arm7 = null; - private Memory memory = null; - private VideoManager videoManager = null; - private SoundManager soundManager = null; - - private bool skipBios = false; - - public delegate void CpuUpdateDelegate(Arm7Processor processor, Memory memory); - private event CpuUpdateDelegate onCpuUpdate = null; - - public Arm7Processor Arm7 - { - get { return this.arm7; } - } - - public VideoManager VideoManager - { - get { return this.videoManager; } - } - - public SoundManager SoundManager - { - get { return this.soundManager; } - } - - public Memory Memory - { - get { return this.memory; } - } - - public Dictionary Breakpoints - { - get { return this.arm7.Breakpoints; } - } - - public ushort KeyState - { - get - { - if (this.memory != null) - { - return this.memory.KeyState; - } - - return 0x3FF; - } - - set - { - this.arm7.KeyState = value; - } - } - - public int FramesRendered - { - get { return this.framesRendered; } - set { this.framesRendered = value; } - } - - public event CpuUpdateDelegate OnCpuUpdate - { - add - { - this.onCpuUpdate += value; - this.onCpuUpdate(this.arm7, this.memory); - } - remove - { - this.onCpuUpdate -= value; - } - } - - public bool SkipBios - { - get { return this.skipBios; } - set { this.skipBios = value; } - } - - public GbaManager(CoreComm comm) - { - _corecomm = comm; - - this.memory = new Memory(); - this.arm7 = new Arm7Processor(this.memory); - this.videoManager = new VideoManager(this); - this.videoManager.Memory = this.memory; - this.soundManager = new SoundManager(this.memory, 44100); - - this.framesRendered = 0; - Renderer renderer = new Renderer(); - renderer.Initialize(null); - VideoManager.Renderer = renderer; - - videoManager.Presenter = delegate(uint[] data) - { - Buffer.BlockCopy(data, 0, this.vbuf, 0, 240 * 160 * 4); - }; - } - - public void Load(byte[] rom, byte[] bios) - { - LoadBios(bios); - LoadRom(rom); - } - - public void Reset() - { - //this.Halt(); - - this.arm7.Reset(this.skipBios); - this.memory.Reset(); - this.videoManager.Reset(); - } - - public void LoadState(BinaryReader state) - { - } - - public void SaveState(BinaryWriter state) - { - state.Write("GARB"); - } - - public void LoadBios(byte[] biosRom) - { - this.memory.LoadBios(biosRom); - - if (this.onCpuUpdate != null) - { - this.onCpuUpdate(this.arm7, this.memory); - } - } - - public void LoadRom(byte[] cartRom) - { - //this.Halt(); - - /* - byte[] logo = new byte[] - { - 0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21, - 0x3d,0x84,0x82,0x0a,0x84,0xe4,0x09,0xad, - 0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21, - 0xa3,0x52,0xbe,0x19,0x93,0x09,0xce,0x20, - 0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec, - 0x58,0xc7,0xe8,0x33,0x82,0xe3,0xce,0xbf, - 0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1, - 0x94,0x56,0x8a,0xc0,0x13,0x72,0xa7,0xfc, - 0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61, - 0x58,0x97,0xa3,0x27,0xfc,0x03,0x98,0x76, - 0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56, - 0xbf,0x38,0x84,0x00,0x40,0xa7,0x0e,0xfd, - 0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1, - 0x97,0xfb,0xc0,0x85,0x60,0xd6,0x80,0x25, - 0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2, - 0xf9,0xa2,0x34,0xff,0xbb,0x3e,0x03,0x44, - 0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94, - 0x65,0xc0,0x7c,0x63,0x87,0xf0,0x3c,0xaf, - 0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72, - 0x21,0xd4,0xf8,0x07 - }; - - Array.Copy(logo, 0, cartRom, 4, logo.Length); - cartRom[0xB2] = 0x96; - cartRom[0xBD] = 0; - for (int i = 0xA0; i <= 0xBC; i++) cartRom[0xBD] = (byte)(cartRom[0xBD] - cartRom[i]); - cartRom[0xBD] = (byte)((cartRom[0xBD] - 0x19) & 0xFF); - */ - this.memory.LoadCartridge(cartRom); - - this.Reset(); - - if (this.onCpuUpdate != null) - { - this.onCpuUpdate(this.arm7, this.memory); - } - } - - public void Step() - { - //this.Halt(); - - this.arm7.Step(); - - if (this.onCpuUpdate != null) - { - this.onCpuUpdate(this.arm7, this.memory); - } - } - - public void StepScanline() - { - //this.Halt(); - - this.arm7.Execute(960); - this.videoManager.RenderLine(); - this.videoManager.EnterHBlank(this.arm7); - this.arm7.Execute(272); - this.videoManager.LeaveHBlank(this.arm7); - - if (this.onCpuUpdate != null) - { - this.onCpuUpdate(this.arm7, this.memory); - } - } - - void UpdateInputState() - { - ushort ret = 0; - if (_controller["Up"]) ret |= 64; - if (_controller["Down"]) ret |= 128; - if (_controller["Left"]) ret |= 32; - if (_controller["Right"]) ret |= 16; - if (_controller["Select"]) ret |= 4; - if (_controller["Start"]) ret |= 8; - if (_controller["B"]) ret |= 2; - if (_controller["A"]) ret |= 1; - if (_controller["L"]) ret |= 512; - if (_controller["R"]) ret |= 256; - ret ^= 0x3ff; - KeyState = ret; - } - - private void StepFrame() - { - UpdateInputState(); - if (_controller["Power"]) - Reset(); - - int vramCycles = 0; - bool inHblank = false; - - //HighPerformanceTimer profileTimer = new HighPerformanceTimer(); - - while (true) - { - - - const int cycleStep = 123; - - - if (vramCycles <= 0) - { - if (inHblank) - { - vramCycles += 960; - bool HitVBlank = this.videoManager.LeaveHBlank(this.arm7); - inHblank = false; - if (HitVBlank) - break; - } - else - { - vramCycles += 272; - this.videoManager.RenderLine(); - this.videoManager.EnterHBlank(this.arm7); - inHblank = true; - } - } - - this.arm7.Execute(cycleStep); -#if ARM_DEBUG - if (this.arm7.BreakpointHit) - { - this.waitingToHalt = true; - Monitor.Wait(this); - } -#endif - vramCycles -= cycleStep; - this.arm7.FireIrq(); - } - - - } - - IVideoProvider IEmulator.VideoProvider - { - get { return this; } - } - - ISoundProvider IEmulator.SoundProvider - { - get { return null; } - } - - ISyncSoundProvider IEmulator.SyncSoundProvider - { - get { return this; } - } - - bool IEmulator.StartAsyncSound() - { - return false; - } - - void IEmulator.EndAsyncSound() - { - - } - - ControllerDefinition IEmulator.ControllerDefinition - { - get { return BizHawk.Emulation.Consoles.Nintendo.GBA.GBA.GBAController; } - } - - IController _controller; - - IController IEmulator.Controller - { - get { return _controller; } - set { _controller = value; } - } - - void IEmulator.FrameAdvance(bool render, bool rendersound) - { - StepFrame(); - } - - int IEmulator.Frame - { - get { return 0; } - } - - int IEmulator.LagCount - { - get - { - return 0; - } - set - { - - } - } - - bool IEmulator.IsLagFrame - { - get { return false; } - } - - string IEmulator.SystemId - { - get { return "GBA"; } - } - - bool IEmulator.DeterministicEmulation - { - get { return true; } - } - - byte[] IEmulator.ReadSaveRam() - { - return new byte[0]; - } - - void IEmulator.StoreSaveRam(byte[] data) - { - - } - - void IEmulator.ClearSaveRam() - { - - } - - bool IEmulator.SaveRamModified - { - get - { - return false; - } - set - { - - } - } - - void IEmulator.ResetFrameCounter() - { - - } - - void IEmulator.SaveStateText(TextWriter writer) - { - - } - - void IEmulator.LoadStateText(TextReader reader) - { - - } - - void IEmulator.SaveStateBinary(BinaryWriter writer) - { - - } - - void IEmulator.LoadStateBinary(BinaryReader reader) - { - - } - - byte[] IEmulator.SaveStateBinary() - { - return new byte[16]; - } - - CoreComm _corecomm; - - CoreComm IEmulator.CoreComm - { - get { return _corecomm; } - } - - IList IEmulator.MemoryDomains - { - get { return new List(); } - } - - MemoryDomain IEmulator.MainMemory - { - get { return null; } - } - - void IDisposable.Dispose() - { - - } - - int[] vbuf = new int[240 * 160]; - int[] IVideoProvider.GetVideoBuffer() { return vbuf; } - int IVideoProvider.VirtualWidth { get { return 240; } } - int IVideoProvider.BufferWidth { get { return 240; } } - int IVideoProvider.BufferHeight { get { return 160; } } - int IVideoProvider.BackgroundColor { get { return unchecked((int)0xff000000); } } - - void ISyncSoundProvider.GetSamples(out short[] samples, out int nsamp) - { - nsamp = soundManager.SamplesMixed / 2; - samples = new short[nsamp * 2]; - soundManager.GetSamples(samples, nsamp * 2); - } - - void ISyncSoundProvider.DiscardSamples() - { - // should implement - } - } -} diff --git a/attic/GarboDev/IRenderer.cs b/attic/GarboDev/IRenderer.cs deleted file mode 100644 index 20fce17447..0000000000 --- a/attic/GarboDev/IRenderer.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace GarboDev -{ - using System; - - public interface IRenderer - { - Memory Memory { set; } - void Initialize(object data); - void Reset(); - void RenderLine(int line); - uint[] ShowFrame(); - } -} diff --git a/attic/GarboDev/Memory.cs b/attic/GarboDev/Memory.cs deleted file mode 100644 index e10058db14..0000000000 --- a/attic/GarboDev/Memory.cs +++ /dev/null @@ -1,1981 +0,0 @@ -namespace GarboDev -{ - using System; - using System.Collections.Generic; - - public class Memory - { - public const uint REG_BASE = 0x4000000; - public const uint PAL_BASE = 0x5000000; - public const uint VRAM_BASE = 0x6000000; - public const uint OAM_BASE = 0x7000000; - - public const uint DISPCNT = 0x0; - public const uint DISPSTAT = 0x4; - public const uint VCOUNT = 0x6; - - public const uint BG0CNT = 0x8; - public const uint BG1CNT = 0xA; - public const uint BG2CNT = 0xC; - public const uint BG3CNT = 0xE; - - public const uint BG0HOFS = 0x10; - public const uint BG0VOFS = 0x12; - public const uint BG1HOFS = 0x14; - public const uint BG1VOFS = 0x16; - public const uint BG2HOFS = 0x18; - public const uint BG2VOFS = 0x1A; - public const uint BG3HOFS = 0x1C; - public const uint BG3VOFS = 0x1E; - - public const uint BG2PA = 0x20; - public const uint BG2PB = 0x22; - public const uint BG2PC = 0x24; - public const uint BG2PD = 0x26; - public const uint BG2X_L = 0x28; - public const uint BG2X_H = 0x2A; - public const uint BG2Y_L = 0x2C; - public const uint BG2Y_H = 0x2E; - public const uint BG3PA = 0x30; - public const uint BG3PB = 0x32; - public const uint BG3PC = 0x34; - public const uint BG3PD = 0x36; - public const uint BG3X_L = 0x38; - public const uint BG3X_H = 0x3A; - public const uint BG3Y_L = 0x3C; - public const uint BG3Y_H = 0x3E; - - public const uint WIN0H = 0x40; - public const uint WIN1H = 0x42; - public const uint WIN0V = 0x44; - public const uint WIN1V = 0x46; - public const uint WININ = 0x48; - public const uint WINOUT = 0x4A; - - public const uint BLDCNT = 0x50; - public const uint BLDALPHA = 0x52; - public const uint BLDY = 0x54; - - public const uint SOUNDCNT_L = 0x80; - public const uint SOUNDCNT_H = 0x82; - public const uint SOUNDCNT_X = 0x84; - - public const uint FIFO_A_L = 0xA0; - public const uint FIFO_A_H = 0xA2; - public const uint FIFO_B_L = 0xA4; - public const uint FIFO_B_H = 0xA6; - - public const uint DMA0SAD = 0xB0; - public const uint DMA0DAD = 0xB4; - public const uint DMA0CNT_L = 0xB8; - public const uint DMA0CNT_H = 0xBA; - public const uint DMA1SAD = 0xBC; - public const uint DMA1DAD = 0xC0; - public const uint DMA1CNT_L = 0xC4; - public const uint DMA1CNT_H = 0xC6; - public const uint DMA2SAD = 0xC8; - public const uint DMA2DAD = 0xCC; - public const uint DMA2CNT_L = 0xD0; - public const uint DMA2CNT_H = 0xD2; - public const uint DMA3SAD = 0xD4; - public const uint DMA3DAD = 0xD8; - public const uint DMA3CNT_L = 0xDC; - public const uint DMA3CNT_H = 0xDE; - - public const uint TM0D = 0x100; - public const uint TM0CNT = 0x102; - public const uint TM1D = 0x104; - public const uint TM1CNT = 0x106; - public const uint TM2D = 0x108; - public const uint TM2CNT = 0x10A; - public const uint TM3D = 0x10C; - public const uint TM3CNT = 0x10E; - - public const uint KEYINPUT = 0x130; - public const uint KEYCNT = 0x132; - public const uint IE = 0x200; - public const uint IF = 0x202; - public const uint IME = 0x208; - - public const uint HALTCNT = 0x300; - - private const uint biosRamMask = 0x3FFF; - private const uint ewRamMask = 0x3FFFF; - private const uint iwRamMask = 0x7FFF; - private const uint ioRegMask = 0x4FF; - private const uint vRamMask = 0x1FFFF; - private const uint palRamMask = 0x3FF; - private const uint oamRamMask = 0x3FF; - private const uint sRamMask = 0xFFFF; - - private byte[] biosRam = new byte[Memory.biosRamMask + 1]; - private byte[] ewRam = new byte[Memory.ewRamMask + 1]; - private byte[] iwRam = new byte[Memory.iwRamMask + 1]; - private byte[] ioReg = new byte[Memory.ioRegMask + 1]; - private byte[] vRam = new byte[Memory.vRamMask + 1]; - private byte[] palRam = new byte[Memory.palRamMask + 1]; - private byte[] oamRam = new byte[Memory.oamRamMask + 1]; - private byte[] sRam = new byte[Memory.sRamMask + 1]; - - public byte[] VideoRam - { - get - { - return this.vRam; - } - } - - public byte[] PaletteRam - { - get - { - return this.palRam; - } - } - - public byte[] OamRam - { - get - { - return this.oamRam; - } - } - - public byte[] IORam - { - get - { - return this.ioReg; - } - } - - private ushort keyState = 0x3FF; - - public ushort KeyState - { - get { return this.keyState; } - set { this.keyState = value; } - } - - private Arm7Processor processor = null; - public Arm7Processor Processor - { - get { return this.processor; } - set { this.processor = value; } - } - - private SoundManager soundManager = null; - public SoundManager SoundManager - { - get { return this.soundManager; } - set { this.soundManager = value; } - } - - private byte[] romBank1 = null; - private byte[] romBank2 = null; - private uint romBank1Mask = 0; - private uint romBank2Mask = 0; - - private int[] bankSTimes = new int[0x10]; - private int[] bankNTimes = new int[0x10]; - - private int waitCycles = 0; - - public int WaitCycles - { - get { int tmp = this.waitCycles; this.waitCycles = 0; return tmp; } - } - - private bool inUnreadable = false; - - private delegate byte ReadU8Delegate(uint address); - private delegate void WriteU8Delegate(uint address, byte value); - private delegate ushort ReadU16Delegate(uint address); - private delegate void WriteU16Delegate(uint address, ushort value); - private delegate uint ReadU32Delegate(uint address); - private delegate void WriteU32Delegate(uint address, uint value); - - private ReadU8Delegate[] ReadU8Funcs = null; - private WriteU8Delegate[] WriteU8Funcs = null; - private ReadU16Delegate[] ReadU16Funcs = null; - private WriteU16Delegate[] WriteU16Funcs = null; - private ReadU32Delegate[] ReadU32Funcs = null; - private WriteU32Delegate[] WriteU32Funcs = null; - - private uint[,] dmaRegs = new uint[4, 4]; - private uint[] timerCnt = new uint[4]; - private int[] bgx = new int[2], bgy = new int[2]; - - public uint[] TimerCnt - { - get { return this.timerCnt; } - } - - public int[] Bgx - { - get { return this.bgx; } - } - - public int[] Bgy - { - get { return this.bgy; } - } - - public Memory() - { - this.ReadU8Funcs = new ReadU8Delegate[] - { - this.ReadBiosRam8, - this.ReadNop8, - this.ReadEwRam8, - this.ReadIwRam8, - this.ReadIO8, - this.ReadPalRam8, - this.ReadVRam8, - this.ReadOamRam8, - this.ReadNop8, - this.ReadNop8, - this.ReadNop8, - this.ReadNop8, - this.ReadNop8, - this.ReadNop8, - this.ReadSRam8, - this.ReadNop8 - }; - - this.WriteU8Funcs = new WriteU8Delegate[] - { - this.WriteNop8, - this.WriteNop8, - this.WriteEwRam8, - this.WriteIwRam8, - this.WriteIO8, - this.WritePalRam8, - this.WriteVRam8, - this.WriteOamRam8, - this.WriteNop8, - this.WriteNop8, - this.WriteNop8, - this.WriteNop8, - this.WriteNop8, - this.WriteNop8, - this.WriteSRam8, - this.WriteNop8 - }; - - this.ReadU16Funcs = new ReadU16Delegate[] - { - this.ReadBiosRam16, - this.ReadNop16, - this.ReadEwRam16, - this.ReadIwRam16, - this.ReadIO16, - this.ReadPalRam16, - this.ReadVRam16, - this.ReadOamRam16, - this.ReadNop16, - this.ReadNop16, - this.ReadNop16, - this.ReadNop16, - this.ReadNop16, - this.ReadNop16, - this.ReadSRam16, - this.ReadNop16 - }; - - this.WriteU16Funcs = new WriteU16Delegate[] - { - this.WriteNop16, - this.WriteNop16, - this.WriteEwRam16, - this.WriteIwRam16, - this.WriteIO16, - this.WritePalRam16, - this.WriteVRam16, - this.WriteOamRam16, - this.WriteNop16, - this.WriteNop16, - this.WriteNop16, - this.WriteNop16, - this.WriteNop16, - this.WriteNop16, - this.WriteSRam16, - this.WriteNop16 - }; - - this.ReadU32Funcs = new ReadU32Delegate[] - { - this.ReadBiosRam32, - this.ReadNop32, - this.ReadEwRam32, - this.ReadIwRam32, - this.ReadIO32, - this.ReadPalRam32, - this.ReadVRam32, - this.ReadOamRam32, - this.ReadNop32, - this.ReadNop32, - this.ReadNop32, - this.ReadNop32, - this.ReadNop32, - this.ReadNop32, - this.ReadSRam32, - this.ReadNop32 - }; - - this.WriteU32Funcs = new WriteU32Delegate[] - { - this.WriteNop32, - this.WriteNop32, - this.WriteEwRam32, - this.WriteIwRam32, - this.WriteIO32, - this.WritePalRam32, - this.WriteVRam32, - this.WriteOamRam32, - this.WriteNop32, - this.WriteNop32, - this.WriteNop32, - this.WriteNop32, - this.WriteNop32, - this.WriteNop32, - this.WriteSRam32, - this.WriteNop32 - }; - } - - public void Reset() - { - Array.Clear(this.ewRam, 0, this.ewRam.Length); - Array.Clear(this.iwRam, 0, this.iwRam.Length); - Array.Clear(this.ioReg, 0, this.ioReg.Length); - Array.Clear(this.vRam, 0, this.vRam.Length); - Array.Clear(this.palRam, 0, this.palRam.Length); - Array.Clear(this.oamRam, 0, this.oamRam.Length); - Array.Clear(this.sRam, 0, this.sRam.Length); - - Memory.WriteU16(this.ioReg, Memory.BG2PA, 0x0100); - Memory.WriteU16(this.ioReg, Memory.BG2PD, 0x0100); - Memory.WriteU16(this.ioReg, Memory.BG3PA, 0x0100); - Memory.WriteU16(this.ioReg, Memory.BG3PD, 0x0100); - } - - public void HBlankDma() - { - for (int i = 0; i < 4; i++) - { - if (((this.dmaRegs[i, 3] >> 12) & 0x3) == 2) - { - this.DmaTransfer(i); - } - } - } - - public void VBlankDma() - { - for (int i = 0; i < 4; i++) - { - if (((this.dmaRegs[i, 3] >> 12) & 0x3) == 1) - { - this.DmaTransfer(i); - } - } - } - - public void FifoDma(int channel) - { - if (((this.dmaRegs[channel, 3] >> 12) & 0x3) == 0x3) - { - this.DmaTransfer(channel); - } - } - - public void DmaTransfer(int channel) - { - // Check if DMA is enabled - if ((this.dmaRegs[channel, 3] & (1 << 15)) != 0) - { - bool wideTransfer = (this.dmaRegs[channel, 3] & (1 << 10)) != 0; - - uint srcDirection = 0, destDirection = 0; - bool reload = false; - - switch ((this.dmaRegs[channel, 3] >> 5) & 0x3) - { - case 0: destDirection = 1; break; - case 1: destDirection = 0xFFFFFFFF; break; - case 2: destDirection = 0; break; - case 3: destDirection = 1; reload = true; break; - } - - switch ((this.dmaRegs[channel, 3] >> 7) & 0x3) - { - case 0: srcDirection = 1; break; - case 1: srcDirection = 0xFFFFFFFF; break; - case 2: srcDirection = 0; break; - case 3: if (channel == 3) - { - // TODO - return; - } - throw new Exception("Unhandled DMA mode."); - } - - int numElements = (int)this.dmaRegs[channel, 2]; - if (numElements == 0) numElements = 0x4000; - - if (((this.dmaRegs[channel, 3] >> 12) & 0x3) == 0x3) - { - // Sound FIFO mode - wideTransfer = true; - destDirection = 0; - numElements = 4; - reload = false; - } - - if (wideTransfer) - { - srcDirection *= 4; - destDirection *= 4; - while (numElements-- > 0) - { - this.WriteU32(this.dmaRegs[channel, 1], this.ReadU32(this.dmaRegs[channel, 0])); - this.dmaRegs[channel, 1] += destDirection; - this.dmaRegs[channel, 0] += srcDirection; - } - } - else - { - srcDirection *= 2; - destDirection *= 2; - while (numElements-- > 0) - { - this.WriteU16(this.dmaRegs[channel, 1], this.ReadU16(this.dmaRegs[channel, 0])); - this.dmaRegs[channel, 1] += destDirection; - this.dmaRegs[channel, 0] += srcDirection; - } - } - - // If not a repeating DMA, then disable the DMA - if ((this.dmaRegs[channel, 3] & (1 << 9)) == 0) - { - this.dmaRegs[channel, 3] &= 0x7FFF; - } - else - { - // Reload dest and count - switch (channel) - { - case 0: - if (reload) this.dmaRegs[0, 1] = Memory.ReadU32(this.ioReg, Memory.DMA0DAD) & 0x07FFFFFF; - this.dmaRegs[0, 2] = Memory.ReadU16(this.ioReg, Memory.DMA0CNT_L); - break; - case 1: - if (reload) this.dmaRegs[1, 1] = Memory.ReadU32(this.ioReg, Memory.DMA1DAD) & 0x07FFFFFF; - this.dmaRegs[1, 2] = Memory.ReadU16(this.ioReg, Memory.DMA1CNT_L); - break; - case 2: - if (reload) this.dmaRegs[2, 1] = Memory.ReadU32(this.ioReg, Memory.DMA2DAD) & 0x07FFFFFF; - this.dmaRegs[2, 2] = Memory.ReadU16(this.ioReg, Memory.DMA2CNT_L); - break; - case 3: - if (reload) this.dmaRegs[3, 1] = Memory.ReadU32(this.ioReg, Memory.DMA3DAD) & 0x0FFFFFFF; - this.dmaRegs[3, 2] = Memory.ReadU16(this.ioReg, Memory.DMA3CNT_L); - break; - } - } - - if ((this.dmaRegs[channel, 3] & (1 << 14)) != 0) - { - this.processor.RequestIrq(8 + channel); - } - } - } - - public void WriteDmaControl(int channel) - { - switch (channel) - { - case 0: - if (((this.dmaRegs[0, 3] ^ Memory.ReadU16(this.ioReg, Memory.DMA0CNT_H)) & (1 << 15)) == 0) return; - this.dmaRegs[0, 0] = Memory.ReadU32(this.ioReg, Memory.DMA0SAD) & 0x07FFFFFF; - this.dmaRegs[0, 1] = Memory.ReadU32(this.ioReg, Memory.DMA0DAD) & 0x07FFFFFF; - this.dmaRegs[0, 2] = Memory.ReadU16(this.ioReg, Memory.DMA0CNT_L); - this.dmaRegs[0, 3] = Memory.ReadU16(this.ioReg, Memory.DMA0CNT_H); - break; - case 1: - if (((this.dmaRegs[1, 3] ^ Memory.ReadU16(this.ioReg, Memory.DMA1CNT_H)) & (1 << 15)) == 0) return; - this.dmaRegs[1, 0] = Memory.ReadU32(this.ioReg, Memory.DMA1SAD) & 0x0FFFFFFF; - this.dmaRegs[1, 1] = Memory.ReadU32(this.ioReg, Memory.DMA1DAD) & 0x07FFFFFF; - this.dmaRegs[1, 2] = Memory.ReadU16(this.ioReg, Memory.DMA1CNT_L); - this.dmaRegs[1, 3] = Memory.ReadU16(this.ioReg, Memory.DMA1CNT_H); - break; - case 2: - if (((this.dmaRegs[2, 3] ^ Memory.ReadU16(this.ioReg, Memory.DMA2CNT_H)) & (1 << 15)) == 0) return; - this.dmaRegs[2, 0] = Memory.ReadU32(this.ioReg, Memory.DMA2SAD) & 0x0FFFFFFF; - this.dmaRegs[2, 1] = Memory.ReadU32(this.ioReg, Memory.DMA2DAD) & 0x07FFFFFF; - this.dmaRegs[2, 2] = Memory.ReadU16(this.ioReg, Memory.DMA2CNT_L); - this.dmaRegs[2, 3] = Memory.ReadU16(this.ioReg, Memory.DMA2CNT_H); - break; - case 3: - if (((this.dmaRegs[3, 3] ^ Memory.ReadU16(this.ioReg, Memory.DMA3CNT_H)) & (1 << 15)) == 0) return; - this.dmaRegs[3, 0] = Memory.ReadU32(this.ioReg, Memory.DMA3SAD) & 0x0FFFFFFF; - this.dmaRegs[3, 1] = Memory.ReadU32(this.ioReg, Memory.DMA3DAD) & 0x0FFFFFFF; - this.dmaRegs[3, 2] = Memory.ReadU16(this.ioReg, Memory.DMA3CNT_L); - this.dmaRegs[3, 3] = Memory.ReadU16(this.ioReg, Memory.DMA3CNT_H); - break; - } - - // Channel start timing - switch ((this.dmaRegs[channel, 3] >> 12) & 0x3) - { - case 0: - // Start immediately - this.DmaTransfer(channel); - break; - case 1: - case 2: - // Hblank and Vblank DMA's - break; - case 3: - // TODO (DMA sound) - return; - } - } - - private void WriteTimerControl(int timer, ushort newCnt) - { - ushort control = Memory.ReadU16(this.ioReg, Memory.TM0CNT + (uint)(timer * 4)); - uint count = Memory.ReadU16(this.ioReg, Memory.TM0D + (uint)(timer * 4)); - - if ((newCnt & (1 << 7)) != 0 && (control & (1 << 7)) == 0) - { - this.timerCnt[timer] = count << 10; - } - } - - #region Read/Write Helpers - public static ushort ReadU16(byte[] array, uint position) - { - return (ushort)(array[position] | (array[position + 1] << 8)); - } - - public static uint ReadU32(byte[] array, uint position) - { - return (uint)(array[position] | (array[position + 1] << 8) | - (array[position + 2] << 16) | (array[position + 3] << 24)); - } - - public static void WriteU16(byte[] array, uint position, ushort value) - { - array[position] = (byte)(value & 0xff); - array[position + 1] = (byte)(value >> 8); - } - - public static void WriteU32(byte[] array, uint position, uint value) - { - array[position] = (byte)(value & 0xff); - array[position + 1] = (byte)((value >> 8) & 0xff); - array[position + 2] = (byte)((value >> 16) & 0xff); - array[position + 3] = (byte)(value >> 24); - } - #endregion - - #region Memory Reads - private uint ReadUnreadable() - { - if (this.inUnreadable) - { - return 0; - } - - this.inUnreadable = true; - - uint res; - - if (this.processor.ArmState) - { - res = this.ReadU32(this.processor.Registers[15]); - } - else - { - ushort val = this.ReadU16(this.processor.Registers[15]); - res = (uint)(val | (val << 16)); - } - - this.inUnreadable = false; - - return res; - } - - private byte ReadNop8(uint address) - { - return (byte)(this.ReadUnreadable() & 0xFF); - } - - private ushort ReadNop16(uint address) - { - return (ushort)(this.ReadUnreadable() & 0xFFFF); - } - - private uint ReadNop32(uint address) - { - return this.ReadUnreadable(); - } - - private byte ReadBiosRam8(uint address) - { - this.waitCycles++; - if (this.processor.Registers[15] < 0x01000000) - { - return this.biosRam[address & Memory.biosRamMask]; - } - return (byte)(this.ReadUnreadable() & 0xFF); - } - - private ushort ReadBiosRam16(uint address) - { - this.waitCycles++; - if (this.processor.Registers[15] < 0x01000000) - { - return Memory.ReadU16(this.biosRam, address & Memory.biosRamMask); - } - return (ushort)(this.ReadUnreadable() & 0xFFFF); - } - - private uint ReadBiosRam32(uint address) - { - this.waitCycles++; - if (this.processor.Registers[15] < 0x01000000) - { - return Memory.ReadU32(this.biosRam, address & Memory.biosRamMask); - } - return this.ReadUnreadable(); - } - - private byte ReadEwRam8(uint address) - { - this.waitCycles += 3; - return this.ewRam[address & Memory.ewRamMask]; - } - - private ushort ReadEwRam16(uint address) - { - this.waitCycles += 3; - return Memory.ReadU16(this.ewRam, address & Memory.ewRamMask); - } - - private uint ReadEwRam32(uint address) - { - this.waitCycles += 6; - return Memory.ReadU32(this.ewRam, address & Memory.ewRamMask); - } - - private byte ReadIwRam8(uint address) - { - this.waitCycles++; - return this.iwRam[address & Memory.iwRamMask]; - } - - private ushort ReadIwRam16(uint address) - { - this.waitCycles++; - return Memory.ReadU16(this.iwRam, address & Memory.iwRamMask); - } - - private uint ReadIwRam32(uint address) - { - this.waitCycles++; - return Memory.ReadU32(this.iwRam, address & Memory.iwRamMask); - } - - private byte ReadIO8(uint address) - { - this.waitCycles++; - address &= 0xFFFFFF; - if (address >= Memory.ioRegMask) return 0; - - switch (address) - { - case KEYINPUT: - return (byte)(this.keyState & 0xFF); - case KEYINPUT + 1: - return (byte)(this.keyState >> 8); - - case DMA0CNT_H: - return (byte)(this.dmaRegs[0, 3] & 0xFF); - case DMA0CNT_H + 1: - return (byte)(this.dmaRegs[0, 3] >> 8); - case DMA1CNT_H: - return (byte)(this.dmaRegs[1, 3] & 0xFF); - case DMA1CNT_H + 1: - return (byte)(this.dmaRegs[1, 3] >> 8); - case DMA2CNT_H: - return (byte)(this.dmaRegs[2, 3] & 0xFF); - case DMA2CNT_H + 1: - return (byte)(this.dmaRegs[2, 3] >> 8); - case DMA3CNT_H: - return (byte)(this.dmaRegs[3, 3] & 0xFF); - case DMA3CNT_H + 1: - return (byte)(this.dmaRegs[3, 3] >> 8); - - case TM0D: - this.processor.UpdateTimers(); - return (byte)((this.timerCnt[0] >> 10) & 0xFF); - case TM0D + 1: - this.processor.UpdateTimers(); - return (byte)((this.timerCnt[0] >> 10) >> 8); - case TM1D: - this.processor.UpdateTimers(); - return (byte)((this.timerCnt[1] >> 10) & 0xFF); - case TM1D + 1: - this.processor.UpdateTimers(); - return (byte)((this.timerCnt[1] >> 10) >> 8); - case TM2D: - this.processor.UpdateTimers(); - return (byte)((this.timerCnt[2] >> 10) & 0xFF); - case TM2D + 1: - this.processor.UpdateTimers(); - return (byte)((this.timerCnt[2] >> 10) >> 8); - case TM3D: - this.processor.UpdateTimers(); - return (byte)((this.timerCnt[3] >> 10) & 0xFF); - case TM3D + 1: - this.processor.UpdateTimers(); - return (byte)((this.timerCnt[3] >> 10) >> 8); - - default: - return this.ioReg[address]; - } - } - - private ushort ReadIO16(uint address) - { - this.waitCycles++; - address &= 0xFFFFFF; - if (address >= Memory.ioRegMask) return 0; - - switch (address) - { - case KEYINPUT: - return this.keyState; - - case DMA0CNT_H: - return (ushort)this.dmaRegs[0, 3]; - case DMA1CNT_H: - return (ushort)this.dmaRegs[1, 3]; - case DMA2CNT_H: - return (ushort)this.dmaRegs[2, 3]; - case DMA3CNT_H: - return (ushort)this.dmaRegs[3, 3]; - - case TM0D: - this.processor.UpdateTimers(); - return (ushort)((this.timerCnt[0] >> 10) & 0xFFFF); - case TM1D: - this.processor.UpdateTimers(); - return (ushort)((this.timerCnt[1] >> 10) & 0xFFFF); - case TM2D: - this.processor.UpdateTimers(); - return (ushort)((this.timerCnt[2] >> 10) & 0xFFFF); - case TM3D: - this.processor.UpdateTimers(); - return (ushort)((this.timerCnt[3] >> 10) & 0xFFFF); - - default: - return Memory.ReadU16(this.ioReg, address); - } - } - - private uint ReadIO32(uint address) - { - this.waitCycles++; - address &= 0xFFFFFF; - if (address >= Memory.ioRegMask) return 0; - - switch (address) - { - case KEYINPUT: - return this.keyState | ((uint)Memory.ReadU16(this.ioReg, address + 0x2) << 16); - - case DMA0CNT_L: - return (uint)Memory.ReadU16(this.ioReg, address) | (this.dmaRegs[0, 3] << 16); - case DMA1CNT_L: - return (uint)Memory.ReadU16(this.ioReg, address) | (this.dmaRegs[1, 3] << 16); - case DMA2CNT_L: - return (uint)Memory.ReadU16(this.ioReg, address) | (this.dmaRegs[2, 3] << 16); - case DMA3CNT_L: - return (uint)Memory.ReadU16(this.ioReg, address) | (this.dmaRegs[3, 3] << 16); - - case TM0D: - this.processor.UpdateTimers(); - return (uint)(((this.timerCnt[0] >> 10) & 0xFFFF) | (uint)(Memory.ReadU16(this.ioReg, address + 2) << 16)); - case TM1D: - this.processor.UpdateTimers(); - return (uint)(((this.timerCnt[1] >> 10) & 0xFFFF) | (uint)(Memory.ReadU16(this.ioReg, address + 2) << 16)); - case TM2D: - this.processor.UpdateTimers(); - return (uint)(((this.timerCnt[2] >> 10) & 0xFFFF) | (uint)(Memory.ReadU16(this.ioReg, address + 2) << 16)); - case TM3D: - this.processor.UpdateTimers(); - return (uint)(((this.timerCnt[3] >> 10) & 0xFFFF) | (uint)(Memory.ReadU16(this.ioReg, address + 2) << 16)); - - default: - return Memory.ReadU32(this.ioReg, address); - } - } - - private byte ReadPalRam8(uint address) - { - this.waitCycles++; - return this.palRam[address & Memory.palRamMask]; - } - - private ushort ReadPalRam16(uint address) - { - this.waitCycles++; - return Memory.ReadU16(this.palRam, address & Memory.palRamMask); - } - - private uint ReadPalRam32(uint address) - { - this.waitCycles += 2; - return Memory.ReadU32(this.palRam, address & Memory.palRamMask); - } - - private byte ReadVRam8(uint address) - { - this.waitCycles++; - address &= Memory.vRamMask; - if (address > 0x17FFF) address = 0x10000 + ((address - 0x17FFF) & 0x7FFF); - return this.vRam[address]; - } - - private ushort ReadVRam16(uint address) - { - this.waitCycles++; - address &= Memory.vRamMask; - if (address > 0x17FFF) address = 0x10000 + ((address - 0x17FFF) & 0x7FFF); - return Memory.ReadU16(this.vRam, address); - } - - private uint ReadVRam32(uint address) - { - this.waitCycles += 2; - address &= Memory.vRamMask; - if (address > 0x17FFF) address = 0x10000 + ((address - 0x17FFF) & 0x7FFF); - return Memory.ReadU32(this.vRam, address & Memory.vRamMask); - } - - private byte ReadOamRam8(uint address) - { - this.waitCycles++; - return this.oamRam[address & Memory.oamRamMask]; - } - - private ushort ReadOamRam16(uint address) - { - this.waitCycles++; - return Memory.ReadU16(this.oamRam, address & Memory.oamRamMask); - } - - private uint ReadOamRam32(uint address) - { - this.waitCycles++; - return Memory.ReadU32(this.oamRam, address & Memory.oamRamMask); - } - - private byte ReadRom1_8(uint address) - { - this.waitCycles += this.bankSTimes[(address >> 24) & 0xf]; - return this.romBank1[address & this.romBank1Mask]; - } - - private ushort ReadRom1_16(uint address) - { - this.waitCycles += this.bankSTimes[(address >> 24) & 0xf]; - return Memory.ReadU16(this.romBank1, address & this.romBank1Mask); - } - - private uint ReadRom1_32(uint address) - { - this.waitCycles += this.bankSTimes[(address >> 24) & 0xf] * 2 + 1; - return Memory.ReadU32(this.romBank1, address & this.romBank1Mask); - } - - private byte ReadRom2_8(uint address) - { - this.waitCycles += this.bankSTimes[(address >> 24) & 0xf]; - return this.romBank2[address & this.romBank2Mask]; - } - - private ushort ReadRom2_16(uint address) - { - this.waitCycles += this.bankSTimes[(address >> 24) & 0xf]; - return Memory.ReadU16(this.romBank2, address & this.romBank2Mask); - } - - private uint ReadRom2_32(uint address) - { - this.waitCycles += this.bankSTimes[(address >> 24) & 0xf] * 2 + 1; - return Memory.ReadU32(this.romBank2, address & this.romBank2Mask); - } - - private byte ReadSRam8(uint address) - { - return this.sRam[address & Memory.sRamMask]; - } - - private ushort ReadSRam16(uint address) - { - // TODO - return 0; - } - - private uint ReadSRam32(uint address) - { - // TODO - return 0; - } - #endregion - - #region Memory Writes - private void WriteNop8(uint address, byte value) - { - } - - private void WriteNop16(uint address, ushort value) - { - } - - private void WriteNop32(uint address, uint value) - { - } - - private void WriteEwRam8(uint address, byte value) - { - this.waitCycles += 3; - this.ewRam[address & Memory.ewRamMask] = value; - } - - private void WriteEwRam16(uint address, ushort value) - { - this.waitCycles += 3; - Memory.WriteU16(this.ewRam, address & Memory.ewRamMask, value); - } - - private void WriteEwRam32(uint address, uint value) - { - this.waitCycles += 6; - Memory.WriteU32(this.ewRam, address & Memory.ewRamMask, value); - } - - private void WriteIwRam8(uint address, byte value) - { - this.waitCycles++; - this.iwRam[address & Memory.iwRamMask] = value; - } - - private void WriteIwRam16(uint address, ushort value) - { - this.waitCycles++; - Memory.WriteU16(this.iwRam, address & Memory.iwRamMask, value); - } - - private void WriteIwRam32(uint address, uint value) - { - this.waitCycles++; - Memory.WriteU32(this.iwRam, address & Memory.iwRamMask, value); - } - - private void WriteIO8(uint address, byte value) - { - this.waitCycles++; - address &= 0xFFFFFF; - if (address >= Memory.ioRegMask) return; - - switch (address) - { - case BG2X_L: - case BG2X_L + 1: - case BG2X_L + 2: - case BG2X_L + 3: - { - this.ioReg[address] = value; - uint tmp = Memory.ReadU32(this.ioReg, BG2X_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG2X_L, tmp); - - this.bgx[0] = (int)tmp; - } - break; - - case BG3X_L: - case BG3X_L + 1: - case BG3X_L + 2: - case BG3X_L + 3: - { - this.ioReg[address] = value; - uint tmp = Memory.ReadU32(this.ioReg, BG3X_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG3X_L, tmp); - - this.bgx[1] = (int)tmp; - } - break; - - case BG2Y_L: - case BG2Y_L + 1: - case BG2Y_L + 2: - case BG2Y_L + 3: - { - this.ioReg[address] = value; - uint tmp = Memory.ReadU32(this.ioReg, BG2Y_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG2Y_L, tmp); - - this.bgy[0] = (int)tmp; - } - break; - - case BG3Y_L: - case BG3Y_L + 1: - case BG3Y_L + 2: - case BG3Y_L + 3: - { - this.ioReg[address] = value; - uint tmp = Memory.ReadU32(this.ioReg, BG3Y_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG3Y_L, tmp); - - this.bgy[1] = (int)tmp; - } - break; - - case DMA0CNT_H: - case DMA0CNT_H + 1: - this.ioReg[address] = value; - this.WriteDmaControl(0); - break; - - case DMA1CNT_H: - case DMA1CNT_H + 1: - this.ioReg[address] = value; - this.WriteDmaControl(1); - break; - - case DMA2CNT_H: - case DMA2CNT_H + 1: - this.ioReg[address] = value; - this.WriteDmaControl(2); - break; - - case DMA3CNT_H: - case DMA3CNT_H + 1: - this.ioReg[address] = value; - this.WriteDmaControl(3); - break; - - case TM0CNT: - case TM0CNT + 1: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM0CNT); - this.ioReg[address] = value; - this.WriteTimerControl(0, oldCnt); - } - break; - - case TM1CNT: - case TM1CNT + 1: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM1CNT); - this.ioReg[address] = value; - this.WriteTimerControl(1, oldCnt); - } - break; - - case TM2CNT: - case TM2CNT + 1: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM2CNT); - this.ioReg[address] = value; - this.WriteTimerControl(2, oldCnt); - } - break; - - case TM3CNT: - case TM3CNT + 1: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM3CNT); - this.ioReg[address] = value; - this.WriteTimerControl(3, oldCnt); - } - break; - - case FIFO_A_L: - case FIFO_A_L+1: - case FIFO_A_H: - case FIFO_A_H+1: - this.ioReg[address] = value; - this.soundManager.IncrementFifoA(); - break; - - case FIFO_B_L: - case FIFO_B_L + 1: - case FIFO_B_H: - case FIFO_B_H + 1: - this.ioReg[address] = value; - this.soundManager.IncrementFifoB(); - break; - - case IF: - case IF + 1: - this.ioReg[address] &= (byte)~value; - break; - - case HALTCNT + 1: - this.ioReg[address] = value; - this.processor.Halt(); - break; - - default: - this.ioReg[address] = value; - break; - } - } - - private void WriteIO16(uint address, ushort value) - { - this.waitCycles++; - address &= 0xFFFFFF; - if (address >= Memory.ioRegMask) return; - - switch (address) - { - case BG2X_L: - case BG2X_L + 2: - { - Memory.WriteU16(this.ioReg, address, value); - uint tmp = Memory.ReadU32(this.ioReg, BG2X_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG2X_L, tmp); - - this.bgx[0] = (int)tmp; - } - break; - - case BG3X_L: - case BG3X_L + 2: - { - Memory.WriteU16(this.ioReg, address, value); - uint tmp = Memory.ReadU32(this.ioReg, BG3X_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG3X_L, tmp); - - this.bgx[1] = (int)tmp; - } - break; - - case BG2Y_L: - case BG2Y_L + 2: - { - Memory.WriteU16(this.ioReg, address, value); - uint tmp = Memory.ReadU32(this.ioReg, BG2Y_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG2Y_L, tmp); - - this.bgy[0] = (int)tmp; - } - break; - - case BG3Y_L: - case BG3Y_L + 2: - { - Memory.WriteU16(this.ioReg, address, value); - uint tmp = Memory.ReadU32(this.ioReg, BG3Y_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG3Y_L, tmp); - - this.bgy[1] = (int)tmp; - } - break; - - case DMA0CNT_H: - Memory.WriteU16(this.ioReg, address, value); - this.WriteDmaControl(0); - break; - - case DMA1CNT_H: - Memory.WriteU16(this.ioReg, address, value); - this.WriteDmaControl(1); - break; - - case DMA2CNT_H: - Memory.WriteU16(this.ioReg, address, value); - this.WriteDmaControl(2); - break; - - case DMA3CNT_H: - Memory.WriteU16(this.ioReg, address, value); - this.WriteDmaControl(3); - break; - - case TM0CNT: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM0CNT); - Memory.WriteU16(this.ioReg, address, value); - this.WriteTimerControl(0, oldCnt); - } - break; - - case TM1CNT: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM1CNT); - Memory.WriteU16(this.ioReg, address, value); - this.WriteTimerControl(1, oldCnt); - } - break; - - case TM2CNT: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM2CNT); - Memory.WriteU16(this.ioReg, address, value); - this.WriteTimerControl(2, oldCnt); - } - break; - - case TM3CNT: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM3CNT); - Memory.WriteU16(this.ioReg, address, value); - this.WriteTimerControl(3, oldCnt); - } - break; - - case FIFO_A_L: - case FIFO_A_H: - Memory.WriteU16(this.ioReg, address, value); - this.soundManager.IncrementFifoA(); - break; - - case FIFO_B_L: - case FIFO_B_H: - Memory.WriteU16(this.ioReg, address, value); - this.soundManager.IncrementFifoB(); - break; - - case SOUNDCNT_H: - Memory.WriteU16(this.ioReg, address, value); - if ((value & (1 << 11)) != 0) - { - this.soundManager.ResetFifoA(); - } - if ((value & (1 << 15)) != 0) - { - this.soundManager.ResetFifoB(); - } - break; - - case IF: - { - ushort tmp = Memory.ReadU16(this.ioReg, address); - Memory.WriteU16(this.ioReg, address, (ushort)(tmp & (~value))); - } - break; - - case HALTCNT: - Memory.WriteU16(this.ioReg, address, value); - this.processor.Halt(); - break; - - default: - Memory.WriteU16(this.ioReg, address, value); - break; - } - } - - private void WriteIO32(uint address, uint value) - { - this.waitCycles++; - address &= 0xFFFFFF; - if (address >= Memory.ioRegMask) return; - - switch (address) - { - case BG2X_L: - { - Memory.WriteU32(this.ioReg, address, value); - uint tmp = Memory.ReadU32(this.ioReg, BG2X_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG2X_L, tmp); - - this.bgx[0] = (int)tmp; - } - break; - - case BG3X_L: - { - Memory.WriteU32(this.ioReg, address, value); - uint tmp = Memory.ReadU32(this.ioReg, BG3X_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG3X_L, tmp); - - this.bgx[1] = (int)tmp; - } - break; - - case BG2Y_L: - { - Memory.WriteU32(this.ioReg, address, value); - uint tmp = Memory.ReadU32(this.ioReg, BG2Y_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG2Y_L, tmp); - - this.bgy[0] = (int)tmp; - } - break; - - case BG3Y_L: - { - Memory.WriteU32(this.ioReg, address, value); - uint tmp = Memory.ReadU32(this.ioReg, BG3Y_L); - if ((tmp & (1 << 27)) != 0) tmp |= 0xF0000000; - Memory.WriteU32(this.ioReg, BG3Y_L, tmp); - - this.bgy[1] = (int)tmp; - } - break; - - case DMA0CNT_L: - Memory.WriteU32(this.ioReg, address, value); - this.WriteDmaControl(0); - break; - - case DMA1CNT_L: - Memory.WriteU32(this.ioReg, address, value); - this.WriteDmaControl(1); - break; - - case DMA2CNT_L: - Memory.WriteU32(this.ioReg, address, value); - this.WriteDmaControl(2); - break; - - case DMA3CNT_L: - Memory.WriteU32(this.ioReg, address, value); - this.WriteDmaControl(3); - break; - - case TM0D: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM0CNT); - Memory.WriteU32(this.ioReg, address, value); - this.WriteTimerControl(0, oldCnt); - } - break; - - case TM1D: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM1CNT); - Memory.WriteU32(this.ioReg, address, value); - this.WriteTimerControl(1, oldCnt); - } - break; - - case TM2D: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM2CNT); - Memory.WriteU32(this.ioReg, address, value); - this.WriteTimerControl(2, oldCnt); - } - break; - - case TM3D: - { - ushort oldCnt = Memory.ReadU16(this.ioReg, TM3CNT); - Memory.WriteU32(this.ioReg, address, value); - this.WriteTimerControl(3, oldCnt); - } - break; - - case FIFO_A_L: - Memory.WriteU32(this.ioReg, address, value); - this.soundManager.IncrementFifoA(); - break; - - case FIFO_B_L: - Memory.WriteU32(this.ioReg, address, value); - this.soundManager.IncrementFifoB(); - break; - - case SOUNDCNT_L: - Memory.WriteU32(this.ioReg, address, value); - if (((value >> 16) & (1 << 11)) != 0) - { - this.soundManager.ResetFifoA(); - } - if (((value >> 16) & (1 << 15)) != 0) - { - this.soundManager.ResetFifoB(); - } - break; - - case IE: - { - uint tmp = Memory.ReadU32(this.ioReg, address); - Memory.WriteU32(this.ioReg, address, (uint)((value & 0xFFFF) | (tmp & (~(value & 0xFFFF0000))))); - } - break; - - case HALTCNT: - Memory.WriteU32(this.ioReg, address, value); - this.processor.Halt(); - break; - - default: - Memory.WriteU32(this.ioReg, address, value); - break; - } - } - - private void WritePalRam8(uint address, byte value) - { - this.waitCycles++; - address &= Memory.palRamMask & ~1U; - this.palRam[address] = value; - this.palRam[address + 1] = value; - } - - private void WritePalRam16(uint address, ushort value) - { - this.waitCycles++; - Memory.WriteU16(this.palRam, address & Memory.palRamMask, value); - } - - private void WritePalRam32(uint address, uint value) - { - this.waitCycles += 2; - Memory.WriteU32(this.palRam, address & Memory.palRamMask, value); - } - - private void WriteVRam8(uint address, byte value) - { - this.waitCycles++; - address &= Memory.vRamMask & ~1U; - if (address > 0x17FFF) address = 0x10000 + ((address - 0x17FFF) & 0x7FFF); - this.vRam[address] = value; - this.vRam[address + 1] = value; - } - - private void WriteVRam16(uint address, ushort value) - { - this.waitCycles++; - address &= Memory.vRamMask; - if (address > 0x17FFF) address = 0x10000 + ((address - 0x17FFF) & 0x7FFF); - Memory.WriteU16(this.vRam, address, value); - } - - private void WriteVRam32(uint address, uint value) - { - this.waitCycles += 2; - address &= Memory.vRamMask; - if (address > 0x17FFF) address = 0x10000 + ((address - 0x17FFF) & 0x7FFF); - Memory.WriteU32(this.vRam, address, value); - } - - private void WriteOamRam8(uint address, byte value) - { - this.waitCycles++; - address &= Memory.oamRamMask & ~1U; - - this.oamRam[address] = value; - this.oamRam[address + 1] = value; - } - - private void WriteOamRam16(uint address, ushort value) - { - this.waitCycles++; - Memory.WriteU16(this.oamRam, address & Memory.oamRamMask, value); - } - - private void WriteOamRam32(uint address, uint value) - { - this.waitCycles++; - Memory.WriteU32(this.oamRam, address & Memory.oamRamMask, value); - } - - private void WriteSRam8(uint address, byte value) - { - this.sRam[address & Memory.sRamMask] = value; - } - - private void WriteSRam16(uint address, ushort value) - { - // TODO - } - - private void WriteSRam32(uint address, uint value) - { - // TODO - } - - private enum EepromModes - { - Idle, - ReadData - } - - private EepromModes eepromMode = EepromModes.Idle; - private byte[] eeprom = new byte[0xffff]; - private byte[] eepromStore = new byte[0xff]; - private int curEepromByte; - private int eepromReadAddress = -1; - - private void WriteEeprom8(uint address, byte value) - { - // EEPROM writes must be done by DMA 3 - if ((this.dmaRegs[3, 3] & (1 << 15)) == 0) return; - // 0 length eeprom writes are bad - if (this.dmaRegs[3, 2] == 0) return; - - if (this.eepromMode != EepromModes.ReadData) - { - this.curEepromByte = 0; - this.eepromMode = EepromModes.ReadData; - this.eepromReadAddress = -1; - - for (int i = 0; i < this.eepromStore.Length; i++) this.eepromStore[i] = 0; - } - - this.eepromStore[this.curEepromByte >> 3] |= (byte)(value << (7 - (this.curEepromByte & 0x7))); - this.curEepromByte++; - - if (this.curEepromByte == this.dmaRegs[3, 2]) - { - if ((this.eepromStore[0] & 0x80) == 0) return; - - if ((this.eepromStore[0] & 0x40) != 0) - { - // Read request - if (this.curEepromByte == 9) - { - this.eepromReadAddress = this.eepromStore[0] & 0x3F; - } - else - { - this.eepromReadAddress = ((this.eepromStore[0] & 0x3F) << 8) | this.eepromStore[1]; - } - - this.curEepromByte = 0; - } - else - { - // Write request - int eepromAddress, offset; - if (this.curEepromByte == 64 + 9) - { - eepromAddress = (int)(this.eepromStore[0] & 0x3F); - offset = 1; - } - else - { - eepromAddress = ((this.eepromStore[0] & 0x3F) << 8) | this.eepromStore[1]; - offset = 2; - } - - for (int i = 0; i < 8; i++) - { - this.eeprom[eepromAddress * 8 + i] = this.eepromStore[i + offset]; - } - - this.eepromMode = EepromModes.Idle; - } - } - } - - private void WriteEeprom16(uint address, ushort value) - { - this.WriteEeprom8(address, (byte)(value & 0xff)); - } - - private void WriteEeprom32(uint address, uint value) - { - this.WriteEeprom8(address, (byte)(value & 0xff)); - } - - private byte ReadEeprom8(uint address) - { - if (this.eepromReadAddress == -1) return 1; - - byte retval = 0; - - if (this.curEepromByte >= 4) - { - retval = (byte)((this.eeprom[this.eepromReadAddress * 8 + ((this.curEepromByte - 4) / 8)] >> (7 - ((this.curEepromByte - 4) & 7))) & 1); - } - - this.curEepromByte++; - - if (this.curEepromByte == this.dmaRegs[3, 2]) - { - this.eepromReadAddress = -1; - this.eepromMode = EepromModes.Idle; - } - - return retval; - } - - private ushort ReadEeprom16(uint address) - { - return (ushort)this.ReadEeprom8(address); - } - - private uint ReadEeprom32(uint address) - { - return (uint)this.ReadEeprom8(address); - } - #endregion - - #region Shader Renderer Vram Writes - private List vramUpdated = new List(); - private List palUpdated = new List(); - public const int VramBlockSize = 64; - public const int PalBlockSize = 32; - private bool[] vramHit = new bool[(Memory.vRamMask + 1) / VramBlockSize]; - private bool[] palHit = new bool[(Memory.palRamMask + 1) / PalBlockSize]; - - public List VramUpdated - { - get - { - List old = this.vramUpdated; - for (int i = 0; i < old.Count; i++) - { - vramHit[old[i]] = false; - } - this.vramUpdated = new List(); - return old; - } - } - - - public List PalUpdated - { - get - { - List old = this.palUpdated; - for (int i = 0; i < old.Count; i++) - { - palHit[old[i]] = false; - } - this.palUpdated = new List(); - return old; - } - } - - private void UpdatePal(uint address) - { - uint index = address / PalBlockSize; - if (!palHit[index]) - { - palHit[index] = true; - this.palUpdated.Add(index); - } - } - - private void UpdateVram(uint address) - { - uint index = address / VramBlockSize; - if (!vramHit[index]) - { - vramHit[index] = true; - this.vramUpdated.Add(index); - } - } - - private void ShaderWritePalRam8(uint address, byte value) - { - this.waitCycles++; - address &= Memory.palRamMask & ~1U; - this.palRam[address] = value; - this.palRam[address + 1] = value; - - this.UpdatePal(address); - } - - private void ShaderWritePalRam16(uint address, ushort value) - { - this.waitCycles++; - Memory.WriteU16(this.palRam, address & Memory.palRamMask, value); - - this.UpdatePal(address & Memory.palRamMask); - } - - private void ShaderWritePalRam32(uint address, uint value) - { - this.waitCycles += 2; - Memory.WriteU32(this.palRam, address & Memory.palRamMask, value); - - this.UpdatePal(address & Memory.palRamMask); - } - - private void ShaderWriteVRam8(uint address, byte value) - { - this.waitCycles++; - address &= Memory.vRamMask & ~1U; - if (address > 0x17FFF) address = 0x10000 + ((address - 0x17FFF) & 0x7FFF); - this.vRam[address] = value; - this.vRam[address + 1] = value; - - this.UpdateVram(address); - } - - private void ShaderWriteVRam16(uint address, ushort value) - { - this.waitCycles++; - address &= Memory.vRamMask; - if (address > 0x17FFF) address = 0x10000 + ((address - 0x17FFF) & 0x7FFF); - Memory.WriteU16(this.vRam, address, value); - - this.UpdateVram(address); - } - - private void ShaderWriteVRam32(uint address, uint value) - { - this.waitCycles += 2; - address &= Memory.vRamMask; - if (address > 0x17FFF) address = 0x10000 + ((address - 0x17FFF) & 0x7FFF); - Memory.WriteU32(this.vRam, address, value); - - this.UpdateVram(address); - } - - public void EnableVramUpdating() - { - this.WriteU8Funcs[0x5] = this.ShaderWritePalRam8; - this.WriteU16Funcs[0x5] = this.ShaderWritePalRam16; - this.WriteU32Funcs[0x5] = this.ShaderWritePalRam32; - this.WriteU8Funcs[0x6] = this.ShaderWriteVRam8; - this.WriteU16Funcs[0x6] = this.ShaderWriteVRam16; - this.WriteU32Funcs[0x6] = this.ShaderWriteVRam32; - - for (uint i = 0; i < (Memory.vRamMask + 1) / Memory.VramBlockSize; i++) - { - this.vramUpdated.Add(i); - } - - for (uint i = 0; i < (Memory.palRamMask + 1) / Memory.PalBlockSize; i++) - { - this.palUpdated.Add(i); - } - } - #endregion - - public byte ReadU8(uint address) - { - uint bank = (address >> 24) & 0xf; - return this.ReadU8Funcs[bank](address); - } - - public ushort ReadU16(uint address) - { - address &= ~1U; - uint bank = (address >> 24) & 0xf; - return this.ReadU16Funcs[bank](address); - } - - public uint ReadU32(uint address) - { - int shiftAmt = (int)((address & 3U) << 3); - address &= ~3U; - uint bank = (address >> 24) & 0xf; - uint res = this.ReadU32Funcs[bank](address); - return (res >> shiftAmt) | (res << (32 - shiftAmt)); - } - - public uint ReadU32Aligned(uint address) - { - uint bank = (address >> 24) & 0xf; - return this.ReadU32Funcs[bank](address); - } - - public ushort ReadU16Debug(uint address) - { - address &= ~1U; - uint bank = (address >> 24) & 0xf; - int oldWaitCycles = this.waitCycles; - ushort res = this.ReadU16Funcs[bank](address); - this.waitCycles = oldWaitCycles; - return res; - } - - public uint ReadU32Debug(uint address) - { - int shiftAmt = (int)((address & 3U) << 3); - address &= ~3U; - uint bank = (address >> 24) & 0xf; - int oldWaitCycles = this.waitCycles; - uint res = this.ReadU32Funcs[bank](address); - this.waitCycles = oldWaitCycles; - return (res >> shiftAmt) | (res << (32 - shiftAmt)); - } - - public void WriteU8(uint address, byte value) - { - uint bank = (address >> 24) & 0xf; - this.WriteU8Funcs[bank](address, value); - } - - public void WriteU16(uint address, ushort value) - { - address &= ~1U; - uint bank = (address >> 24) & 0xf; - this.WriteU16Funcs[bank](address, value); - } - - public void WriteU32(uint address, uint value) - { - address &= ~3U; - uint bank = (address >> 24) & 0xf; - this.WriteU32Funcs[bank](address, value); - } - - public void WriteU8Debug(uint address, byte value) - { - uint bank = (address >> 24) & 0xf; - int oldWaitCycles = this.waitCycles; - this.WriteU8Funcs[bank](address, value); - this.waitCycles = oldWaitCycles; - } - - public void WriteU16Debug(uint address, ushort value) - { - address &= ~1U; - uint bank = (address >> 24) & 0xf; - int oldWaitCycles = this.waitCycles; - this.WriteU16Funcs[bank](address, value); - this.waitCycles = oldWaitCycles; - } - - public void WriteU32Debug(uint address, uint value) - { - address &= ~3U; - uint bank = (address >> 24) & 0xf; - int oldWaitCycles = this.waitCycles; - this.WriteU32Funcs[bank](address, value); - this.waitCycles = oldWaitCycles; - } - - public void LoadBios(byte[] biosRom) - { - Array.Copy(biosRom, this.biosRam, this.biosRam.Length); - } - - public void LoadCartridge(byte[] cartRom) - { - this.ResetRomBank1(); - this.ResetRomBank2(); - - // Set up the appropriate cart size - int cartSize = 1; - while (cartSize < cartRom.Length) - { - cartSize <<= 1; - } - - if (cartSize != cartRom.Length) - { - throw new Exception("Unable to load non power of two carts"); - } - - // Split across bank 1 and 2 if cart is too big - if (cartSize > 1 << 24) - { - this.romBank1 = cartRom; - this.romBank1Mask = (1 << 24) - 1; - - cartRom.CopyTo(this.romBank2, 1 << 24); - this.romBank2Mask = (1 << 24) - 1; - } - else - { - this.romBank1 = cartRom; - this.romBank1Mask = (uint)(cartSize - 1); - } - - if (this.romBank1Mask != 0) - { - // TODO: Writes (i.e. eeprom, and other stuff) - this.ReadU8Funcs[0x8] = this.ReadRom1_8; - this.ReadU8Funcs[0xA] = this.ReadRom1_8; - this.ReadU8Funcs[0xC] = this.ReadRom1_8; - this.ReadU16Funcs[0x8] = this.ReadRom1_16; - this.ReadU16Funcs[0xA] = this.ReadRom1_16; - this.ReadU16Funcs[0xC] = this.ReadRom1_16; - this.ReadU32Funcs[0x8] = this.ReadRom1_32; - this.ReadU32Funcs[0xA] = this.ReadRom1_32; - this.ReadU32Funcs[0xC] = this.ReadRom1_32; - } - - if (this.romBank2Mask != 0) - { - this.ReadU8Funcs[0x9] = this.ReadRom2_8; - this.ReadU8Funcs[0xB] = this.ReadRom2_8; - this.ReadU8Funcs[0xD] = this.ReadRom2_8; - this.ReadU16Funcs[0x9] = this.ReadRom2_16; - this.ReadU16Funcs[0xB] = this.ReadRom2_16; - this.ReadU16Funcs[0xD] = this.ReadRom2_16; - this.ReadU32Funcs[0x9] = this.ReadRom2_32; - this.ReadU32Funcs[0xB] = this.ReadRom2_32; - this.ReadU32Funcs[0xD] = this.ReadRom2_32; - } - } - - private void ResetRomBank1() - { - this.romBank1 = null; - this.romBank1Mask = 0; - - for (int i = 0; i < this.bankSTimes.Length; i++) - { - this.bankSTimes[i] = 2; - } - - this.ReadU8Funcs[0x8] = this.ReadNop8; - this.ReadU8Funcs[0xA] = this.ReadNop8; - this.ReadU8Funcs[0xC] = this.ReadNop8; - this.ReadU16Funcs[0x8] = this.ReadNop16; - this.ReadU16Funcs[0xA] = this.ReadNop16; - this.ReadU16Funcs[0xC] = this.ReadNop16; - this.ReadU32Funcs[0x8] = this.ReadNop32; - this.ReadU32Funcs[0xA] = this.ReadNop32; - this.ReadU32Funcs[0xC] = this.ReadNop32; - } - - private void ResetRomBank2() - { - this.romBank2 = null; - this.romBank2Mask = 0; - - this.ReadU8Funcs[0x9] = this.ReadEeprom8; - this.ReadU8Funcs[0xB] = this.ReadEeprom8; - this.ReadU8Funcs[0xD] = this.ReadEeprom8; - this.ReadU16Funcs[0x9] = this.ReadEeprom16; - this.ReadU16Funcs[0xB] = this.ReadEeprom16; - this.ReadU16Funcs[0xD] = this.ReadEeprom16; - this.ReadU32Funcs[0x9] = this.ReadEeprom32; - this.ReadU32Funcs[0xB] = this.ReadEeprom32; - this.ReadU32Funcs[0xD] = this.ReadEeprom32; - - this.WriteU8Funcs[0x9] = this.WriteEeprom8; - this.WriteU8Funcs[0xB] = this.WriteEeprom8; - this.WriteU8Funcs[0xD] = this.WriteEeprom8; - this.WriteU16Funcs[0x9] = this.WriteEeprom16; - this.WriteU16Funcs[0xB] = this.WriteEeprom16; - this.WriteU16Funcs[0xD] = this.WriteEeprom16; - this.WriteU32Funcs[0x9] = this.WriteEeprom32; - this.WriteU32Funcs[0xB] = this.WriteEeprom32; - this.WriteU32Funcs[0xD] = this.WriteEeprom32; - } - } -} diff --git a/attic/GarboDev/Renderer.cs b/attic/GarboDev/Renderer.cs deleted file mode 100644 index 4e7b7301ee..0000000000 --- a/attic/GarboDev/Renderer.cs +++ /dev/null @@ -1,952 +0,0 @@ -namespace GarboDev -{ - using System; - using System.Collections.Generic; - using System.Text; - - public partial class Renderer : IRenderer - { - private Memory memory; - private uint[] scanline = new uint[240]; - private byte[] blend = new byte[240]; - private byte[] windowCover = new byte[240]; - private uint[] back = new uint[240 * 160]; - //private uint[] front = new uint[240 * 160]; - private const uint pitch = 240; - - // Convenience variable as I use it everywhere, set once in RenderLine - private ushort dispCnt; - - // Window helper variables - private byte win0x1, win0x2, win0y1, win0y2; - private byte win1x1, win1x2, win1y1, win1y2; - private byte win0Enabled, win1Enabled, winObjEnabled, winOutEnabled; - private bool winEnabled; - - private byte blendSource, blendTarget; - private byte blendA, blendB, blendY; - private int blendType; - - private int curLine = 0; - - private static uint[] colorLUT; - - static Renderer() - { - colorLUT = new uint[0x10000]; - // Pre-calculate the color LUT - for (uint i = 0; i <= 0xFFFF; i++) - { - uint r = (i & 0x1FU); - uint g = (i & 0x3E0U) >> 5; - uint b = (i & 0x7C00U) >> 10; - r = (r << 3) | (r >> 2); - g = (g << 3) | (g >> 2); - b = (b << 3) | (b >> 2); - colorLUT[i] = (r << 16) | (g << 8) | b; - } - } - - public Memory Memory - { - set { this.memory = value; } - } - - public void Initialize(object data) - { - } - - public void Reset() - { - } - - public uint[] ShowFrame() - { - //Array.Copy(this.back, this.front, this.front.Length); - - //return this.front; - return this.back; - } - - public void RenderLine(int line) - { - this.curLine = line; - - // Render the line - this.dispCnt = Memory.ReadU16(this.memory.IORam, Memory.DISPCNT); - - if ((this.dispCnt & (1 << 7)) != 0) - { - uint bgColor = Renderer.GbaTo32((ushort)0x7FFF); - for (int i = 0; i < 240; i++) this.scanline[i] = bgColor; - } - else - { - this.winEnabled = false; - - if ((this.dispCnt & (1 << 13)) != 0) - { - // Calculate window 0 information - ushort winy = Memory.ReadU16(this.memory.IORam, Memory.WIN0V); - this.win0y1 = (byte)(winy >> 8); - this.win0y2 = (byte)(winy & 0xff); - ushort winx = Memory.ReadU16(this.memory.IORam, Memory.WIN0H); - this.win0x1 = (byte)(winx >> 8); - this.win0x2 = (byte)(winx & 0xff); - - if (this.win0x2 > 240 || this.win0x1 > this.win0x2) - { - this.win0x2 = 240; - } - - if (this.win0y2 > 160 || this.win0y1 > this.win0y2) - { - this.win0y2 = 160; - } - - this.win0Enabled = this.memory.IORam[Memory.WININ]; - this.winEnabled = true; - } - - if ((this.dispCnt & (1 << 14)) != 0) - { - // Calculate window 1 information - ushort winy = Memory.ReadU16(this.memory.IORam, Memory.WIN1V); - this.win1y1 = (byte)(winy >> 8); - this.win1y2 = (byte)(winy & 0xff); - ushort winx = Memory.ReadU16(this.memory.IORam, Memory.WIN1H); - this.win1x1 = (byte)(winx >> 8); - this.win1x2 = (byte)(winx & 0xff); - - if (this.win1x2 > 240 || this.win1x1 > this.win1x2) - { - this.win1x2 = 240; - } - - if (this.win1y2 > 160 || this.win1y1 > this.win1y2) - { - this.win1y2 = 160; - } - - this.win1Enabled = this.memory.IORam[Memory.WININ + 1]; - this.winEnabled = true; - } - - if ((this.dispCnt & (1 << 15)) != 0 && (this.dispCnt & (1 << 12)) != 0) - { - // Object windows are enabled - this.winObjEnabled = this.memory.IORam[Memory.WINOUT + 1]; - this.winEnabled = true; - } - - if (this.winEnabled) - { - this.winOutEnabled = this.memory.IORam[Memory.WINOUT]; - } - - // Calculate blending information - ushort bldcnt = Memory.ReadU16(this.memory.IORam, Memory.BLDCNT); - this.blendType = (bldcnt >> 6) & 0x3; - this.blendSource = (byte)(bldcnt & 0x3F); - this.blendTarget = (byte)((bldcnt >> 8) & 0x3F); - - ushort bldalpha = Memory.ReadU16(this.memory.IORam, Memory.BLDALPHA); - this.blendA = (byte)(bldalpha & 0x1F); - if (this.blendA > 0x10) this.blendA = 0x10; - this.blendB = (byte)((bldalpha >> 8) & 0x1F); - if (this.blendB > 0x10) this.blendB = 0x10; - - this.blendY = (byte)(this.memory.IORam[Memory.BLDY] & 0x1F); - if (this.blendY > 0x10) this.blendY = 0x10; - - switch (this.dispCnt & 0x7) - { - case 0: this.RenderMode0Line(); break; - case 1: this.RenderMode1Line(); break; - case 2: this.RenderMode2Line(); break; - case 3: this.RenderMode3Line(); break; - case 4: this.RenderMode4Line(); break; - case 5: this.RenderMode5Line(); break; - } - } - - Array.Copy(this.scanline, 0, this.back, this.curLine * Renderer.pitch, Renderer.pitch); - } - - private void DrawBackdrop() - { - byte[] palette = this.memory.PaletteRam; - - // Initialize window coverage buffer if neccesary - if (this.winEnabled) - { - for (int i = 0; i < 240; i++) - { - this.windowCover[i] = this.winOutEnabled; - } - - if ((this.dispCnt & (1 << 15)) != 0) - { - // Sprite window - this.DrawSpriteWindows(); - } - - if ((this.dispCnt & (1 << 14)) != 0) - { - // Window 1 - if (this.curLine >= this.win1y1 && this.curLine < this.win1y2) - { - for (int i = this.win1x1; i < this.win1x2; i++) - { - this.windowCover[i] = this.win1Enabled; - } - } - } - - if ((this.dispCnt & (1 << 13)) != 0) - { - // Window 0 - if (this.curLine >= this.win0y1 && this.curLine < this.win0y2) - { - for (int i = this.win0x1; i < this.win0x2; i++) - { - this.windowCover[i] = this.win0Enabled; - } - } - } - } - - // Draw backdrop first - uint bgColor = Renderer.GbaTo32((ushort)(palette[0] | (palette[1] << 8))); - uint modColor = bgColor; - - if (this.blendType == 2 && (this.blendSource & (1 << 5)) != 0) - { - // Brightness increase - uint r = bgColor & 0xFF; - uint g = (bgColor >> 8) & 0xFF; - uint b = (bgColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - modColor = r | (g << 8) | (b << 16); - } - else if (this.blendType == 3 && (this.blendSource & (1 << 5)) != 0) - { - // Brightness decrease - uint r = bgColor & 0xFF; - uint g = (bgColor >> 8) & 0xFF; - uint b = (bgColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - modColor = r | (g << 8) | (b << 16); - } - - if (this.winEnabled) - { - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << 5)) != 0) - { - this.scanline[i] = modColor; - } - else - { - this.scanline[i] = bgColor; - } - this.blend[i] = 1 << 5; - } - } - else - { - for (int i = 0; i < 240; i++) - { - this.scanline[i] = modColor; - this.blend[i] = 1 << 5; - } - } - } - - private void RenderTextBg(int bg) - { - if (this.winEnabled) - { - switch (this.blendType) - { - case 0: - this.RenderTextBgWindow(bg); - break; - case 1: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderTextBgWindowBlend(bg); - else - this.RenderTextBgWindow(bg); - break; - case 2: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderTextBgWindowBrightInc(bg); - else - this.RenderTextBgWindow(bg); - break; - case 3: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderTextBgWindowBrightDec(bg); - else - this.RenderTextBgWindow(bg); - break; - } - } - else - { - switch (this.blendType) - { - case 0: - this.RenderTextBgNormal(bg); - break; - case 1: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderTextBgBlend(bg); - else - this.RenderTextBgNormal(bg); - break; - case 2: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderTextBgBrightInc(bg); - else - this.RenderTextBgNormal(bg); - break; - case 3: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderTextBgBrightDec(bg); - else - this.RenderTextBgNormal(bg); - break; - } - } - } - - private void RenderRotScaleBg(int bg) - { - if (this.winEnabled) - { - switch (this.blendType) - { - case 0: - this.RenderRotScaleBgWindow(bg); - break; - case 1: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderRotScaleBgWindowBlend(bg); - else - this.RenderRotScaleBgWindow(bg); - break; - case 2: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderRotScaleBgWindowBrightInc(bg); - else - this.RenderRotScaleBgWindow(bg); - break; - case 3: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderRotScaleBgWindowBrightDec(bg); - else - this.RenderRotScaleBgWindow(bg); - break; - } - } - else - { - switch (this.blendType) - { - case 0: - this.RenderRotScaleBgNormal(bg); - break; - case 1: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderRotScaleBgBlend(bg); - else - this.RenderRotScaleBgNormal(bg); - break; - case 2: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderRotScaleBgBrightInc(bg); - else - this.RenderRotScaleBgNormal(bg); - break; - case 3: - if ((this.blendSource & (1 << bg)) != 0) - this.RenderRotScaleBgBrightDec(bg); - else - this.RenderRotScaleBgNormal(bg); - break; - } - } - } - - private void DrawSprites(int pri) - { - if (this.winEnabled) - { - switch (this.blendType) - { - case 0: - this.DrawSpritesWindow(pri); - break; - case 1: - if ((this.blendSource & (1 << 4)) != 0) - this.DrawSpritesWindowBlend(pri); - else - this.DrawSpritesWindow(pri); - break; - case 2: - if ((this.blendSource & (1 << 4)) != 0) - this.DrawSpritesWindowBrightInc(pri); - else - this.DrawSpritesWindow(pri); - break; - case 3: - if ((this.blendSource & (1 << 4)) != 0) - this.DrawSpritesWindowBrightDec(pri); - else - this.DrawSpritesWindow(pri); - break; - } - } - else - { - switch (this.blendType) - { - case 0: - this.DrawSpritesNormal(pri); - break; - case 1: - if ((this.blendSource & (1 << 4)) != 0) - this.DrawSpritesBlend(pri); - else - this.DrawSpritesNormal(pri); - break; - case 2: - if ((this.blendSource & (1 << 4)) != 0) - this.DrawSpritesBrightInc(pri); - else - this.DrawSpritesNormal(pri); - break; - case 3: - if ((this.blendSource & (1 << 4)) != 0) - this.DrawSpritesBrightDec(pri); - else - this.DrawSpritesNormal(pri); - break; - } - } - } - - private void RenderMode0Line() - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - this.DrawBackdrop(); - - for (int pri = 3; pri >= 0; pri--) - { - for (int i = 3; i >= 0; i--) - { - if ((this.dispCnt & (1 << (8 + i))) != 0) - { - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)i); - - if ((bgcnt & 0x3) == pri) - { - this.RenderTextBg(i); - } - } - } - - this.DrawSprites(pri); - } - } - - private void RenderMode1Line() - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - this.DrawBackdrop(); - - for (int pri = 3; pri >= 0; pri--) - { - if ((this.dispCnt & (1 << (8 + 2))) != 0) - { - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG2CNT); - - if ((bgcnt & 0x3) == pri) - { - this.RenderRotScaleBg(2); - } - } - - for (int i = 1; i >= 0; i--) - { - if ((this.dispCnt & (1 << (8 + i))) != 0) - { - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)i); - - if ((bgcnt & 0x3) == pri) - { - this.RenderTextBg(i); - } - } - } - - this.DrawSprites(pri); - } - } - - private void RenderMode2Line() - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - this.DrawBackdrop(); - - for (int pri = 3; pri >= 0; pri--) - { - for (int i = 3; i >= 2; i--) - { - if ((this.dispCnt & (1 << (8 + i))) != 0) - { - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)i); - - if ((bgcnt & 0x3) == pri) - { - this.RenderRotScaleBg(i); - } - } - } - - this.DrawSprites(pri); - } - } - - private void RenderMode3Line() - { - ushort bg2Cnt = Memory.ReadU16(this.memory.IORam, Memory.BG2CNT); - - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - this.DrawBackdrop(); - - byte blendMaskType = (byte)(1 << 2); - - int bgPri = bg2Cnt & 0x3; - for (int pri = 3; pri > bgPri; pri--) - { - this.DrawSprites(pri); - } - - if ((this.dispCnt & (1 << 10)) != 0) - { - // Background enabled, render it - int x = this.memory.Bgx[0]; - int y = this.memory.Bgy[0]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC); - - for (int i = 0; i < 240; i++) - { - int ax = ((int)x) >> 8; - int ay = ((int)y) >> 8; - - if (ax >= 0 && ax < 240 && ay >= 0 && ay < 160) - { - int curIdx = ((ay * 240) + ax) * 2; - this.scanline[i] = Renderer.GbaTo32((ushort)(vram[curIdx] | (vram[curIdx + 1] << 8))); - this.blend[i] = blendMaskType; - } - - x += dx; - y += dy; - } - } - - for (int pri = bgPri; pri >= 0; pri--) - { - this.DrawSprites(pri); - } - } - - private void RenderMode4Line() - { - ushort bg2Cnt = Memory.ReadU16(this.memory.IORam, Memory.BG2CNT); - - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - this.DrawBackdrop(); - - byte blendMaskType = (byte)(1 << 2); - - int bgPri = bg2Cnt & 0x3; - for (int pri = 3; pri > bgPri; pri--) - { - this.DrawSprites(pri); - } - - if ((this.dispCnt & (1 << 10)) != 0) - { - // Background enabled, render it - int baseIdx = 0; - if ((this.dispCnt & (1 << 4)) == 1 << 4) baseIdx = 0xA000; - - int x = this.memory.Bgx[0]; - int y = this.memory.Bgy[0]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC); - - for (int i = 0; i < 240; i++) - { - int ax = ((int)x) >> 8; - int ay = ((int)y) >> 8; - - if (ax >= 0 && ax < 240 && ay >= 0 && ay < 160) - { - int lookup = vram[baseIdx + (ay * 240) + ax]; - if (lookup != 0) - { - this.scanline[i] = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - this.blend[i] = blendMaskType; - } - } - - x += dx; - y += dy; - } - } - - for (int pri = bgPri; pri >= 0; pri--) - { - this.DrawSprites(pri); - } - } - - private void RenderMode5Line() - { - ushort bg2Cnt = Memory.ReadU16(this.memory.IORam, Memory.BG2CNT); - - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - this.DrawBackdrop(); - - byte blendMaskType = (byte)(1 << 2); - - int bgPri = bg2Cnt & 0x3; - for (int pri = 3; pri > bgPri; pri--) - { - this.DrawSprites(pri); - } - - if ((this.dispCnt & (1 << 10)) != 0) - { - // Background enabled, render it - int baseIdx = 0; - if ((this.dispCnt & (1 << 4)) == 1 << 4) baseIdx += 160 * 128 * 2; - - int x = this.memory.Bgx[0]; - int y = this.memory.Bgy[0]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC); - - for (int i = 0; i < 240; i++) - { - int ax = ((int)x) >> 8; - int ay = ((int)y) >> 8; - - if (ax >= 0 && ax < 160 && ay >= 0 && ay < 128) - { - int curIdx = (int)(ay * 160 + ax) * 2; - - this.scanline[i] = Renderer.GbaTo32((ushort)(vram[baseIdx + curIdx] | (vram[baseIdx + curIdx + 1] << 8))); - this.blend[i] = blendMaskType; - } - - x += dx; - y += dy; - } - } - - for (int pri = bgPri; pri >= 0; pri--) - { - this.DrawSprites(pri); - } - } - - private void DrawSpriteWindows() - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - // OBJ must be enabled in this.dispCnt - if ((this.dispCnt & (1 << 12)) == 0) return; - - for (int oamNum = 127; oamNum >= 0; oamNum--) - { - ushort attr0 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 0); - - // Not an object window, so continue - if (((attr0 >> 10) & 3) != 2) continue; - - ushort attr1 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 2); - ushort attr2 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 4); - - int x = attr1 & 0x1FF; - int y = attr0 & 0xFF; - - int width = -1, height = -1; - switch ((attr0 >> 14) & 3) - { - case 0: - // Square - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 8; break; - case 1: width = 16; height = 16; break; - case 2: width = 32; height = 32; break; - case 3: width = 64; height = 64; break; - } - break; - case 1: - // Horizontal Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 16; height = 8; break; - case 1: width = 32; height = 8; break; - case 2: width = 32; height = 16; break; - case 3: width = 64; height = 32; break; - } - break; - case 2: - // Vertical Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 16; break; - case 1: width = 8; height = 32; break; - case 2: width = 16; height = 32; break; - case 3: width = 32; height = 64; break; - } - break; - } - - // Check double size flag here - - int rwidth = width, rheight = height; - if ((attr0 & (1 << 8)) != 0) - { - // Rot-scale on - if ((attr0 & (1 << 9)) != 0) - { - rwidth *= 2; - rheight *= 2; - } - } - else - { - // Invalid sprite - if ((attr0 & (1 << 9)) != 0) - width = -1; - } - - if (width == -1) - { - // Invalid sprite - continue; - } - - // Y clipping - if (y > ((y + rheight) & 0xff)) - { - if (this.curLine >= ((y + rheight) & 0xff) && !(y < this.curLine)) continue; - } - else - { - if (this.curLine < y || this.curLine >= ((y + rheight) & 0xff)) continue; - } - - int scale = 1; - if ((attr0 & (1 << 13)) != 0) scale = 2; - - int spritey = this.curLine - y; - if (spritey < 0) spritey += 256; - - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - this.windowCover[i & 0x1ff] = this.winObjEnabled; - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - this.windowCover[i & 0x1ff] = this.winObjEnabled; - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - short rx = (short)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - short ry = (short)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - this.windowCover[i & 0x1ff] = this.winObjEnabled; - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - this.windowCover[i & 0x1ff] = this.winObjEnabled; - } - } - - rx += dx; - ry += dy; - } - } - } - } - } - - public static uint GbaTo32(ushort color) - { - // more accurate, but slower :( - // return colorLUT[color]; - return ((color & 0x1FU) << 19) | ((color & 0x3E0U) << 6) | ((color & 0x7C00U) >> 7); - } - } -} diff --git a/attic/GarboDev/Renderers.cs b/attic/GarboDev/Renderers.cs deleted file mode 100644 index a05b3b8634..0000000000 --- a/attic/GarboDev/Renderers.cs +++ /dev/null @@ -1,5939 +0,0 @@ -namespace GarboDev -{ - partial class Renderer - { - #region Sprite Drawing - private void DrawSpritesNormal(int priority) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - // OBJ must be enabled in this.dispCnt - if ((this.dispCnt & (1 << 12)) == 0) return; - - byte blendMaskType = (byte)(1 << 4); - - for (int oamNum = 127; oamNum >= 0; oamNum--) - { - ushort attr2 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 4); - - if (((attr2 >> 10) & 3) != priority) continue; - - ushort attr0 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 0); - ushort attr1 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 2); - - int x = attr1 & 0x1FF; - int y = attr0 & 0xFF; - - bool semiTransparent = false; - - switch ((attr0 >> 10) & 3) - { - case 1: - // Semi-transparent - semiTransparent = true; - break; - case 2: - // Obj window - continue; - case 3: - continue; - } - - if ((this.dispCnt & 0x7) >= 3 && (attr2 & 0x3FF) < 0x200) continue; - - int width = -1, height = -1; - switch ((attr0 >> 14) & 3) - { - case 0: - // Square - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 8; break; - case 1: width = 16; height = 16; break; - case 2: width = 32; height = 32; break; - case 3: width = 64; height = 64; break; - } - break; - case 1: - // Horizontal Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 16; height = 8; break; - case 1: width = 32; height = 8; break; - case 2: width = 32; height = 16; break; - case 3: width = 64; height = 32; break; - } - break; - case 2: - // Vertical Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 16; break; - case 1: width = 8; height = 32; break; - case 2: width = 16; height = 32; break; - case 3: width = 32; height = 64; break; - } - break; - } - - // Check double size flag here - - int rwidth = width, rheight = height; - if ((attr0 & (1 << 8)) != 0) - { - // Rot-scale on - if ((attr0 & (1 << 9)) != 0) - { - rwidth *= 2; - rheight *= 2; - } - } - else - { - // Invalid sprite - if ((attr0 & (1 << 9)) != 0) - width = -1; - } - - if (width == -1) - { - // Invalid sprite - continue; - } - - // Y clipping - if (y > ((y + rheight) & 0xff)) - { - if (this.curLine >= ((y + rheight) & 0xff) && !(y < this.curLine)) continue; - } - else - { - if (this.curLine < y || this.curLine >= ((y + rheight) & 0xff)) continue; - } - - int scale = 1; - if ((attr0 & (1 << 13)) != 0) scale = 2; - - int spritey = this.curLine - y; - if (spritey < 0) spritey += 256; - - if (semiTransparent) - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - else - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - } - } - private void DrawSpritesBlend(int priority) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - // OBJ must be enabled in this.dispCnt - if ((this.dispCnt & (1 << 12)) == 0) return; - - byte blendMaskType = (byte)(1 << 4); - - for (int oamNum = 127; oamNum >= 0; oamNum--) - { - ushort attr2 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 4); - - if (((attr2 >> 10) & 3) != priority) continue; - - ushort attr0 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 0); - ushort attr1 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 2); - - int x = attr1 & 0x1FF; - int y = attr0 & 0xFF; - - bool semiTransparent = false; - - switch ((attr0 >> 10) & 3) - { - case 1: - // Semi-transparent - semiTransparent = true; - break; - case 2: - // Obj window - continue; - case 3: - continue; - } - - if ((this.dispCnt & 0x7) >= 3 && (attr2 & 0x3FF) < 0x200) continue; - - int width = -1, height = -1; - switch ((attr0 >> 14) & 3) - { - case 0: - // Square - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 8; break; - case 1: width = 16; height = 16; break; - case 2: width = 32; height = 32; break; - case 3: width = 64; height = 64; break; - } - break; - case 1: - // Horizontal Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 16; height = 8; break; - case 1: width = 32; height = 8; break; - case 2: width = 32; height = 16; break; - case 3: width = 64; height = 32; break; - } - break; - case 2: - // Vertical Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 16; break; - case 1: width = 8; height = 32; break; - case 2: width = 16; height = 32; break; - case 3: width = 32; height = 64; break; - } - break; - } - - // Check double size flag here - - int rwidth = width, rheight = height; - if ((attr0 & (1 << 8)) != 0) - { - // Rot-scale on - if ((attr0 & (1 << 9)) != 0) - { - rwidth *= 2; - rheight *= 2; - } - } - else - { - // Invalid sprite - if ((attr0 & (1 << 9)) != 0) - width = -1; - } - - if (width == -1) - { - // Invalid sprite - continue; - } - - // Y clipping - if (y > ((y + rheight) & 0xff)) - { - if (this.curLine >= ((y + rheight) & 0xff) && !(y < this.curLine)) continue; - } - else - { - if (this.curLine < y || this.curLine >= ((y + rheight) & 0xff)) continue; - } - - int scale = 1; - if ((attr0 & (1 << 13)) != 0) scale = 2; - - int spritey = this.curLine - y; - if (spritey < 0) spritey += 256; - - if (semiTransparent) - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - else - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - } - } - private void DrawSpritesBrightInc(int priority) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - // OBJ must be enabled in this.dispCnt - if ((this.dispCnt & (1 << 12)) == 0) return; - - byte blendMaskType = (byte)(1 << 4); - - for (int oamNum = 127; oamNum >= 0; oamNum--) - { - ushort attr2 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 4); - - if (((attr2 >> 10) & 3) != priority) continue; - - ushort attr0 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 0); - ushort attr1 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 2); - - int x = attr1 & 0x1FF; - int y = attr0 & 0xFF; - - bool semiTransparent = false; - - switch ((attr0 >> 10) & 3) - { - case 1: - // Semi-transparent - semiTransparent = true; - break; - case 2: - // Obj window - continue; - case 3: - continue; - } - - if ((this.dispCnt & 0x7) >= 3 && (attr2 & 0x3FF) < 0x200) continue; - - int width = -1, height = -1; - switch ((attr0 >> 14) & 3) - { - case 0: - // Square - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 8; break; - case 1: width = 16; height = 16; break; - case 2: width = 32; height = 32; break; - case 3: width = 64; height = 64; break; - } - break; - case 1: - // Horizontal Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 16; height = 8; break; - case 1: width = 32; height = 8; break; - case 2: width = 32; height = 16; break; - case 3: width = 64; height = 32; break; - } - break; - case 2: - // Vertical Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 16; break; - case 1: width = 8; height = 32; break; - case 2: width = 16; height = 32; break; - case 3: width = 32; height = 64; break; - } - break; - } - - // Check double size flag here - - int rwidth = width, rheight = height; - if ((attr0 & (1 << 8)) != 0) - { - // Rot-scale on - if ((attr0 & (1 << 9)) != 0) - { - rwidth *= 2; - rheight *= 2; - } - } - else - { - // Invalid sprite - if ((attr0 & (1 << 9)) != 0) - width = -1; - } - - if (width == -1) - { - // Invalid sprite - continue; - } - - // Y clipping - if (y > ((y + rheight) & 0xff)) - { - if (this.curLine >= ((y + rheight) & 0xff) && !(y < this.curLine)) continue; - } - else - { - if (this.curLine < y || this.curLine >= ((y + rheight) & 0xff)) continue; - } - - int scale = 1; - if ((attr0 & (1 << 13)) != 0) scale = 2; - - int spritey = this.curLine - y; - if (spritey < 0) spritey += 256; - - if (semiTransparent) - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - else - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - } - } - private void DrawSpritesBrightDec(int priority) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - // OBJ must be enabled in this.dispCnt - if ((this.dispCnt & (1 << 12)) == 0) return; - - byte blendMaskType = (byte)(1 << 4); - - for (int oamNum = 127; oamNum >= 0; oamNum--) - { - ushort attr2 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 4); - - if (((attr2 >> 10) & 3) != priority) continue; - - ushort attr0 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 0); - ushort attr1 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 2); - - int x = attr1 & 0x1FF; - int y = attr0 & 0xFF; - - bool semiTransparent = false; - - switch ((attr0 >> 10) & 3) - { - case 1: - // Semi-transparent - semiTransparent = true; - break; - case 2: - // Obj window - continue; - case 3: - continue; - } - - if ((this.dispCnt & 0x7) >= 3 && (attr2 & 0x3FF) < 0x200) continue; - - int width = -1, height = -1; - switch ((attr0 >> 14) & 3) - { - case 0: - // Square - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 8; break; - case 1: width = 16; height = 16; break; - case 2: width = 32; height = 32; break; - case 3: width = 64; height = 64; break; - } - break; - case 1: - // Horizontal Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 16; height = 8; break; - case 1: width = 32; height = 8; break; - case 2: width = 32; height = 16; break; - case 3: width = 64; height = 32; break; - } - break; - case 2: - // Vertical Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 16; break; - case 1: width = 8; height = 32; break; - case 2: width = 16; height = 32; break; - case 3: width = 32; height = 64; break; - } - break; - } - - // Check double size flag here - - int rwidth = width, rheight = height; - if ((attr0 & (1 << 8)) != 0) - { - // Rot-scale on - if ((attr0 & (1 << 9)) != 0) - { - rwidth *= 2; - rheight *= 2; - } - } - else - { - // Invalid sprite - if ((attr0 & (1 << 9)) != 0) - width = -1; - } - - if (width == -1) - { - // Invalid sprite - continue; - } - - // Y clipping - if (y > ((y + rheight) & 0xff)) - { - if (this.curLine >= ((y + rheight) & 0xff) && !(y < this.curLine)) continue; - } - else - { - if (this.curLine < y || this.curLine >= ((y + rheight) & 0xff)) continue; - } - - int scale = 1; - if ((attr0 & (1 << 13)) != 0) scale = 2; - - int spritey = this.curLine - y; - if (spritey < 0) spritey += 256; - - if (semiTransparent) - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - else - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && true) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && true) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - } - } - private void DrawSpritesWindow(int priority) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - // OBJ must be enabled in this.dispCnt - if ((this.dispCnt & (1 << 12)) == 0) return; - - byte blendMaskType = (byte)(1 << 4); - - for (int oamNum = 127; oamNum >= 0; oamNum--) - { - ushort attr2 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 4); - - if (((attr2 >> 10) & 3) != priority) continue; - - ushort attr0 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 0); - ushort attr1 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 2); - - int x = attr1 & 0x1FF; - int y = attr0 & 0xFF; - - bool semiTransparent = false; - - switch ((attr0 >> 10) & 3) - { - case 1: - // Semi-transparent - semiTransparent = true; - break; - case 2: - // Obj window - continue; - case 3: - continue; - } - - if ((this.dispCnt & 0x7) >= 3 && (attr2 & 0x3FF) < 0x200) continue; - - int width = -1, height = -1; - switch ((attr0 >> 14) & 3) - { - case 0: - // Square - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 8; break; - case 1: width = 16; height = 16; break; - case 2: width = 32; height = 32; break; - case 3: width = 64; height = 64; break; - } - break; - case 1: - // Horizontal Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 16; height = 8; break; - case 1: width = 32; height = 8; break; - case 2: width = 32; height = 16; break; - case 3: width = 64; height = 32; break; - } - break; - case 2: - // Vertical Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 16; break; - case 1: width = 8; height = 32; break; - case 2: width = 16; height = 32; break; - case 3: width = 32; height = 64; break; - } - break; - } - - // Check double size flag here - - int rwidth = width, rheight = height; - if ((attr0 & (1 << 8)) != 0) - { - // Rot-scale on - if ((attr0 & (1 << 9)) != 0) - { - rwidth *= 2; - rheight *= 2; - } - } - else - { - // Invalid sprite - if ((attr0 & (1 << 9)) != 0) - width = -1; - } - - if (width == -1) - { - // Invalid sprite - continue; - } - - // Y clipping - if (y > ((y + rheight) & 0xff)) - { - if (this.curLine >= ((y + rheight) & 0xff) && !(y < this.curLine)) continue; - } - else - { - if (this.curLine < y || this.curLine >= ((y + rheight) & 0xff)) continue; - } - - int scale = 1; - if ((attr0 & (1 << 13)) != 0) scale = 2; - - int spritey = this.curLine - y; - if (spritey < 0) spritey += 256; - - if (semiTransparent) - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - else - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - } - } - private void DrawSpritesWindowBlend(int priority) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - // OBJ must be enabled in this.dispCnt - if ((this.dispCnt & (1 << 12)) == 0) return; - - byte blendMaskType = (byte)(1 << 4); - - for (int oamNum = 127; oamNum >= 0; oamNum--) - { - ushort attr2 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 4); - - if (((attr2 >> 10) & 3) != priority) continue; - - ushort attr0 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 0); - ushort attr1 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 2); - - int x = attr1 & 0x1FF; - int y = attr0 & 0xFF; - - bool semiTransparent = false; - - switch ((attr0 >> 10) & 3) - { - case 1: - // Semi-transparent - semiTransparent = true; - break; - case 2: - // Obj window - continue; - case 3: - continue; - } - - if ((this.dispCnt & 0x7) >= 3 && (attr2 & 0x3FF) < 0x200) continue; - - int width = -1, height = -1; - switch ((attr0 >> 14) & 3) - { - case 0: - // Square - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 8; break; - case 1: width = 16; height = 16; break; - case 2: width = 32; height = 32; break; - case 3: width = 64; height = 64; break; - } - break; - case 1: - // Horizontal Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 16; height = 8; break; - case 1: width = 32; height = 8; break; - case 2: width = 32; height = 16; break; - case 3: width = 64; height = 32; break; - } - break; - case 2: - // Vertical Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 16; break; - case 1: width = 8; height = 32; break; - case 2: width = 16; height = 32; break; - case 3: width = 32; height = 64; break; - } - break; - } - - // Check double size flag here - - int rwidth = width, rheight = height; - if ((attr0 & (1 << 8)) != 0) - { - // Rot-scale on - if ((attr0 & (1 << 9)) != 0) - { - rwidth *= 2; - rheight *= 2; - } - } - else - { - // Invalid sprite - if ((attr0 & (1 << 9)) != 0) - width = -1; - } - - if (width == -1) - { - // Invalid sprite - continue; - } - - // Y clipping - if (y > ((y + rheight) & 0xff)) - { - if (this.curLine >= ((y + rheight) & 0xff) && !(y < this.curLine)) continue; - } - else - { - if (this.curLine < y || this.curLine >= ((y + rheight) & 0xff)) continue; - } - - int scale = 1; - if ((attr0 & (1 << 13)) != 0) scale = 2; - - int spritey = this.curLine - y; - if (spritey < 0) spritey += 256; - - if (semiTransparent) - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - else - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - } - } - private void DrawSpritesWindowBrightInc(int priority) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - // OBJ must be enabled in this.dispCnt - if ((this.dispCnt & (1 << 12)) == 0) return; - - byte blendMaskType = (byte)(1 << 4); - - for (int oamNum = 127; oamNum >= 0; oamNum--) - { - ushort attr2 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 4); - - if (((attr2 >> 10) & 3) != priority) continue; - - ushort attr0 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 0); - ushort attr1 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 2); - - int x = attr1 & 0x1FF; - int y = attr0 & 0xFF; - - bool semiTransparent = false; - - switch ((attr0 >> 10) & 3) - { - case 1: - // Semi-transparent - semiTransparent = true; - break; - case 2: - // Obj window - continue; - case 3: - continue; - } - - if ((this.dispCnt & 0x7) >= 3 && (attr2 & 0x3FF) < 0x200) continue; - - int width = -1, height = -1; - switch ((attr0 >> 14) & 3) - { - case 0: - // Square - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 8; break; - case 1: width = 16; height = 16; break; - case 2: width = 32; height = 32; break; - case 3: width = 64; height = 64; break; - } - break; - case 1: - // Horizontal Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 16; height = 8; break; - case 1: width = 32; height = 8; break; - case 2: width = 32; height = 16; break; - case 3: width = 64; height = 32; break; - } - break; - case 2: - // Vertical Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 16; break; - case 1: width = 8; height = 32; break; - case 2: width = 16; height = 32; break; - case 3: width = 32; height = 64; break; - } - break; - } - - // Check double size flag here - - int rwidth = width, rheight = height; - if ((attr0 & (1 << 8)) != 0) - { - // Rot-scale on - if ((attr0 & (1 << 9)) != 0) - { - rwidth *= 2; - rheight *= 2; - } - } - else - { - // Invalid sprite - if ((attr0 & (1 << 9)) != 0) - width = -1; - } - - if (width == -1) - { - // Invalid sprite - continue; - } - - // Y clipping - if (y > ((y + rheight) & 0xff)) - { - if (this.curLine >= ((y + rheight) & 0xff) && !(y < this.curLine)) continue; - } - else - { - if (this.curLine < y || this.curLine >= ((y + rheight) & 0xff)) continue; - } - - int scale = 1; - if ((attr0 & (1 << 13)) != 0) scale = 2; - - int spritey = this.curLine - y; - if (spritey < 0) spritey += 256; - - if (semiTransparent) - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - else - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - } - } - private void DrawSpritesWindowBrightDec(int priority) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - // OBJ must be enabled in this.dispCnt - if ((this.dispCnt & (1 << 12)) == 0) return; - - byte blendMaskType = (byte)(1 << 4); - - for (int oamNum = 127; oamNum >= 0; oamNum--) - { - ushort attr2 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 4); - - if (((attr2 >> 10) & 3) != priority) continue; - - ushort attr0 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 0); - ushort attr1 = this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(oamNum * 8) + 2); - - int x = attr1 & 0x1FF; - int y = attr0 & 0xFF; - - bool semiTransparent = false; - - switch ((attr0 >> 10) & 3) - { - case 1: - // Semi-transparent - semiTransparent = true; - break; - case 2: - // Obj window - continue; - case 3: - continue; - } - - if ((this.dispCnt & 0x7) >= 3 && (attr2 & 0x3FF) < 0x200) continue; - - int width = -1, height = -1; - switch ((attr0 >> 14) & 3) - { - case 0: - // Square - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 8; break; - case 1: width = 16; height = 16; break; - case 2: width = 32; height = 32; break; - case 3: width = 64; height = 64; break; - } - break; - case 1: - // Horizontal Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 16; height = 8; break; - case 1: width = 32; height = 8; break; - case 2: width = 32; height = 16; break; - case 3: width = 64; height = 32; break; - } - break; - case 2: - // Vertical Rectangle - switch ((attr1 >> 14) & 3) - { - case 0: width = 8; height = 16; break; - case 1: width = 8; height = 32; break; - case 2: width = 16; height = 32; break; - case 3: width = 32; height = 64; break; - } - break; - } - - // Check double size flag here - - int rwidth = width, rheight = height; - if ((attr0 & (1 << 8)) != 0) - { - // Rot-scale on - if ((attr0 & (1 << 9)) != 0) - { - rwidth *= 2; - rheight *= 2; - } - } - else - { - // Invalid sprite - if ((attr0 & (1 << 9)) != 0) - width = -1; - } - - if (width == -1) - { - // Invalid sprite - continue; - } - - // Y clipping - if (y > ((y + rheight) & 0xff)) - { - if (this.curLine >= ((y + rheight) & 0xff) && !(y < this.curLine)) continue; - } - else - { - if (this.curLine < y || this.curLine >= ((y + rheight) & 0xff)) continue; - } - - int scale = 1; - if ((attr0 & (1 << 13)) != 0) scale = 2; - - int spritey = this.curLine - y; - if (spritey < 0) spritey += 256; - - if (semiTransparent) - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - if ((this.blend[i & 0x1ff] & this.blendTarget) != 0 && this.blend[i & 0x1ff] != blendMaskType) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[(i & 0x1ff)]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - else - { - if ((attr0 & (1 << 8)) == 0) - { - if ((attr1 & (1 << 13)) != 0) spritey = (height - 1) - spritey; - - int baseSprite; - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * (width / 8)) * scale; - } - else - { - // 2 dimensional - baseSprite = (attr2 & 0x3FF) + ((spritey / 8) * 0x20); - } - - int baseInc = scale; - if ((attr1 & (1 << 12)) != 0) - { - baseSprite += ((width / 8) * scale) - scale; - baseInc = -baseInc; - } - - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 8) + tx; - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + width; i++) - { - if ((i & 0x1ff) < 240 && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int tx = (i - x) & 7; - if ((attr1 & (1 << 12)) != 0) tx = 7 - tx; - int curIdx = baseSprite * 32 + ((spritey & 7) * 4) + (tx / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - if (((i - x) & 7) == 7) baseSprite += baseInc; - } - } - } - else - { - int rotScaleParam = (attr1 >> 9) & 0x1F; - - short dx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x6); - short dmx = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0xE); - short dy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x16); - short dmy = (short)this.memory.ReadU16Debug(Memory.OAM_BASE + (uint)(rotScaleParam * 8 * 4) + 0x1E); - - int cx = rwidth / 2; - int cy = rheight / 2; - - int baseSprite = attr2 & 0x3FF; - int pitch; - - if ((this.dispCnt & (1 << 6)) != 0) - { - // 1 dimensional - pitch = (width / 8) * scale; - } - else - { - // 2 dimensional - pitch = 0x20; - } - - int rx = (int)((dmx * (spritey - cy)) - (cx * dx) + (width << 7)); - int ry = (int)((dmy * (spritey - cy)) - (cx * dy) + (height << 7)); - - // Draw a rot/scale sprite - if ((attr0 & (1 << 13)) != 0) - { - // 256 colors - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 8) + (tx & 7); - int lookup = vram[0x10000 + curIdx]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[0x200 + lookup * 2] | (palette[0x200 + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - else - { - // 16 colors - int palIdx = 0x200 + (((attr2 >> 12) & 0xF) * 16 * 2); - for (int i = x; i < x + rwidth; i++) - { - int tx = rx >> 8; - int ty = ry >> 8; - - if ((i & 0x1ff) < 240 && tx >= 0 && tx < width && ty >= 0 && ty < height - && (this.windowCover[i & 0x1ff] & (1 << 4)) != 0) - { - int curIdx = (baseSprite + ((ty / 8) * pitch) + ((tx / 8) * scale)) * 32 + ((ty & 7) * 4) + ((tx & 7) / 2); - int lookup = vram[0x10000 + curIdx]; - if ((tx & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palIdx + lookup * 2] | (palette[palIdx + lookup * 2 + 1] << 8))); - if ((this.windowCover[i & 0x1ff] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[(i & 0x1ff)] = pixelColor; - this.blend[(i & 0x1ff)] = blendMaskType; - - } - } - - rx += dx; - ry += dy; - } - } - } - } - } - } - #endregion Sprite Drawing - #region Rot/Scale Bg - private void RenderRotScaleBgNormal(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 128; height = 128; break; - case 1: width = 256; height = 256; break; - case 2: width = 512; height = 512; break; - case 3: width = 1024; height = 1024; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int x = this.memory.Bgx[bg - 2]; - int y = this.memory.Bgy[bg - 2]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA + (uint)(bg - 2) * 0x10); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC + (uint)(bg - 2) * 0x10); - - bool transparent = (bgcnt & (1 << 13)) == 0; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int ax = x >> 8; - int ay = y >> 8; - - if ((ax >= 0 && ax < width && ay >= 0 && ay < height) || !transparent) - { - int tmpTileIdx = (int)(screenBase + ((ay & (height - 1)) / 8) * (width / 8) + ((ax & (width - 1)) / 8)); - int tileChar = vram[tmpTileIdx]; - - int lookup = vram[charBase + (tileChar * 64) + ((ay & 7) * 8) + (ax & 7)]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - - x += dx; - y += dy; - } - } - private void RenderRotScaleBgBlend(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 128; height = 128; break; - case 1: width = 256; height = 256; break; - case 2: width = 512; height = 512; break; - case 3: width = 1024; height = 1024; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int x = this.memory.Bgx[bg - 2]; - int y = this.memory.Bgy[bg - 2]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA + (uint)(bg - 2) * 0x10); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC + (uint)(bg - 2) * 0x10); - - bool transparent = (bgcnt & (1 << 13)) == 0; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int ax = x >> 8; - int ay = y >> 8; - - if ((ax >= 0 && ax < width && ay >= 0 && ay < height) || !transparent) - { - int tmpTileIdx = (int)(screenBase + ((ay & (height - 1)) / 8) * (width / 8) + ((ax & (width - 1)) / 8)); - int tileChar = vram[tmpTileIdx]; - - int lookup = vram[charBase + (tileChar * 64) + ((ay & 7) * 8) + (ax & 7)]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - if ((this.blend[i] & this.blendTarget) != 0) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[i]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - - x += dx; - y += dy; - } - } - private void RenderRotScaleBgBrightInc(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 128; height = 128; break; - case 1: width = 256; height = 256; break; - case 2: width = 512; height = 512; break; - case 3: width = 1024; height = 1024; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int x = this.memory.Bgx[bg - 2]; - int y = this.memory.Bgy[bg - 2]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA + (uint)(bg - 2) * 0x10); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC + (uint)(bg - 2) * 0x10); - - bool transparent = (bgcnt & (1 << 13)) == 0; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int ax = x >> 8; - int ay = y >> 8; - - if ((ax >= 0 && ax < width && ay >= 0 && ay < height) || !transparent) - { - int tmpTileIdx = (int)(screenBase + ((ay & (height - 1)) / 8) * (width / 8) + ((ax & (width - 1)) / 8)); - int tileChar = vram[tmpTileIdx]; - - int lookup = vram[charBase + (tileChar * 64) + ((ay & 7) * 8) + (ax & 7)]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - - x += dx; - y += dy; - } - } - private void RenderRotScaleBgBrightDec(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 128; height = 128; break; - case 1: width = 256; height = 256; break; - case 2: width = 512; height = 512; break; - case 3: width = 1024; height = 1024; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int x = this.memory.Bgx[bg - 2]; - int y = this.memory.Bgy[bg - 2]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA + (uint)(bg - 2) * 0x10); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC + (uint)(bg - 2) * 0x10); - - bool transparent = (bgcnt & (1 << 13)) == 0; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int ax = x >> 8; - int ay = y >> 8; - - if ((ax >= 0 && ax < width && ay >= 0 && ay < height) || !transparent) - { - int tmpTileIdx = (int)(screenBase + ((ay & (height - 1)) / 8) * (width / 8) + ((ax & (width - 1)) / 8)); - int tileChar = vram[tmpTileIdx]; - - int lookup = vram[charBase + (tileChar * 64) + ((ay & 7) * 8) + (ax & 7)]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - - x += dx; - y += dy; - } - } - private void RenderRotScaleBgWindow(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 128; height = 128; break; - case 1: width = 256; height = 256; break; - case 2: width = 512; height = 512; break; - case 3: width = 1024; height = 1024; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int x = this.memory.Bgx[bg - 2]; - int y = this.memory.Bgy[bg - 2]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA + (uint)(bg - 2) * 0x10); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC + (uint)(bg - 2) * 0x10); - - bool transparent = (bgcnt & (1 << 13)) == 0; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int ax = x >> 8; - int ay = y >> 8; - - if ((ax >= 0 && ax < width && ay >= 0 && ay < height) || !transparent) - { - int tmpTileIdx = (int)(screenBase + ((ay & (height - 1)) / 8) * (width / 8) + ((ax & (width - 1)) / 8)); - int tileChar = vram[tmpTileIdx]; - - int lookup = vram[charBase + (tileChar * 64) + ((ay & 7) * 8) + (ax & 7)]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - - x += dx; - y += dy; - } - } - private void RenderRotScaleBgWindowBlend(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 128; height = 128; break; - case 1: width = 256; height = 256; break; - case 2: width = 512; height = 512; break; - case 3: width = 1024; height = 1024; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int x = this.memory.Bgx[bg - 2]; - int y = this.memory.Bgy[bg - 2]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA + (uint)(bg - 2) * 0x10); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC + (uint)(bg - 2) * 0x10); - - bool transparent = (bgcnt & (1 << 13)) == 0; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int ax = x >> 8; - int ay = y >> 8; - - if ((ax >= 0 && ax < width && ay >= 0 && ay < height) || !transparent) - { - int tmpTileIdx = (int)(screenBase + ((ay & (height - 1)) / 8) * (width / 8) + ((ax & (width - 1)) / 8)); - int tileChar = vram[tmpTileIdx]; - - int lookup = vram[charBase + (tileChar * 64) + ((ay & 7) * 8) + (ax & 7)]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - if ((this.windowCover[i] & (1 << 5)) != 0) - { - if ((this.blend[i] & this.blendTarget) != 0) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[i]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - - x += dx; - y += dy; - } - } - private void RenderRotScaleBgWindowBrightInc(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 128; height = 128; break; - case 1: width = 256; height = 256; break; - case 2: width = 512; height = 512; break; - case 3: width = 1024; height = 1024; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int x = this.memory.Bgx[bg - 2]; - int y = this.memory.Bgy[bg - 2]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA + (uint)(bg - 2) * 0x10); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC + (uint)(bg - 2) * 0x10); - - bool transparent = (bgcnt & (1 << 13)) == 0; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int ax = x >> 8; - int ay = y >> 8; - - if ((ax >= 0 && ax < width && ay >= 0 && ay < height) || !transparent) - { - int tmpTileIdx = (int)(screenBase + ((ay & (height - 1)) / 8) * (width / 8) + ((ax & (width - 1)) / 8)); - int tileChar = vram[tmpTileIdx]; - - int lookup = vram[charBase + (tileChar * 64) + ((ay & 7) * 8) + (ax & 7)]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - if ((this.windowCover[i] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - - x += dx; - y += dy; - } - } - private void RenderRotScaleBgWindowBrightDec(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 128; height = 128; break; - case 1: width = 256; height = 256; break; - case 2: width = 512; height = 512; break; - case 3: width = 1024; height = 1024; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int x = this.memory.Bgx[bg - 2]; - int y = this.memory.Bgy[bg - 2]; - - short dx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PA + (uint)(bg - 2) * 0x10); - short dy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PC + (uint)(bg - 2) * 0x10); - - bool transparent = (bgcnt & (1 << 13)) == 0; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int ax = x >> 8; - int ay = y >> 8; - - if ((ax >= 0 && ax < width && ay >= 0 && ay < height) || !transparent) - { - int tmpTileIdx = (int)(screenBase + ((ay & (height - 1)) / 8) * (width / 8) + ((ax & (width - 1)) / 8)); - int tileChar = vram[tmpTileIdx]; - - int lookup = vram[charBase + (tileChar * 64) + ((ay & 7) * 8) + (ax & 7)]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - if ((this.windowCover[i] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - - x += dx; - y += dy; - } - } - #endregion Rot/Scale Bg - #region Text Bg - private void RenderTextBgNormal(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 256; height = 256; break; - case 1: width = 512; height = 256; break; - case 2: width = 256; height = 512; break; - case 3: width = 512; height = 512; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int hofs = Memory.ReadU16(this.memory.IORam, Memory.BG0HOFS + (uint)bg * 4) & 0x1FF; - int vofs = Memory.ReadU16(this.memory.IORam, Memory.BG0VOFS + (uint)bg * 4) & 0x1FF; - - if ((bgcnt & (1 << 7)) != 0) - { - // 256 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 8; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 56 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 64) + y + x]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - else - { - // 16 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 4; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 28 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 32) + y + (x / 2)]; - if ((x & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - int palNum = ((tileChar >> 12) & 0xf) * 16 * 2; - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palNum + lookup * 2] | (palette[palNum + lookup * 2 + 1] << 8))); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - } - private void RenderTextBgBlend(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 256; height = 256; break; - case 1: width = 512; height = 256; break; - case 2: width = 256; height = 512; break; - case 3: width = 512; height = 512; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int hofs = Memory.ReadU16(this.memory.IORam, Memory.BG0HOFS + (uint)bg * 4) & 0x1FF; - int vofs = Memory.ReadU16(this.memory.IORam, Memory.BG0VOFS + (uint)bg * 4) & 0x1FF; - - if ((bgcnt & (1 << 7)) != 0) - { - // 256 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 8; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 56 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 64) + y + x]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - if ((this.blend[i] & this.blendTarget) != 0) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[i]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - else - { - // 16 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 4; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 28 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 32) + y + (x / 2)]; - if ((x & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - int palNum = ((tileChar >> 12) & 0xf) * 16 * 2; - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palNum + lookup * 2] | (palette[palNum + lookup * 2 + 1] << 8))); - if ((this.blend[i] & this.blendTarget) != 0) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[i]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - } - private void RenderTextBgBrightInc(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 256; height = 256; break; - case 1: width = 512; height = 256; break; - case 2: width = 256; height = 512; break; - case 3: width = 512; height = 512; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int hofs = Memory.ReadU16(this.memory.IORam, Memory.BG0HOFS + (uint)bg * 4) & 0x1FF; - int vofs = Memory.ReadU16(this.memory.IORam, Memory.BG0VOFS + (uint)bg * 4) & 0x1FF; - - if ((bgcnt & (1 << 7)) != 0) - { - // 256 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 8; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 56 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 64) + y + x]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - else - { - // 16 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 4; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 28 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 32) + y + (x / 2)]; - if ((x & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - int palNum = ((tileChar >> 12) & 0xf) * 16 * 2; - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palNum + lookup * 2] | (palette[palNum + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - } - private void RenderTextBgBrightDec(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 256; height = 256; break; - case 1: width = 512; height = 256; break; - case 2: width = 256; height = 512; break; - case 3: width = 512; height = 512; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int hofs = Memory.ReadU16(this.memory.IORam, Memory.BG0HOFS + (uint)bg * 4) & 0x1FF; - int vofs = Memory.ReadU16(this.memory.IORam, Memory.BG0VOFS + (uint)bg * 4) & 0x1FF; - - if ((bgcnt & (1 << 7)) != 0) - { - // 256 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 8; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 56 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 64) + y + x]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - else - { - // 16 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 4; - - for (int i = 0; i < 240; i++) - { - if (true) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 28 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 32) + y + (x / 2)]; - if ((x & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - int palNum = ((tileChar >> 12) & 0xf) * 16 * 2; - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palNum + lookup * 2] | (palette[palNum + lookup * 2 + 1] << 8))); - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - } - private void RenderTextBgWindow(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 256; height = 256; break; - case 1: width = 512; height = 256; break; - case 2: width = 256; height = 512; break; - case 3: width = 512; height = 512; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int hofs = Memory.ReadU16(this.memory.IORam, Memory.BG0HOFS + (uint)bg * 4) & 0x1FF; - int vofs = Memory.ReadU16(this.memory.IORam, Memory.BG0VOFS + (uint)bg * 4) & 0x1FF; - - if ((bgcnt & (1 << 7)) != 0) - { - // 256 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 8; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 56 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 64) + y + x]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - else - { - // 16 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 4; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 28 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 32) + y + (x / 2)]; - if ((x & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - int palNum = ((tileChar >> 12) & 0xf) * 16 * 2; - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palNum + lookup * 2] | (palette[palNum + lookup * 2 + 1] << 8))); - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - } - private void RenderTextBgWindowBlend(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 256; height = 256; break; - case 1: width = 512; height = 256; break; - case 2: width = 256; height = 512; break; - case 3: width = 512; height = 512; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int hofs = Memory.ReadU16(this.memory.IORam, Memory.BG0HOFS + (uint)bg * 4) & 0x1FF; - int vofs = Memory.ReadU16(this.memory.IORam, Memory.BG0VOFS + (uint)bg * 4) & 0x1FF; - - if ((bgcnt & (1 << 7)) != 0) - { - // 256 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 8; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 56 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 64) + y + x]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - if ((this.windowCover[i] & (1 << 5)) != 0) - { - if ((this.blend[i] & this.blendTarget) != 0) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[i]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - else - { - // 16 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 4; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 28 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 32) + y + (x / 2)]; - if ((x & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - int palNum = ((tileChar >> 12) & 0xf) * 16 * 2; - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palNum + lookup * 2] | (palette[palNum + lookup * 2 + 1] << 8))); - if ((this.windowCover[i] & (1 << 5)) != 0) - { - if ((this.blend[i] & this.blendTarget) != 0) - { - uint r = ((pixelColor & 0xFF) * this.blendA) >> 4; - uint g = (((pixelColor >> 8) & 0xFF) * this.blendA) >> 4; - uint b = (((pixelColor >> 16) & 0xFF) * this.blendA) >> 4; - uint sourceValue = this.scanline[i]; - r += ((sourceValue & 0xFF) * this.blendB) >> 4; - g += (((sourceValue >> 8) & 0xFF) * this.blendB) >> 4; - b += (((sourceValue >> 16) & 0xFF) * this.blendB) >> 4; - if (r > 0xff) r = 0xff; - if (g > 0xff) g = 0xff; - if (b > 0xff) b = 0xff; - pixelColor = r | (g << 8) | (b << 16); - } - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - } - private void RenderTextBgWindowBrightInc(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 256; height = 256; break; - case 1: width = 512; height = 256; break; - case 2: width = 256; height = 512; break; - case 3: width = 512; height = 512; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int hofs = Memory.ReadU16(this.memory.IORam, Memory.BG0HOFS + (uint)bg * 4) & 0x1FF; - int vofs = Memory.ReadU16(this.memory.IORam, Memory.BG0VOFS + (uint)bg * 4) & 0x1FF; - - if ((bgcnt & (1 << 7)) != 0) - { - // 256 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 8; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 56 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 64) + y + x]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - if ((this.windowCover[i] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - else - { - // 16 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 4; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 28 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 32) + y + (x / 2)]; - if ((x & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - int palNum = ((tileChar >> 12) & 0xf) * 16 * 2; - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palNum + lookup * 2] | (palette[palNum + lookup * 2 + 1] << 8))); - if ((this.windowCover[i] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r + (((0xFF - r) * this.blendY) >> 4); - g = g + (((0xFF - g) * this.blendY) >> 4); - b = b + (((0xFF - b) * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - } - private void RenderTextBgWindowBrightDec(int bg) - { - byte[] palette = this.memory.PaletteRam; - byte[] vram = this.memory.VideoRam; - - byte blendMaskType = (byte)(1 << bg); - - ushort bgcnt = Memory.ReadU16(this.memory.IORam, Memory.BG0CNT + 0x2 * (uint)bg); - - int width = 0, height = 0; - switch ((bgcnt >> 14) & 0x3) - { - case 0: width = 256; height = 256; break; - case 1: width = 512; height = 256; break; - case 2: width = 256; height = 512; break; - case 3: width = 512; height = 512; break; - } - - int screenBase = ((bgcnt >> 8) & 0x1F) * 0x800; - int charBase = ((bgcnt >> 2) & 0x3) * 0x4000; - - int hofs = Memory.ReadU16(this.memory.IORam, Memory.BG0HOFS + (uint)bg * 4) & 0x1FF; - int vofs = Memory.ReadU16(this.memory.IORam, Memory.BG0VOFS + (uint)bg * 4) & 0x1FF; - - if ((bgcnt & (1 << 7)) != 0) - { - // 256 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 8; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 56 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 64) + y + x]; - if (lookup != 0) - { - uint pixelColor = Renderer.GbaTo32((ushort)(palette[lookup * 2] | (palette[lookup * 2 + 1] << 8))); - if ((this.windowCover[i] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - else - { - // 16 color tiles - int bgy = ((this.curLine + vofs) & (height - 1)) / 8; - - int tileIdx = screenBase + (((bgy & 31) * 32) * 2); - switch ((bgcnt >> 14) & 0x3) - { - case 2: if (bgy >= 32) tileIdx += 32 * 32 * 2; break; - case 3: if (bgy >= 32) tileIdx += 32 * 32 * 4; break; - } - - int tileY = ((this.curLine + vofs) & 0x7) * 4; - - for (int i = 0; i < 240; i++) - { - if ((this.windowCover[i] & (1 << bg)) != 0) - { - int bgx = ((i + hofs) & (width - 1)) / 8; - int tmpTileIdx = tileIdx + ((bgx & 31) * 2); - if (bgx >= 32) tmpTileIdx += 32 * 32 * 2; - int tileChar = vram[tmpTileIdx] | (vram[tmpTileIdx + 1] << 8); - int x = (i + hofs) & 7; - int y = tileY; - if ((tileChar & (1 << 10)) != 0) x = 7 - x; - if ((tileChar & (1 << 11)) != 0) y = 28 - y; - int lookup = vram[charBase + ((tileChar & 0x3FF) * 32) + y + (x / 2)]; - if ((x & 1) == 0) - { - lookup &= 0xf; - } - else - { - lookup >>= 4; - } - if (lookup != 0) - { - int palNum = ((tileChar >> 12) & 0xf) * 16 * 2; - uint pixelColor = Renderer.GbaTo32((ushort)(palette[palNum + lookup * 2] | (palette[palNum + lookup * 2 + 1] << 8))); - if ((this.windowCover[i] & (1 << 5)) != 0) - { - uint r = pixelColor & 0xFF; - uint g = (pixelColor >> 8) & 0xFF; - uint b = (pixelColor >> 16) & 0xFF; - r = r - ((r * this.blendY) >> 4); - g = g - ((g * this.blendY) >> 4); - b = b - ((b * this.blendY) >> 4); - pixelColor = r | (g << 8) | (b << 16); - } - this.scanline[i] = pixelColor; this.blend[i] = blendMaskType; - - } - } - } - } - } - #endregion Text Bg - } -} diff --git a/attic/GarboDev/SoundManager.cs b/attic/GarboDev/SoundManager.cs deleted file mode 100644 index 5679202345..0000000000 --- a/attic/GarboDev/SoundManager.cs +++ /dev/null @@ -1,191 +0,0 @@ -namespace GarboDev -{ - using System; - using System.Collections.Generic; - using System.Text; - - public class SoundManager - { - private Memory memory = null; - private Queue[] soundQueue = new Queue[2]; - private byte latchedA, latchedB; - private int frequency, cyclesPerSample; - private int leftover = 0; - - private short[] soundBuffer = new short[40000]; - private int soundBufferPos = 0; - private int lastSoundBufferPos = 0; - - public SoundManager(Memory memory, int frequency) - { - this.Frequency = frequency; - - this.memory = memory; - this.memory.SoundManager = this; - - this.soundQueue[0] = new Queue(32); - this.soundQueue[1] = new Queue(32); - } - - #region Public Properties - public int Frequency - { - get { return this.frequency; } - set - { - this.frequency = value; - this.cyclesPerSample = (GbaManager.cpuFreq << 5) / this.frequency; - } - } - - public int QueueSizeA - { - get { return this.soundQueue[0].Count; } - } - - public int QueueSizeB - { - get { return this.soundQueue[1].Count; } - } - - public int SamplesMixed - { - get - { - int value = this.soundBufferPos - this.lastSoundBufferPos; - if (value < 0) value += this.soundBuffer.Length; - return value; - } - } - #endregion - - #region Public Methods - public void GetSamples(short[] buffer, int length) - { - for (int i = 0; i < length; i++) - { - if (this.lastSoundBufferPos == this.soundBuffer.Length) - { - this.lastSoundBufferPos = 0; - } - buffer[i] = this.soundBuffer[this.lastSoundBufferPos++]; - } - } - - public void Mix(int cycles) - { - ushort soundCntH = Memory.ReadU16(this.memory.IORam, Memory.SOUNDCNT_H); - ushort soundCntX = Memory.ReadU16(this.memory.IORam, Memory.SOUNDCNT_X); - - cycles <<= 5; - cycles += this.leftover; - - if (cycles > 0) - { - // Precompute loop invariants - short directA = (short)(sbyte)(this.latchedA); - short directB = (short)(sbyte)(this.latchedB); - - if ((soundCntH & (1 << 2)) == 0) - { - directA >>= 1; - } - if ((soundCntH & (1 << 3)) == 0) - { - directB >>= 1; - } - - while (cycles > 0) - { - short l = 0, r = 0; - - cycles -= this.cyclesPerSample; - - // Mixing - if ((soundCntX & (1 << 7)) != 0) - { - if ((soundCntH & (1 << 8)) != 0) - { - r += directA; - } - if ((soundCntH & (1 << 9)) != 0) - { - l += directA; - } - if ((soundCntH & (1 << 12)) != 0) - { - r += directB; - } - if ((soundCntH & (1 << 13)) != 0) - { - l += directB; - } - } - - if (this.soundBufferPos == this.soundBuffer.Length) - { - this.soundBufferPos = 0; - } - - this.soundBuffer[this.soundBufferPos++] = (short)(l << 6); - this.soundBuffer[this.soundBufferPos++] = (short)(r << 6); - } - } - - this.leftover = cycles; - } - - public void ResetFifoA() - { - this.soundQueue[0].Clear(); - this.latchedA = 0; - } - - public void ResetFifoB() - { - this.soundQueue[1].Clear(); - this.latchedB = 0; - } - - public void IncrementFifoA() - { - for (int i = 0; i < 4; i++) - { - this.EnqueueDSoundSample(0, this.memory.IORam[Memory.FIFO_A_L + i]); - } - } - - public void IncrementFifoB() - { - for (int i = 0; i < 4; i++) - { - this.EnqueueDSoundSample(1, this.memory.IORam[Memory.FIFO_B_L + i]); - } - } - - public void DequeueA() - { - if (this.soundQueue[0].Count > 0) - { - this.latchedA = this.soundQueue[0].Dequeue(); - } - } - - public void DequeueB() - { - if (this.soundQueue[1].Count > 0) - { - this.latchedB = this.soundQueue[1].Dequeue(); - } - } - #endregion Public Methods - - private void EnqueueDSoundSample(int channel, byte sample) - { - if (this.soundQueue[channel].Count < 32) - { - this.soundQueue[channel].Enqueue(sample); - } - } - } -} diff --git a/attic/GarboDev/ThumbCore.cs b/attic/GarboDev/ThumbCore.cs deleted file mode 100644 index ca17f233c2..0000000000 --- a/attic/GarboDev/ThumbCore.cs +++ /dev/null @@ -1,981 +0,0 @@ -//#define ARM_DEBUG - -namespace GarboDev -{ - using System; - using System.Collections.Generic; - using System.Text; - - public class ThumbCore - { - private const int COND_EQ = 0; // Z set - private const int COND_NE = 1; // Z clear - private const int COND_CS = 2; // C set - private const int COND_CC = 3; // C clear - private const int COND_MI = 4; // N set - private const int COND_PL = 5; // N clear - private const int COND_VS = 6; // V set - private const int COND_VC = 7; // V clear - private const int COND_HI = 8; // C set and Z clear - private const int COND_LS = 9; // C clear or Z set - private const int COND_GE = 10; // N equals V - private const int COND_LT = 11; // N not equal to V - private const int COND_GT = 12; // Z clear AND (N equals V) - private const int COND_LE = 13; // Z set OR (N not equal to V) - private const int COND_AL = 14; // Always - private const int COND_NV = 15; // Never execute - - private const int OP_AND = 0x0; - private const int OP_EOR = 0x1; - private const int OP_LSL = 0x2; - private const int OP_LSR = 0x3; - private const int OP_ASR = 0x4; - private const int OP_ADC = 0x5; - private const int OP_SBC = 0x6; - private const int OP_ROR = 0x7; - private const int OP_TST = 0x8; - private const int OP_NEG = 0x9; - private const int OP_CMP = 0xA; - private const int OP_CMN = 0xB; - private const int OP_ORR = 0xC; - private const int OP_MUL = 0xD; - private const int OP_BIC = 0xE; - private const int OP_MVN = 0xF; - - private Arm7Processor parent; - private Memory memory; - private uint[] registers; - - // CPU flags - private uint zero, carry, negative, overflow; - private ushort curInstruction, instructionQueue; - - private delegate void ExecuteInstruction(); - private ExecuteInstruction[] NormalOps = null; - - public ThumbCore(Arm7Processor parent, Memory memory) - { - this.parent = parent; - this.memory = memory; - this.registers = this.parent.Registers; - - this.NormalOps = new ExecuteInstruction[256] - { - OpLslImm, OpLslImm, OpLslImm, OpLslImm, OpLslImm, OpLslImm, OpLslImm, OpLslImm, - OpLsrImm, OpLsrImm, OpLsrImm, OpLsrImm, OpLsrImm, OpLsrImm, OpLsrImm, OpLsrImm, - OpAsrImm, OpAsrImm, OpAsrImm, OpAsrImm, OpAsrImm, OpAsrImm, OpAsrImm, OpAsrImm, - OpAddRegReg, OpAddRegReg, OpSubRegReg, OpSubRegReg, OpAddRegImm, OpAddRegImm, OpSubRegImm, OpSubRegImm, - OpMovImm, OpMovImm, OpMovImm, OpMovImm, OpMovImm, OpMovImm, OpMovImm, OpMovImm, - OpCmpImm, OpCmpImm, OpCmpImm, OpCmpImm, OpCmpImm, OpCmpImm, OpCmpImm, OpCmpImm, - OpAddImm, OpAddImm, OpAddImm, OpAddImm, OpAddImm, OpAddImm, OpAddImm, OpAddImm, - OpSubImm, OpSubImm, OpSubImm, OpSubImm, OpSubImm, OpSubImm, OpSubImm, OpSubImm, - OpArith, OpArith, OpArith, OpArith, OpAddHi, OpCmpHi, OpMovHi, OpBx, - OpLdrPc, OpLdrPc, OpLdrPc, OpLdrPc, OpLdrPc, OpLdrPc, OpLdrPc, OpLdrPc, - OpStrReg, OpStrReg, OpStrhReg, OpStrhReg, OpStrbReg, OpStrbReg, OpLdrsbReg, OpLdrsbReg, - OpLdrReg, OpLdrReg, OpLdrhReg, OpLdrhReg, OpLdrbReg, OpLdrbReg, OpLdrshReg, OpLdrshReg, - OpStrImm, OpStrImm, OpStrImm, OpStrImm, OpStrImm, OpStrImm, OpStrImm, OpStrImm, - OpLdrImm, OpLdrImm, OpLdrImm, OpLdrImm, OpLdrImm, OpLdrImm, OpLdrImm, OpLdrImm, - OpStrbImm, OpStrbImm, OpStrbImm, OpStrbImm, OpStrbImm, OpStrbImm, OpStrbImm, OpStrbImm, - OpLdrbImm, OpLdrbImm, OpLdrbImm, OpLdrbImm, OpLdrbImm, OpLdrbImm, OpLdrbImm, OpLdrbImm, - OpStrhImm, OpStrhImm, OpStrhImm, OpStrhImm, OpStrhImm, OpStrhImm, OpStrhImm, OpStrhImm, - OpLdrhImm, OpLdrhImm, OpLdrhImm, OpLdrhImm, OpLdrhImm, OpLdrhImm, OpLdrhImm, OpLdrhImm, - OpStrSp, OpStrSp, OpStrSp, OpStrSp, OpStrSp, OpStrSp, OpStrSp, OpStrSp, - OpLdrSp, OpLdrSp, OpLdrSp, OpLdrSp, OpLdrSp, OpLdrSp, OpLdrSp, OpLdrSp, - OpAddPc, OpAddPc, OpAddPc, OpAddPc, OpAddPc, OpAddPc, OpAddPc, OpAddPc, - OpAddSp, OpAddSp, OpAddSp, OpAddSp, OpAddSp, OpAddSp, OpAddSp, OpAddSp, - OpSubSp, OpUnd, OpUnd, OpUnd, OpPush, OpPushLr, OpUnd, OpUnd, - OpUnd, OpUnd, OpUnd, OpUnd, OpPop, OpPopPc, OpUnd, OpUnd, - OpStmia, OpStmia, OpStmia, OpStmia, OpStmia, OpStmia, OpStmia, OpStmia, - OpLdmia, OpLdmia, OpLdmia, OpLdmia, OpLdmia, OpLdmia, OpLdmia, OpLdmia, - OpBCond, OpBCond, OpBCond, OpBCond, OpBCond, OpBCond, OpBCond, OpBCond, - OpBCond, OpBCond, OpBCond, OpBCond, OpBCond, OpBCond, OpUnd, OpSwi, - OpB, OpB, OpB, OpB, OpB, OpB, OpB, OpB, - OpUnd, OpUnd, OpUnd, OpUnd, OpUnd, OpUnd, OpUnd, OpUnd, - OpBl1, OpBl1, OpBl1, OpBl1, OpBl1, OpBl1, OpBl1, OpBl1, - OpBl2, OpBl2, OpBl2, OpBl2, OpBl2, OpBl2, OpBl2, OpBl2 - }; - } - - public void BeginExecution() - { - this.FlushQueue(); - } - - public void Step() - { - this.UnpackFlags(); - - this.curInstruction = this.instructionQueue; - this.instructionQueue = this.memory.ReadU16(registers[15]); - registers[15] += 2; - - // Execute the instruction - this.NormalOps[this.curInstruction >> 8](); - - this.parent.Cycles -= this.memory.WaitCycles; - - if ((this.parent.CPSR & Arm7Processor.T_MASK) != Arm7Processor.T_MASK) - { - if ((this.curInstruction >> 8) != 0xDF) this.parent.ReloadQueue(); - } - - this.PackFlags(); - } - - public void Execute() - { - this.UnpackFlags(); - - while (this.parent.Cycles > 0) - { - this.curInstruction = this.instructionQueue; - this.instructionQueue = this.memory.ReadU16(registers[15]); - registers[15] += 2; - - // Execute the instruction - this.NormalOps[this.curInstruction >> 8](); - - this.parent.Cycles -= this.memory.WaitCycles; - - if ((this.parent.CPSR & Arm7Processor.T_MASK) != Arm7Processor.T_MASK) - { - if ((this.curInstruction >> 8) != 0xDF) this.parent.ReloadQueue(); - break; - } - - // Check the current PC -#if ARM_DEBUG - if (this.parent.Breakpoints.ContainsKey(registers[15] - 2U)) - { - this.parent.BreakpointHit = true; - break; - } -#endif - } - - this.PackFlags(); - } - - #region Flag helpers - public void OverflowCarryAdd(uint a, uint b, uint r) - { - overflow = ((a & b & ~r) | (~a & ~b & r)) >> 31; - carry = ((a & b) | (a & ~r) | (b & ~r)) >> 31; - } - - public void OverflowCarrySub(uint a, uint b, uint r) - { - overflow = ((a & ~b & ~r) | (~a & b & r)) >> 31; - carry = ((a & ~b) | (a & ~r) | (~b & ~r)) >> 31; - } - #endregion - - #region Opcodes - private void OpLslImm() - { - // 0x00 - 0x07 - // lsl rd, rm, #immed - int rd = this.curInstruction & 0x7; - int rm = (this.curInstruction >> 3) & 0x7; - int immed = (this.curInstruction >> 6) & 0x1F; - - if (immed == 0) - { - registers[rd] = registers[rm]; - } else - { - carry = (registers[rm] >> (32 - immed)) & 0x1; - registers[rd] = registers[rm] << immed; - } - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpLsrImm() - { - // 0x08 - 0x0F - // lsr rd, rm, #immed - int rd = this.curInstruction & 0x7; - int rm = (this.curInstruction >> 3) & 0x7; - int immed = (this.curInstruction >> 6) & 0x1F; - - if (immed == 0) - { - carry = registers[rm] >> 31; - registers[rd] = 0; - } - else - { - carry = (registers[rm] >> (immed - 1)) & 0x1; - registers[rd] = registers[rm] >> immed; - } - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpAsrImm() - { - // asr rd, rm, #immed - int rd = this.curInstruction & 0x7; - int rm = (this.curInstruction >> 3) & 0x7; - int immed = (this.curInstruction >> 6) & 0x1F; - - if (immed == 0) - { - carry = registers[rm] >> 31; - if (carry == 1) registers[rd] = 0xFFFFFFFF; - else registers[rd] = 0; - } - else - { - carry = (registers[rm] >> (immed - 1)) & 0x1; - registers[rd] = (uint)(((int)registers[rm]) >> immed); - } - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpAddRegReg() - { - // add rd, rn, rm - int rd = this.curInstruction & 0x7; - int rn = (this.curInstruction >> 3) & 0x7; - int rm = (this.curInstruction >> 6) & 0x7; - - uint orn = registers[rn]; - uint orm = registers[rm]; - - registers[rd] = orn + orm; - - this.OverflowCarryAdd(orn, orm, registers[rd]); - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpSubRegReg() - { - // sub rd, rn, rm - int rd = this.curInstruction & 0x7; - int rn = (this.curInstruction >> 3) & 0x7; - int rm = (this.curInstruction >> 6) & 0x7; - - uint orn = registers[rn]; - uint orm = registers[rm]; - - registers[rd] = orn - orm; - - this.OverflowCarrySub(orn, orm, registers[rd]); - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpAddRegImm() - { - // add rd, rn, #immed - int rd = this.curInstruction & 0x7; - int rn = (this.curInstruction >> 3) & 0x7; - uint immed = (uint)((this.curInstruction >> 6) & 0x7); - - uint orn = registers[rn]; - - registers[rd] = orn + immed; - - this.OverflowCarryAdd(orn, immed, registers[rd]); - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpSubRegImm() - { - // sub rd, rn, #immed - int rd = this.curInstruction & 0x7; - int rn = (this.curInstruction >> 3) & 0x7; - uint immed = (uint)((this.curInstruction >> 6) & 0x7); - - uint orn = registers[rn]; - - registers[rd] = orn - immed; - - this.OverflowCarrySub(orn, immed, registers[rd]); - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpMovImm() - { - // mov rd, #immed - int rd = (this.curInstruction >> 8) & 0x7; - - registers[rd] = (uint)(this.curInstruction & 0xFF); - - negative = 0; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpCmpImm() - { - // cmp rn, #immed - int rn = (this.curInstruction >> 8) & 0x7; - - uint alu = registers[rn] - (uint)(this.curInstruction & 0xFF); - - this.OverflowCarrySub(registers[rn], (uint)(this.curInstruction & 0xFF), alu); - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - } - - private void OpAddImm() - { - // add rd, #immed - int rd = (this.curInstruction >> 8) & 0x7; - - uint ord = registers[rd]; - - registers[rd] += (uint)(this.curInstruction & 0xFF); - - this.OverflowCarryAdd(ord, (uint)(this.curInstruction & 0xFF), registers[rd]); - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpSubImm() - { - // sub rd, #immed - int rd = (this.curInstruction >> 8) & 0x7; - - uint ord = registers[rd]; - - registers[rd] -= (uint)(this.curInstruction & 0xFF); - - this.OverflowCarrySub(ord, (uint)(this.curInstruction & 0xFF), registers[rd]); - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - } - - private void OpArith() - { - int rd = this.curInstruction & 0x7; - uint rn = registers[(this.curInstruction >> 3) & 0x7]; - - uint orig, alu; - int shiftAmt; - - switch ((this.curInstruction >> 6) & 0xF) - { - case OP_ADC: - orig = registers[rd]; - registers[rd] += rn + carry; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarryAdd(orig, rn, registers[rd]); - break; - - case OP_AND: - registers[rd] &= rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_ASR: - shiftAmt = (int)(rn & 0xFF); - if (shiftAmt == 0) - { - // Do nothing - } - else if (shiftAmt < 32) - { - carry = (registers[rd] >> (shiftAmt - 1)) & 0x1; - registers[rd] = (uint)(((int)registers[rd]) >> shiftAmt); - } - else - { - carry = (registers[rd] >> 31) & 1; - if (carry == 1) registers[rd] = 0xFFFFFFFF; - else registers[rd] = 0; - } - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_BIC: - registers[rd] &= ~rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_CMN: - alu = registers[rd] + rn; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarryAdd(registers[rd], rn, alu); - break; - - case OP_CMP: - alu = registers[rd] - rn; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(registers[rd], rn, alu); - break; - - case OP_EOR: - registers[rd] ^= rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_LSL: - shiftAmt = (int)(rn & 0xFF); - if (shiftAmt == 0) - { - // Do nothing - } - else if (shiftAmt < 32) - { - carry = (registers[rd] >> (32 - shiftAmt)) & 0x1; - registers[rd] <<= shiftAmt; - } - else if (shiftAmt == 32) - { - carry = registers[rd] & 0x1; - registers[rd] = 0; - } - else - { - carry = 0; - registers[rd] = 0; - } - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_LSR: - shiftAmt = (int)(rn & 0xFF); - if (shiftAmt == 0) - { - // Do nothing - } - else if (shiftAmt < 32) - { - carry = (registers[rd] >> (shiftAmt - 1)) & 0x1; - registers[rd] >>= shiftAmt; - } - else if (shiftAmt == 32) - { - carry = (registers[rd] >> 31) & 0x1; - registers[rd] = 0; - } - else - { - carry = 0; - registers[rd] = 0; - } - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_MUL: - int mulCycles = 4; - // Multiply cycle calculations - if ((rn & 0xFFFFFF00) == 0 || (rn & 0xFFFFFF00) == 0xFFFFFF00) - { - mulCycles = 1; - } - else if ((rn & 0xFFFF0000) == 0 || (rn & 0xFFFF0000) == 0xFFFF0000) - { - mulCycles = 2; - } - else if ((rn & 0xFF000000) == 0 || (rn & 0xFF000000) == 0xFF000000) - { - mulCycles = 3; - } - - this.parent.Cycles -= mulCycles; - - registers[rd] *= rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_MVN: - registers[rd] = ~rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_NEG: - registers[rd] = 0 - rn; - - this.OverflowCarrySub(0, rn, registers[rd]); - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_ORR: - registers[rd] |= rn; - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_ROR: - shiftAmt = (int)(rn & 0xFF); - if (shiftAmt == 0) - { - // Do nothing - } - else if ((shiftAmt & 0x1F) == 0) - { - carry = registers[rd] >> 31; - } - else - { - shiftAmt &= 0x1F; - carry = (registers[rd] >> (shiftAmt - 1)) & 0x1; - registers[rd] = (registers[rd] >> shiftAmt) | (registers[rd] << (32 - shiftAmt)); - } - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - break; - - case OP_SBC: - orig = registers[rd]; - registers[rd] = (registers[rd] - rn) - (1U - carry); - - negative = registers[rd] >> 31; - zero = registers[rd] == 0 ? 1U : 0U; - this.OverflowCarrySub(orig, rn, registers[rd]); - break; - - case OP_TST: - alu = registers[rd] & rn; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - break; - - default: - throw new Exception("The coder screwed up on the thumb alu op..."); - } - } - - private void OpAddHi() - { - int rd = ((this.curInstruction & (1 << 7)) >> 4) | (this.curInstruction & 0x7); - int rm = (this.curInstruction >> 3) & 0xF; - - registers[rd] += registers[rm]; - - if (rd == 15) - { - registers[rd] &= ~1U; - this.FlushQueue(); - } - } - - private void OpCmpHi() - { - int rd = ((this.curInstruction & (1 << 7)) >> 4) | (this.curInstruction & 0x7); - int rm = (this.curInstruction >> 3) & 0xF; - - uint alu = registers[rd] - registers[rm]; - - negative = alu >> 31; - zero = alu == 0 ? 1U : 0U; - this.OverflowCarrySub(registers[rd], registers[rm], alu); - } - - private void OpMovHi() - { - int rd = ((this.curInstruction & (1 << 7)) >> 4) | (this.curInstruction & 0x7); - int rm = (this.curInstruction >> 3) & 0xF; - - registers[rd] = registers[rm]; - - if (rd == 15) - { - registers[rd] &= ~1U; - this.FlushQueue(); - } - } - - private void OpBx() - { - int rm = (this.curInstruction >> 3) & 0xf; - - this.PackFlags(); - - this.parent.CPSR &= ~Arm7Processor.T_MASK; - this.parent.CPSR |= (registers[rm] & 1) << Arm7Processor.T_BIT; - - registers[15] = registers[rm] & (~1U); - - this.UnpackFlags(); - - // Check for branch back to Arm Mode - if ((this.parent.CPSR & Arm7Processor.T_MASK) != Arm7Processor.T_MASK) - { - return; - } - - this.FlushQueue(); - } - - private void OpLdrPc() - { - int rd = (this.curInstruction >> 8) & 0x7; - - registers[rd] = this.memory.ReadU32((registers[15] & ~2U) + (uint)((this.curInstruction & 0xFF) * 4)); - - this.parent.Cycles--; - } - - private void OpStrReg() - { - this.memory.WriteU32(registers[(this.curInstruction >> 3) & 0x7] + registers[(this.curInstruction >> 6) & 0x7], - registers[this.curInstruction & 0x7]); - } - - private void OpStrhReg() - { - this.memory.WriteU16(registers[(this.curInstruction >> 3) & 0x7] + registers[(this.curInstruction >> 6) & 0x7], - (ushort)(registers[this.curInstruction & 0x7] & 0xFFFF)); - } - - private void OpStrbReg() - { - this.memory.WriteU8(registers[(this.curInstruction >> 3) & 0x7] + registers[(this.curInstruction >> 6) & 0x7], - (byte)(registers[this.curInstruction & 0x7] & 0xFF)); - } - - private void OpLdrsbReg() - { - registers[this.curInstruction & 0x7] = - this.memory.ReadU8(registers[(this.curInstruction >> 3) & 0x7] + registers[(this.curInstruction >> 6) & 0x7]); - - if ((registers[this.curInstruction & 0x7] & (1 << 7)) != 0) - { - registers[this.curInstruction & 0x7] |= 0xFFFFFF00; - } - - this.parent.Cycles--; - } - - private void OpLdrReg() - { - registers[this.curInstruction & 0x7] = - this.memory.ReadU32(registers[(this.curInstruction >> 3) & 0x7] + registers[(this.curInstruction >> 6) & 0x7]); - - this.parent.Cycles--; - } - - private void OpLdrhReg() - { - registers[this.curInstruction & 0x7] = - this.memory.ReadU16(registers[(this.curInstruction >> 3) & 0x7] + registers[(this.curInstruction >> 6) & 0x7]); - - this.parent.Cycles--; - } - - private void OpLdrbReg() - { - registers[this.curInstruction & 0x7] = - this.memory.ReadU8(registers[(this.curInstruction >> 3) & 0x7] + registers[(this.curInstruction >> 6) & 0x7]); - - this.parent.Cycles--; - } - - private void OpLdrshReg() - { - registers[this.curInstruction & 0x7] = - this.memory.ReadU16(registers[(this.curInstruction >> 3) & 0x7] + registers[(this.curInstruction >> 6) & 0x7]); - - if ((registers[this.curInstruction & 0x7] & (1 << 15)) != 0) - { - registers[this.curInstruction & 0x7] |= 0xFFFF0000; - } - - this.parent.Cycles--; - } - - private void OpStrImm() - { - this.memory.WriteU32(registers[(this.curInstruction >> 3) & 0x7] + (uint)(((this.curInstruction >> 6) & 0x1F) * 4), - registers[this.curInstruction & 0x7]); - } - - private void OpLdrImm() - { - registers[this.curInstruction & 0x7] = - this.memory.ReadU32(registers[(this.curInstruction >> 3) & 0x7] + (uint)(((this.curInstruction >> 6) & 0x1F) * 4)); - - this.parent.Cycles--; - } - - private void OpStrbImm() - { - this.memory.WriteU8(registers[(this.curInstruction >> 3) & 0x7] + (uint)((this.curInstruction >> 6) & 0x1F), - (byte)(registers[this.curInstruction & 0x7] & 0xFF)); - } - - private void OpLdrbImm() - { - registers[this.curInstruction & 0x7] = - this.memory.ReadU8(registers[(this.curInstruction >> 3) & 0x7] + (uint)((this.curInstruction >> 6) & 0x1F)); - - this.parent.Cycles--; - } - - private void OpStrhImm() - { - this.memory.WriteU16(registers[(this.curInstruction >> 3) & 0x7] + (uint)(((this.curInstruction >> 6) & 0x1F) * 2), - (ushort)(registers[this.curInstruction & 0x7] & 0xFFFF)); - } - - private void OpLdrhImm() - { - registers[this.curInstruction & 0x7] = - this.memory.ReadU16(registers[(this.curInstruction >> 3) & 0x7] + (uint)(((this.curInstruction >> 6) & 0x1F) * 2)); - - this.parent.Cycles--; - } - - private void OpStrSp() - { - this.memory.WriteU32(registers[13] + (uint)((this.curInstruction & 0xFF) * 4), - registers[(this.curInstruction >> 8) & 0x7]); - } - - private void OpLdrSp() - { - registers[(this.curInstruction >> 8) & 0x7] = - this.memory.ReadU32(registers[13] + (uint)((this.curInstruction & 0xFF) * 4)); - } - - private void OpAddPc() - { - registers[(this.curInstruction >> 8) & 0x7] = - (registers[15] & ~2U) + (uint)((this.curInstruction & 0xFF) * 4); - } - - private void OpAddSp() - { - registers[(this.curInstruction >> 8) & 0x7] = - registers[13] + (uint)((this.curInstruction & 0xFF) * 4); - } - - private void OpSubSp() - { - if ((this.curInstruction & (1 << 7)) != 0) - registers[13] -= (uint)((this.curInstruction & 0x7F) * 4); - else - registers[13] += (uint)((this.curInstruction & 0x7F) * 4); - } - - private void OpPush() - { - for (int i = 7; i >= 0; i--) - { - if (((this.curInstruction >> i) & 1) != 0) - { - registers[13] -= 4; - this.memory.WriteU32(registers[13], registers[i]); - } - } - } - - private void OpPushLr() - { - registers[13] -= 4; - this.memory.WriteU32(registers[13], registers[14]); - - for (int i = 7; i >= 0; i--) - { - if (((this.curInstruction >> i) & 1) != 0) - { - registers[13] -= 4; - this.memory.WriteU32(registers[13], registers[i]); - } - } - } - - private void OpPop() - { - for (int i = 0; i < 8; i++) - { - if (((this.curInstruction >> i) & 1) != 0) - { - registers[i] = this.memory.ReadU32(registers[13]); - registers[13] += 4; - } - } - - this.parent.Cycles--; - } - - private void OpPopPc() - { - for (int i = 0; i < 8; i++) - { - if (((this.curInstruction >> i) & 1) != 0) - { - registers[i] = this.memory.ReadU32(registers[13]); - registers[13] += 4; - } - } - - registers[15] = this.memory.ReadU32(registers[13]) & (~1U); - registers[13] += 4; - - // ARM9 check here - - this.FlushQueue(); - - this.parent.Cycles--; - } - - private void OpStmia() - { - int rn = (this.curInstruction >> 8) & 0x7; - - for (int i = 0; i < 8; i++) - { - if (((this.curInstruction >> i) & 1) != 0) - { - this.memory.WriteU32(registers[rn] & (~3U), registers[i]); - registers[rn] += 4; - } - } - } - - private void OpLdmia() - { - int rn = (this.curInstruction >> 8) & 0x7; - - uint address = registers[rn]; - - for (int i = 0; i < 8; i++) - { - if (((this.curInstruction >> i) & 1) != 0) - { - registers[i] = this.memory.ReadU32Aligned(address & (~3U)); - address += 4; - } - } - - if (((this.curInstruction >> rn) & 1) == 0) - { - registers[rn] = address; - } - } - - private void OpBCond() - { - uint cond = 0; - switch ((this.curInstruction >> 8) & 0xF) - { - case COND_AL: cond = 1; break; - case COND_EQ: cond = zero; break; - case COND_NE: cond = 1 - zero; break; - case COND_CS: cond = carry; break; - case COND_CC: cond = 1 - carry; break; - case COND_MI: cond = negative; break; - case COND_PL: cond = 1 - negative; break; - case COND_VS: cond = overflow; break; - case COND_VC: cond = 1 - overflow; break; - case COND_HI: cond = carry & (1 - zero); break; - case COND_LS: cond = (1 - carry) | zero; break; - case COND_GE: cond = (1 - negative) ^ overflow; break; - case COND_LT: cond = negative ^ overflow; break; - case COND_GT: cond = (1 - zero) & (negative ^ (1 - overflow)); break; - case COND_LE: cond = (negative ^ overflow) | zero; break; - } - - if (cond == 1) - { - uint offset = (uint)(this.curInstruction & 0xFF); - if ((offset & (1 << 7)) != 0) offset |= 0xFFFFFF00; - - registers[15] += offset << 1; - - this.FlushQueue(); - } - } - - private void OpSwi() - { - registers[15] -= 4U; - this.parent.EnterException(Arm7Processor.SVC, 0x8, false, false); - } - - private void OpB() - { - uint offset = (uint)(this.curInstruction & 0x7FF); - if ((offset & (1 << 10)) != 0) offset |= 0xFFFFF800; - - registers[15] += offset << 1; - - this.FlushQueue(); - } - - private void OpBl1() - { - uint offset = (uint)(this.curInstruction & 0x7FF); - if ((offset & (1 << 10)) != 0) offset |= 0xFFFFF800; - - registers[14] = registers[15] + (offset << 12); - } - - private void OpBl2() - { - uint tmp = registers[15]; - registers[15] = registers[14] + (uint)((this.curInstruction & 0x7FF) << 1); - registers[14] = (tmp - 2U) | 1; - - this.FlushQueue(); - } - - private void OpUnd() - { - throw new Exception("Unknown opcode"); - } - #endregion - - private void PackFlags() - { - this.parent.CPSR &= 0x0FFFFFFF; - this.parent.CPSR |= this.negative << Arm7Processor.N_BIT; - this.parent.CPSR |= this.zero << Arm7Processor.Z_BIT; - this.parent.CPSR |= this.carry << Arm7Processor.C_BIT; - this.parent.CPSR |= this.overflow << Arm7Processor.V_BIT; - } - - private void UnpackFlags() - { - this.negative = (this.parent.CPSR >> Arm7Processor.N_BIT) & 1; - this.zero = (this.parent.CPSR >> Arm7Processor.Z_BIT) & 1; - this.carry = (this.parent.CPSR >> Arm7Processor.C_BIT) & 1; - this.overflow = (this.parent.CPSR >> Arm7Processor.V_BIT) & 1; - } - - private void FlushQueue() - { - this.instructionQueue = this.memory.ReadU16(registers[15]); - registers[15] += 2; - } - } -} diff --git a/attic/GarboDev/VideoManager.cs b/attic/GarboDev/VideoManager.cs deleted file mode 100644 index 328702d8fa..0000000000 --- a/attic/GarboDev/VideoManager.cs +++ /dev/null @@ -1,164 +0,0 @@ -namespace GarboDev -{ - public class VideoManager - { - public delegate void OnPresent(uint[] data); - - private Memory memory = null; - private IRenderer renderer = null; - private OnPresent presenter; - private GbaManager gbaManager; - private int curLine; - - public Memory Memory - { - set{ this.memory = value; } - } - - public IRenderer Renderer - { - set - { - this.renderer = value; - this.renderer.Memory = this.memory; - } - } - - public OnPresent Presenter - { - set { this.presenter = value; } - } - - public VideoManager(GbaManager gbaManager) - { - this.gbaManager = gbaManager; - } - - public void Reset() - { - this.curLine = 0; - - this.renderer.Memory = memory; - this.renderer.Reset(); - } - - private void EnterVBlank(Arm7Processor processor) - { - ushort dispstat = Memory.ReadU16(this.memory.IORam, Memory.DISPSTAT); - dispstat |= 1; - Memory.WriteU16(this.memory.IORam, Memory.DISPSTAT, dispstat); - - // Render the frame - this.gbaManager.FramesRendered++; - this.presenter(this.renderer.ShowFrame()); - - if ((dispstat & (1 << 3)) != 0) - { - // Fire the vblank irq - processor.RequestIrq(0); - } - - // Check for DMA triggers - this.memory.VBlankDma(); - } - - private void LeaveVBlank(Arm7Processor processor) - { - ushort dispstat = Memory.ReadU16(this.memory.IORam, Memory.DISPSTAT); - dispstat &= 0xFFFE; - Memory.WriteU16(this.memory.IORam, Memory.DISPSTAT, dispstat); - - processor.UpdateKeyState(); - - // Update the rot/scale values - this.memory.Bgx[0] = (int)Memory.ReadU32(this.memory.IORam, Memory.BG2X_L); - this.memory.Bgx[1] = (int)Memory.ReadU32(this.memory.IORam, Memory.BG3X_L); - this.memory.Bgy[0] = (int)Memory.ReadU32(this.memory.IORam, Memory.BG2Y_L); - this.memory.Bgy[1] = (int)Memory.ReadU32(this.memory.IORam, Memory.BG3Y_L); - } - - public void EnterHBlank(Arm7Processor processor) - { - ushort dispstat = Memory.ReadU16(this.memory.IORam, Memory.DISPSTAT); - dispstat |= 1 << 1; - Memory.WriteU16(this.memory.IORam, Memory.DISPSTAT, dispstat); - - // Advance the bgx registers - for (int bg = 0; bg <= 1; bg++) - { - short dmx = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PB + (uint)bg * 0x10); - short dmy = (short)Memory.ReadU16(this.memory.IORam, Memory.BG2PD + (uint)bg * 0x10); - this.memory.Bgx[bg] += dmx; - this.memory.Bgy[bg] += dmy; - } - - if (this.curLine < 160) - { - this.memory.HBlankDma(); - - // Trigger hblank irq - if ((dispstat & (1 << 4)) != 0) - { - processor.RequestIrq(1); - } - } - } - - /// - /// - /// - /// - /// true if end of frame - public bool LeaveHBlank(Arm7Processor processor) - { - bool ret = false; - ushort dispstat = Memory.ReadU16(this.memory.IORam, Memory.DISPSTAT); - dispstat &= 0xFFF9; - Memory.WriteU16(this.memory.IORam, Memory.DISPSTAT, dispstat); - - // Move to the next line - this.curLine++; - - if (this.curLine >= 228) - { - // Start again at the beginning - this.curLine = 0; - } - - // Update registers - Memory.WriteU16(this.memory.IORam, Memory.VCOUNT, (ushort)this.curLine); - - // Check for vblank - if (this.curLine == 160) - { - this.EnterVBlank(processor); - ret = true; - } - else if (this.curLine == 0) - { - this.LeaveVBlank(processor); - } - - // Check y-line trigger - if (((dispstat >> 8) & 0xff) == this.curLine) - { - dispstat = (ushort)(Memory.ReadU16(this.memory.IORam, Memory.DISPSTAT) | (1 << 2)); - Memory.WriteU16(this.memory.IORam, Memory.DISPSTAT, dispstat); - - if ((dispstat & (1 << 5)) != 0) - { - processor.RequestIrq(2); - } - } - return ret; - } - - public void RenderLine() - { - if (this.curLine < 160) - { - this.renderer.RenderLine(this.curLine); - } - } - } -} \ No newline at end of file diff --git a/attic/GarboDev/readme.txt b/attic/GarboDev/readme.txt deleted file mode 100644 index 9aec52234e..0000000000 --- a/attic/GarboDev/readme.txt +++ /dev/null @@ -1,7 +0,0 @@ -garbodev with a quick iemulator binding. license uncertain. - -basic functionality works (gets ingame on a number of commercial titles). - -no GB classic sound channels. -no savestates. -lots of things not hooked up (saveram, etc) diff --git a/libmeteor/Makefile b/libmeteor/Makefile deleted file mode 100644 index 2029f11b3d..0000000000 --- a/libmeteor/Makefile +++ /dev/null @@ -1,110 +0,0 @@ -# this was modified at one point so that it would compile in our bizhawk project, but isn't in -# use at the moment. tread carefully - -ifeq ($(platform),) -platform = unix -ifeq ($(shell uname -a),) - platform = win -else ifneq ($(findstring MINGW,$(shell uname -a)),) - platform = win -else ifneq ($(findstring Darwin,$(shell uname -a)),) - platform = osx -else ifneq ($(findstring win,$(shell uname -a)),) - platform = win -endif -endif - -ifeq ($(platform), unix) - TARGET := libmeteor.so - fpic := -fPIC - SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined -else ifeq ($(platform), osx) - TARGET := libmeteor.dylib - fpic := -fPIC - SHARED := -dynamiclib -else - TARGET := libmeteor.dll - CXX = g++ -# SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T -Wl,--no-undefined - SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--no-undefined - CXXFLAGS += -DNO_MEMMEM -endif - -#__LIBRETRO__ enables a slightly different saveram mechanism that doesn't seem to serve any useful purpose? -#CXXFLAGS += -Wall -pedantic -I. -I../ameteor/include -pipe -D__LIBRETRO__ -Wno-parentheses -fno-exceptions -fno-rtti -CXXFLAGS += -Wall -pedantic -I. -Iinclude -pipe -DX86_ASM -Wno-parentheses -fno-exceptions -fno-rtti - -ifeq ($(DEBUG), 1) - CFLAGS += -O0 -g - CXXFLAGS += -O0 -g -else - CFLAGS += -O3 - CXXFLAGS += -O3 -endif - -#SRCDIR := ../ameteor/source -SRCDIR := ./source - -SOURCES := \ - $(SRCDIR)/audio/dsound.cpp \ - $(SRCDIR)/audio/sound1.cpp \ - $(SRCDIR)/audio/sound2.cpp \ - $(SRCDIR)/audio/sound4.cpp \ - $(SRCDIR)/audio/speaker.cpp \ - $(SRCDIR)/disassembler/argimmediate.cpp \ - $(SRCDIR)/disassembler/argmulregisters.cpp \ - $(SRCDIR)/disassembler/argpsr.cpp \ - $(SRCDIR)/disassembler/argregister.cpp \ - $(SRCDIR)/disassembler/argrelative.cpp \ - $(SRCDIR)/disassembler/argshift.cpp \ - $(SRCDIR)/disassembler/arguimmediate.cpp \ - $(SRCDIR)/disassembler/arguments.cpp \ - $(SRCDIR)/disassembler/instruction.cpp \ - $(SRCDIR)/graphics/bglayer.cpp \ - $(SRCDIR)/graphics/object.cpp \ - $(SRCDIR)/graphics/objects.cpp \ - $(SRCDIR)/graphics/renderer.cpp \ - $(SRCDIR)/graphics/screen.cpp \ - $(SRCDIR)/ameteor.cpp \ - $(SRCDIR)/bios.cpp \ - $(SRCDIR)/clock.cpp \ - $(SRCDIR)/cpu.cpp \ - $(SRCDIR)/debug.cpp \ - $(SRCDIR)/dma.cpp \ - $(SRCDIR)/eeprom.cpp \ - $(SRCDIR)/flash.cpp \ - $(SRCDIR)/cartmem.cpp \ - $(SRCDIR)/interpreter.cpp \ - $(SRCDIR)/interpreter_arm.cpp \ - $(SRCDIR)/interpreter_thumb.cpp \ - $(SRCDIR)/io.cpp \ - $(SRCDIR)/keypad.cpp \ - $(SRCDIR)/lcd.cpp \ - $(SRCDIR)/memory.cpp \ - $(SRCDIR)/sound.cpp \ - $(SRCDIR)/sram.cpp \ - $(SRCDIR)/timer.cpp \ - cinterface.cpp -# video.cpp \ -# audio.cpp \ -# input.cpp \ -# libretro.cpp - -OBJ := $(SOURCES:.cpp=.o) - -all: $(TARGET) - -$(TARGET): $(OBJ) - @$(CXX) -o $@ $^ $(SHARED) $(LDFLAGS) $(LIBS) - @echo LD $(notdir $@) - -%.o: %.cpp - @$(CXX) -o $@ -c $< $(CXXFLAGS) $(fpic) - @echo CXX $(notdir $<) - -clean: - rm -f $(TARGET) - rm -f $(OBJ) - -.PHONY: clean - diff --git a/libmeteor/cinterface.cpp b/libmeteor/cinterface.cpp deleted file mode 100644 index 7ec62ef343..0000000000 --- a/libmeteor/cinterface.cpp +++ /dev/null @@ -1,246 +0,0 @@ -#include "ameteor.hpp" -#include "ameteor/cartmem.hpp" -#include "source/debug.hpp" -#include - -#define EXPORT extern "C" __declspec(dllexport) - -void (*messagecallback)(const char *msg, int abort) = NULL; - -EXPORT void libmeteor_setmessagecallback(void (*callback)(const char *msg, int abort)) -{ - messagecallback = callback; - print_bizhawk("libmeteor message stream operational."); -} - -void print_bizhawk(const char *msg) -{ - if (messagecallback) - messagecallback(msg, 0); -} -void print_bizhawk(std::string &msg) -{ - if (messagecallback) - messagecallback(msg.c_str(), 0); -} -void abort_bizhawk(const char *msg) -{ - if (messagecallback) - messagecallback(msg, 1); - AMeteor::Stop(); // makes it easy to pick apart what happened -} - -uint16_t (*keycallback)() = NULL; - -void keyupdate_bizhawk() -{ - if (keycallback) - AMeteor::_keypad.SetPadState(keycallback() ^ 0x3FF); -} - -EXPORT void libmeteor_setkeycallback(uint16_t (*callback)()) -{ - keycallback = callback; -} - -bool traceenabled = false; -void (*tracecallback)(const char *msg) = NULL; - -EXPORT void libmeteor_settracecallback(void (*callback)(const char*msg)) -{ - tracecallback = callback; - traceenabled = tracecallback != NULL; -} - -void trace_bizhawk(std::string msg) -{ - if (tracecallback) - tracecallback(msg.c_str()); -} - -EXPORT void libmeteor_hardreset() -{ - AMeteor::Reset(AMeteor::UNIT_ALL ^ (AMeteor::UNIT_MEMORY_BIOS | AMeteor::UNIT_MEMORY_ROM)); -} - -uint32_t *videobuff; - -void videocb(const uint16_t *frame) -{ - uint32_t *dest = videobuff; - const uint16_t *src = frame; - for (int i = 0; i < 240 * 160; i++, src++, dest++) - { - uint16_t c = *src; - uint16_t b = c >> 10 & 31; - uint16_t g = c >> 5 & 31; - uint16_t r = c & 31; - b = b << 3 | b >> 2; - g = g << 3 | g >> 2; - r = r << 3 | r >> 2; - *dest = b | g << 8 | r << 16 | 0xff000000; - } - AMeteor::Stop(); // to the end of frame only -} - -int16_t *soundbuff; -int16_t *soundbuffcur; -int16_t *soundbuffend; - -void soundcb(const int16_t *samples) -{ - if (soundbuffcur < soundbuffend) - { - *soundbuffcur++ = *samples++; - *soundbuffcur++ = *samples++; - } -} - -EXPORT unsigned libmeteor_emptysound() -{ - unsigned ret = (soundbuffcur - soundbuff) * sizeof(int16_t); - soundbuffcur = soundbuff; - return ret; -} - -EXPORT int libmeteor_setbuffers(uint32_t *vid, unsigned vidlen, int16_t *aud, unsigned audlen) -{ - if (vidlen < 240 * 160 * sizeof(uint32_t)) - return 0; - if (audlen < 4 || audlen % 4 != 0) - return 0; - videobuff = vid; - soundbuff = aud; - soundbuffend = soundbuff + audlen / sizeof(int16_t); - libmeteor_emptysound(); - return 1; -} - -EXPORT void libmeteor_init() -{ - static bool first = true; - if (first) - { - AMeteor::_lcd.GetScreen().GetRenderer().SetFrameSlot(syg::ptr_fun(videocb)); - AMeteor::_sound.GetSpeaker().SetFrameSlot(syg::ptr_fun(soundcb)); - first = false; - } -} - -EXPORT void libmeteor_frameadvance() -{ - AMeteor::Run(10000000); -} - -EXPORT void libmeteor_loadrom(const void *data, unsigned size) -{ - AMeteor::_memory.LoadRom((const uint8_t*)data, size); -} - -EXPORT void libmeteor_loadbios(const void *data, unsigned size) -{ - AMeteor::_memory.LoadBios((const uint8_t*)data, size); -} - -EXPORT uint8_t *libmeteor_getmemoryarea(int which) -{ - if (which < 7) - return AMeteor::_memory.GetMemoryArea(which); - else if (which == 7) - return AMeteor::_io.GetIoPointer(); - else - return NULL; -} - -EXPORT int libmeteor_loadsaveram(const void *data, unsigned size) -{ - return AMeteor::_memory.LoadCart((const uint8_t*)data, size); -} - -EXPORT int libmeteor_savesaveram(void **data, unsigned *size) -{ - return AMeteor::_memory.SaveCart((uint8_t **)data, size); -} - -EXPORT void libmeteor_savesaveram_destroy(void *data) -{ - AMeteor::_memory.SaveCartDestroy((uint8_t *)data); -} - -EXPORT int libmeteor_hassaveram() -{ - return AMeteor::_memory.HasCart(); -} - -EXPORT void libmeteor_clearsaveram() -{ - AMeteor::_memory.DeleteCart(); -} - -EXPORT int libmeteor_savestate(void **data, unsigned *size) -{ - if (!data || !size) - return 0; - - std::ostringstream ss = std::ostringstream(std::ios_base::binary); - AMeteor::SaveState(ss); - - std::string s = ss.str(); - - void *ret = std::malloc(s.size()); - if (!ret) - return 0; - std::memcpy(ret, s.data(), s.size()); - *data = ret; - *size = s.size(); - return 1; -} - -EXPORT void libmeteor_savestate_destroy(void *data) -{ - std::free(data); -} - -EXPORT int libmeteor_loadstate(const void *data, unsigned size) -{ - std::istringstream ss = std::istringstream(std::string((const char*)data, size), std::ios_base::binary); - return AMeteor::LoadState(ss); -} - -// TODO: cartram memory domain, cartram in system bus memory domain -EXPORT uint8_t libmeteor_peekbus(uint32_t addr) -{ - return AMeteor::_memory.Peek8(addr); -} - -EXPORT void libmeteor_writebus(uint32_t addr, uint8_t val) -{ - AMeteor::_memory.Write8(addr, val); -} - -int slcallbackline = 400; -void (*slcallback)() = NULL; - -EXPORT void libmeteor_setscanlinecallback(void (*callback)(), int scanline) -{ - if (!callback) - slcallbackline = 400; - else - slcallbackline = scanline; - slcallback = callback; -} - -void scanlinecallback_bizhawk() -{ - if (slcallback) - slcallback(); -} - -EXPORT void libmeteor_getregs(int *dest) -{ - AMeteor::_cpu.UpdateCpsr(); - for (int i = 0; i < 16; i++) - dest[i] = AMeteor::_cpu.Reg(i); - dest[16] = AMeteor::_cpu.Cpsr().dw; - dest[17] = AMeteor::_cpu.Spsr().dw; -} diff --git a/libmeteor/include/ameteor.hpp b/libmeteor/include/ameteor.hpp deleted file mode 100644 index 27dafb1fd8..0000000000 --- a/libmeteor/include/ameteor.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __AMETEOR_H__ -#define __AMETEOR_H__ - -#include "ameteor/memory.hpp" -#include "ameteor/io.hpp" -#include "ameteor/dma.hpp" -#include "ameteor/interpreter.hpp" -#include "ameteor/lcd.hpp" -#include "ameteor/clock.hpp" -#include "ameteor/timer.hpp" -#include "ameteor/sound.hpp" -#include "ameteor/keypad.hpp" - -namespace AMeteor -{ - extern Clock _clock; - extern Io _io; - extern Interpreter _cpu; - extern Memory _memory; - extern Dma _dma; - extern Lcd _lcd; - extern Sound _sound; - extern Keypad _keypad; - extern Timer _timer0; - extern Timer _timer1; - extern Timer _timer2; - extern Timer _timer3; - - const uint32_t UNIT_CLOCK = 0x0001; - const uint32_t UNIT_IO = 0x0002; - const uint32_t UNIT_CPU = 0x0004; - const uint32_t UNIT_MEMORY = 0x0008; - const uint32_t UNIT_DMA = 0x0010; - const uint32_t UNIT_LCD = 0x0020; - const uint32_t UNIT_SOUND = 0x0040; - const uint32_t UNIT_KEYPAD = 0x0080; - const uint32_t UNIT_TIMER0 = 0x0100; - const uint32_t UNIT_TIMER1 = 0x0200; - const uint32_t UNIT_TIMER2 = 0x0400; - const uint32_t UNIT_TIMER3 = 0x0800; - const uint32_t UNIT_MEMORY_ROM = 0x1000; - const uint32_t UNIT_MEMORY_BIOS = 0x2000; - const uint32_t UNIT_ALL = 0x3FFF; - - void Reset (uint32_t units); - - bool SaveState (const char* filename); - bool LoadState (const char* filename); - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - inline void Run (unsigned int cycles) - { - _cpu.Run(cycles); - } - - inline void Stop () - { - _cpu.Stop(); - } -} - -#endif diff --git a/libmeteor/include/ameteor/audio/dsound.hpp b/libmeteor/include/ameteor/audio/dsound.hpp deleted file mode 100644 index 85dc320b13..0000000000 --- a/libmeteor/include/ameteor/audio/dsound.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __AUDIO_D_SOUND_H__ -#define __AUDIO_D_SOUND_H__ - -#include -#include -#include - -namespace AMeteor -{ - namespace Audio - { - class DSound - { - public : - static const int BUFFER_SIZE = 32; - - DSound (); - - void FillFifo (int8_t* buffer); - void FillFifo (int8_t sample); - - void NextSample () - { - // if the buffer is empty, there is nothing to do - if (m_size) - // if this was the last sample, we reset all and send 0 to all next - // GetSample()s until the buffer is refilled - if (--m_size == 0) - Reset(); - // else, we go on to next sample and we go to the first if we got - // to the last - else if (++m_rpos >= BUFFER_SIZE) - m_rpos = 0; - } - - void Reset () - { - m_buffer[0] = m_size = m_rpos = m_wpos = 0; - } - - int8_t GetSample() - { - return m_buffer[m_rpos]; - } - - uint8_t GetSize () - { - return m_size; - }; - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - int8_t m_buffer[BUFFER_SIZE]; - uint8_t m_rpos, m_wpos; - uint8_t m_size; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/audio/sound1.hpp b/libmeteor/include/ameteor/audio/sound1.hpp deleted file mode 100644 index 282ff2c125..0000000000 --- a/libmeteor/include/ameteor/audio/sound1.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __AUDIO_SOUND_1_H__ -#define __AUDIO_SOUND_1_H__ - -#include -#include -#include - -namespace AMeteor -{ - namespace Audio - { - class Sound1 - { - public : - Sound1 (uint16_t& cntl, uint16_t& cnth, uint16_t& cntx, - uint16_t freq); - - void Reset (); - - // call this at the frequence given in constructor - void SoundTick (); - - void ResetSound (); - void ResetEnvelope () - { - m_envelope = 0; - } - - int8_t GetSample () const - { - return m_sample; - } - - bool IsOn () const - { - return m_on; - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - uint16_t &m_cntl, &m_cnth, &m_cntx; - bool m_on; - // positions in Period, Sweep time and Envelope step time - uint32_t m_posP, m_posS, m_posE; - int8_t m_sample; - // sample period in cycles - uint16_t m_speriod; - // envelope level - uint8_t m_envelope; - // sound length in cycles - uint32_t m_length; - bool m_timed; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/audio/sound2.hpp b/libmeteor/include/ameteor/audio/sound2.hpp deleted file mode 100644 index d4c18d8aaa..0000000000 --- a/libmeteor/include/ameteor/audio/sound2.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __AUDIO_SOUND_2_H__ -#define __AUDIO_SOUND_2_H__ - -#include -#include -#include - -namespace AMeteor -{ - namespace Audio - { - class Sound2 - { - public : - Sound2 (uint16_t& cntl, uint16_t& cnth, uint16_t freq); - - void Reset (); - - // call this at the frequence given in constructor - void SoundTick (); - - void ResetSound (); - void ResetEnvelope () - { - m_envelope = 0; - } - - int8_t GetSample () const - { - return m_sample; - } - - bool IsOn () const - { - return m_on; - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - uint16_t &m_cntl, &m_cnth; - bool m_on; - uint32_t m_posP, m_posE; - int8_t m_sample; - uint16_t m_speriod; - uint8_t m_envelope; - uint32_t m_length; - bool m_timed; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/audio/sound4.hpp b/libmeteor/include/ameteor/audio/sound4.hpp deleted file mode 100644 index ab51d627d9..0000000000 --- a/libmeteor/include/ameteor/audio/sound4.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __AUDIO_SOUND_4_H__ -#define __AUDIO_SOUND_4_H__ - -#include -#include -#include - -namespace AMeteor -{ - namespace Audio - { - void InitNoise (); - - class Sound4 - { - public : - Sound4 (uint16_t& cntl, uint16_t& cnth, uint16_t freq); - - void Reset (); - - // call this at the frequence given in constructor - void SoundTick (); - - void ResetSound (); - void ResetEnvelope () - { - m_envelope = 0; - } - - int8_t GetSample () const - { - return m_sample; - } - - bool IsOn () const - { - return m_on; - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - uint16_t &m_cntl, &m_cnth; - bool m_on; - // positions in Period, position in noise and Envelope step time - uint32_t m_posP, m_posN, m_posE; - int8_t m_sample; - // sample period in cycles - uint16_t m_speriod; - // envelope level - uint8_t m_envelope; - // sound length in cycles - uint32_t m_length; - bool m_timed; - // clock divider - uint8_t m_div; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/audio/speaker.hpp b/libmeteor/include/ameteor/audio/speaker.hpp deleted file mode 100644 index 15d37f955b..0000000000 --- a/libmeteor/include/ameteor/audio/speaker.hpp +++ /dev/null @@ -1,173 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __AUDIO_SPEAKER_H__ -#define __AUDIO_SPEAKER_H__ - -#include -#include -#include -#include -#include "sound1.hpp" -#include "sound2.hpp" -#include "sound4.hpp" -#include "dsound.hpp" - -namespace AMeteor -{ - namespace Audio - { - class Speaker - { - public : - typedef syg::slot1 FrameSlot; - - Speaker (uint16_t& cnt1l, uint16_t& cnt1h, uint16_t& cnt1x, - uint16_t& cnt2l, uint16_t& cnt2h, - uint16_t& cnt4l, uint16_t& cnt4h, - uint16_t& cntl, uint16_t& cnth, uint16_t& cntx, uint16_t& bias); - ~Speaker (); - - inline void SetFrameSlot (const FrameSlot& slot); - - void Reset (); - - inline void ResetSound1 (); - inline void ResetSound2 (); - inline void ResetSound4 (); - inline void ResetSound1Envelope (); - inline void ResetSound2Envelope (); - inline void ResetSound4Envelope (); - - inline void FillFifoA (int8_t* buffer); - inline void FillFifoB (int8_t* buffer); - inline void FillFifoA (int8_t sample); - inline void FillFifoB (int8_t sample); - - inline void ResetFifoA (); - inline void ResetFifoB (); - - inline void NextSampleA (); - inline void NextSampleB (); - - inline uint8_t GetSizeA(); - inline uint8_t GetSizeB(); - - void SoundTick (); - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - Sound1 m_sound1; - Sound2 m_sound2; - Sound4 m_sound4; - DSound m_dsa, m_dsb; - uint16_t &m_cntl, &m_cnth, &m_cntx, &m_bias; - - FrameSlot m_sig_frame; - - int16_t MixSample (uint16_t cntl, uint8_t cnth); - }; - - inline void Speaker::SetFrameSlot (const FrameSlot& slot) - { - m_sig_frame = slot; - } - - inline void Speaker::ResetSound1 () - { - m_sound1.ResetSound (); - } - - inline void Speaker::ResetSound2 () - { - m_sound2.ResetSound (); - } - - inline void Speaker::ResetSound4 () - { - m_sound4.ResetSound (); - } - - inline void Speaker::ResetSound1Envelope () - { - m_sound1.ResetEnvelope(); - } - - inline void Speaker::ResetSound2Envelope () - { - m_sound2.ResetEnvelope(); - } - - inline void Speaker::ResetSound4Envelope () - { - m_sound4.ResetEnvelope(); - } - - inline void Speaker::FillFifoA (int8_t* buffer) - { - m_dsa.FillFifo(buffer); - } - - inline void Speaker::FillFifoB (int8_t* buffer) - { - m_dsb.FillFifo(buffer); - } - - inline void Speaker::FillFifoA (int8_t sample) - { - m_dsa.FillFifo(sample); - } - - inline void Speaker::FillFifoB (int8_t sample) - { - m_dsb.FillFifo(sample); - } - - inline void Speaker::ResetFifoA () - { - m_dsa.Reset(); - } - - inline void Speaker::ResetFifoB () - { - m_dsb.Reset(); - } - - inline void Speaker::NextSampleA () - { - m_dsa.NextSample(); - } - - inline void Speaker::NextSampleB () - { - m_dsb.NextSample(); - } - - inline uint8_t Speaker::GetSizeA() - { - return m_dsa.GetSize(); - } - - inline uint8_t Speaker::GetSizeB() - { - return m_dsb.GetSize(); - } - } -} - -#endif diff --git a/libmeteor/include/ameteor/bios.hpp b/libmeteor/include/ameteor/bios.hpp deleted file mode 100644 index 05a3b7db70..0000000000 --- a/libmeteor/include/ameteor/bios.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __BIOS_H__ -#define __BIOS_H__ - -#include "ameteor.hpp" - -namespace AMeteor -{ - namespace Bios - { - // Entry point - void Bios000h (); - // Software IRQ - void Bios008h (); - void Bios168h (); - // Return from IntrWait (after the IRQ) - void Bios338h (); - // IRQ - void Bios018h (); - void Bios130h (); - - void SoftReset (); // 00 - void RegisterRamReset (); // 01 - void Halt (); // 02 - void IntrWait (); // 04 - void VBlankIntrWait (); // 05 - void Div (); // 06 - void DivArm (); // 07 - void Sqrt (); // 08 - void ArcTan (); // 09 - void ArcTan2 (); // 0A - void CpuSet (); // 0B - void CpuFastSet (); // 0C - void BgAffineSet (); // 0E - void ObjAffineSet (); // 0F - void LZ77UnCompWram (); // 11 - void LZ77UnCompVram (); // 12 - void HuffUnComp (); // 13 - void RLUnCompWram (); // 14 - void RLUnCompVram (); // 15 - } -} - -#endif diff --git a/libmeteor/include/ameteor/cartmem.hpp b/libmeteor/include/ameteor/cartmem.hpp deleted file mode 100644 index e7ee43678a..0000000000 --- a/libmeteor/include/ameteor/cartmem.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __CART_MEM_H__ -#define __CART_MEM_H__ - -#include -#include -#include -#include - -namespace AMeteor -{ - class CartMem - { - public: - static const unsigned int MAX_SIZE = 0x20000; - - CartMem(); - virtual ~CartMem(); - - virtual void Reset () = 0; - - virtual bool Load (std::istream& stream) = 0; - virtual bool Save (std::ostream& stream) = 0; - - virtual uint8_t Read (uint16_t add) = 0; - // returns true if memory has been updated - virtual bool Write (uint16_t add, uint8_t val) = 0; - - virtual bool SaveState (std::ostream& stream); - virtual bool LoadState (std::istream& stream); - - protected: - uint8_t* m_data; - uint32_t m_size; - }; - -#ifdef __LIBRETRO__ - extern uint8_t CartMemData[CartMem::MAX_SIZE+4]; -#endif -} - -#endif diff --git a/libmeteor/include/ameteor/clock.hpp b/libmeteor/include/ameteor/clock.hpp deleted file mode 100644 index b711080538..0000000000 --- a/libmeteor/include/ameteor/clock.hpp +++ /dev/null @@ -1,111 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __CLOCK_H__ -#define __CLOCK_H__ - -#include -#include -#include -#include -#include - -namespace AMeteor -{ - class Clock - { - public : - Clock () - { - Reset(); - } - - void Reset (); - - void ResetCounter() - { - m_count = 0; - } - unsigned int GetCounter() const - { - return m_count; - } - - void TimePass (unsigned short cycles) - { - m_cycles += cycles; - } - void Commit (); - void WaitForNext (); - - void AddLcd (uint32_t cycles) - { - // The lcd clock is always enabled - m_lcd += cycles; - SetFirst(); - } - - void AddTimer (uint8_t num, uint32_t cycles) - { - if (m_timer[num] == INT_MAX) - m_timer[num] = cycles; - else - m_timer[num] += cycles; - SetFirst(); - } - void SetTimer (uint8_t num, uint32_t cycles) - { - m_timer[num] = cycles; - SetFirst(); - } - void DisableTimer (uint8_t num) - { - m_timer[num] = INT_MAX; - SetFirst(); - } - int GetTimer (uint8_t num) - { - return m_timer[num]; - } - - //void SetBattery (uint32_t cycles) - //{ - // m_battery = cycles; - //} - //void DisableBattery () - //{ - // m_battery = INT_MAX; - // no need to SetFirst since battery will be disabled only in TimeEvent - //} - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - // XXX freq - static const int SOUND_PERIOD = 380; - - unsigned short m_cycles; - unsigned short m_first; - int m_lcd, m_timer[4], m_sound;//, m_battery; - - unsigned int m_count; - - void SetFirst (); - }; -} - -#endif diff --git a/libmeteor/include/ameteor/cpu.hpp b/libmeteor/include/ameteor/cpu.hpp deleted file mode 100644 index 2259de832d..0000000000 --- a/libmeteor/include/ameteor/cpu.hpp +++ /dev/null @@ -1,148 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __CPU_H__ -#define __CPU_H__ - -#include -#include -#include - -namespace AMeteor -{ - class Cpu - { - public : - union Psr - { - uint32_t dw; - struct - { - unsigned int mode : 5; - unsigned int thumb : 1; - unsigned int fiq_d : 1; - unsigned int irq_d : 1; - unsigned int reserved : 19; - unsigned int s_overflow : 1; - unsigned int f_overflow : 1; - unsigned int f_carry : 1; - unsigned int f_zero : 1; - unsigned int f_sign : 1; - } b; - }; - struct IPsr - { - uint8_t mode; - bool thumb; - bool fiq_d; - bool irq_d; - bool s_overflow; - bool f_overflow; - bool f_carry; - bool f_zero; - bool f_sign; - }; - enum Modes - { - M_USR = 0x10, - M_FIQ = 0x11, - M_IRQ = 0x12, - M_SVC = 0x13, - M_ABT = 0x17, - M_UND = 0x1B, - M_SYS = 0x1F - }; - - Cpu (); - virtual ~Cpu () {} - - virtual void Reset (); - virtual void SoftReset (); - - void UpdateICpsr (); - void UpdateCpsr (); - void SwitchToMode (uint8_t newmode); - void SwitchModeBack (); - - virtual void SendInterrupt (uint16_t interrupt) = 0; - virtual void CheckInterrupt () = 0; - void Interrupt (); - void SoftwareInterrupt (uint32_t comment); - void SoftwareInterrupt (); - - uint32_t& Reg(uint8_t r) - { - return m_st.r[r]; - } - - Psr& Cpsr() - { - return m_st.cpsr; - } - IPsr& ICpsr() - { - return m_st.icpsr; - } - Psr& Spsr() - { - return m_st.spsr; - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - protected : - struct CPUState - { - // Current registers - uint32_t r[16]; - Psr cpsr, spsr; - IPsr icpsr; - - // System/User - uint32_t usr_r[7]; // from 8 to 14 - - // FIQ - uint32_t fiq_r[7]; // from 8 to 14 - Psr fiq_spsr; - - // Supervisor - uint32_t svc_r[2]; // 13 and 14 - Psr svc_spsr; - - // Abort - uint32_t abt_r[2]; // 13 and 14 - Psr abt_spsr; - - // IRQ - uint32_t irq_r[2]; // 13 and 14 - Psr irq_spsr; - - // Undefined - uint32_t und_r[2]; // 13 and 14 - Psr und_spsr; - }; - - CPUState m_st; - - virtual void SetInterrupt (bool interrupt) = 0; - - private : - void SaveMode (uint8_t mode); - }; -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/argimmediate.hpp b/libmeteor/include/ameteor/disassembler/argimmediate.hpp deleted file mode 100644 index cb372f1067..0000000000 --- a/libmeteor/include/ameteor/disassembler/argimmediate.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __ARG_IMMEDIATE_H__ -#define __ARG_IMMEDIATE_H__ - -#include "argument.hpp" -#include - -namespace AMeteor -{ - namespace Disassembler - { - class ArgImmediate : public Argument - { - public : - ArgImmediate (int32_t imm) : - m_imm(imm) - { } - - Argument* Clone () const; - - std::string GetString () const; - - private : - int32_t m_imm; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/argmulregisters.hpp b/libmeteor/include/ameteor/disassembler/argmulregisters.hpp deleted file mode 100644 index 73a6c241a1..0000000000 --- a/libmeteor/include/ameteor/disassembler/argmulregisters.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __ARG_MUL_REGISTERS_H__ -#define __ARG_MUL_REGISTERS_H__ - -#include "argument.hpp" - -#include -#include - -namespace AMeteor -{ - namespace Disassembler - { - enum SpecialRegister - { - SPREG_NONE = 0, - SPREG_LR = 1, - SPREG_PC = 2 - }; - - class ArgMulRegisters : public Argument - { - public : - ArgMulRegisters (bool forceuser) : - m_lastreg(SPREG_NONE), - m_forceuser(forceuser) - { } - - Argument* Clone () const; - - void AddRegister(uint8_t reg) - { - m_regs.push_back(reg); - } - void AddLastRegister(SpecialRegister reg) - { - m_lastreg = reg; - } - - std::string GetString () const; - - private : - typedef std::vector Registers; - - Registers m_regs; - SpecialRegister m_lastreg; - bool m_forceuser; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/argpsr.hpp b/libmeteor/include/ameteor/disassembler/argpsr.hpp deleted file mode 100644 index 5557615a99..0000000000 --- a/libmeteor/include/ameteor/disassembler/argpsr.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __ARG_PSR_H__ -#define __ARG_PSR_H__ - -#include "argument.hpp" - -#include - -namespace AMeteor -{ - namespace Disassembler - { - class ArgPsr : public Argument - { - public : - ArgPsr (bool spsr, uint8_t fields = 0xFF) : - m_spsr(spsr), - m_fields(fields) - { } - - Argument* Clone () const; - - std::string GetString () const; - - private : - bool m_spsr; - uint8_t m_fields; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/argregister.hpp b/libmeteor/include/ameteor/disassembler/argregister.hpp deleted file mode 100644 index 78a26b44e1..0000000000 --- a/libmeteor/include/ameteor/disassembler/argregister.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __ARG_REGISTER_H__ -#define __ARG_REGISTER_H__ - -#include "argument.hpp" - -#include - -namespace AMeteor -{ - namespace Disassembler - { - class ArgRegister : public Argument - { - public : - ArgRegister (uint8_t reg, bool writeback = false, - bool special = false, bool memory = false) : - m_reg(reg), - m_writeback(writeback), - m_special(special), - m_memory(memory) - { } - - Argument* Clone () const; - - std::string GetString () const; - uint8_t GetRegister () const - { - return m_reg; - } - - private : - uint8_t m_reg; - bool m_writeback; - bool m_special; - bool m_memory; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/argrelative.hpp b/libmeteor/include/ameteor/disassembler/argrelative.hpp deleted file mode 100644 index c7ccc9e212..0000000000 --- a/libmeteor/include/ameteor/disassembler/argrelative.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __ARG_RELATIVE_H__ -#define __ARG_RELATIVE_H__ - -#include "argument.hpp" -#include "argregister.hpp" -#include "argimmediate.hpp" - -namespace AMeteor -{ - namespace Disassembler - { - class ArgRelative : public Argument - { - public : - ArgRelative (const ArgRegister& reg, const Argument& off, - bool pre, bool up, bool writeback); - ArgRelative (const ArgRelative& arg); - ~ArgRelative (); - - Argument* Clone () const; - - std::string GetString () const; - - private : - ArgRegister m_reg; - const Argument* m_off; - bool m_pre; - bool m_up; - bool m_writeback; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/argshift.hpp b/libmeteor/include/ameteor/disassembler/argshift.hpp deleted file mode 100644 index 1ba586b6d7..0000000000 --- a/libmeteor/include/ameteor/disassembler/argshift.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __ARG_SHIFT_H__ -#define __ARG_SHIFT_H__ - -#include "argument.hpp" - -namespace AMeteor -{ - namespace Disassembler - { - enum ShiftType - { - SHIFT_LSL = 0, - SHIFT_LSR, - SHIFT_ASR, - SHIFT_ROR, - SHIFT_RRX - }; - - class ArgShift : public Argument - { - public : - ArgShift (const Argument& arg1, const Argument& arg2, - ShiftType type, bool memory); - ArgShift (const ArgShift& arg); - ~ArgShift (); - - Argument* Clone () const; - - std::string GetString () const; - - private : - const Argument* m_arg1; - const Argument* m_arg2; - ShiftType m_type; - bool m_memory; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/arguimmediate.hpp b/libmeteor/include/ameteor/disassembler/arguimmediate.hpp deleted file mode 100644 index 450322eba3..0000000000 --- a/libmeteor/include/ameteor/disassembler/arguimmediate.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __ARG_U_IMMEDIATE_H__ -#define __ARG_U_IMMEDIATE_H__ - -#include "argument.hpp" - -#include - -namespace AMeteor -{ - namespace Disassembler - { - class ArgUImmediate : public Argument - { - public : - ArgUImmediate (uint32_t imm) : - m_imm(imm) - { } - - Argument* Clone () const; - - std::string GetString () const; - - private : - uint32_t m_imm; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/argument.hpp b/libmeteor/include/ameteor/disassembler/argument.hpp deleted file mode 100644 index de007d0d7f..0000000000 --- a/libmeteor/include/ameteor/disassembler/argument.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __ARGUMENT_H__ -#define __ARGUMENT_H__ - -#include - -namespace AMeteor -{ - namespace Disassembler - { - class Argument - { - public : - virtual ~Argument () - { } - - virtual Argument* Clone () const = 0; - - virtual std::string GetString () const = 0; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/arguments.hpp b/libmeteor/include/ameteor/disassembler/arguments.hpp deleted file mode 100644 index dd078da2ef..0000000000 --- a/libmeteor/include/ameteor/disassembler/arguments.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __ARGUMENTS_H__ -#define __ARGUMENTS_H__ - -#include "argument.hpp" - -#include - -namespace AMeteor -{ - namespace Disassembler - { - class Arguments - { - public : - ~Arguments (); - - void Clear (); - - void AddArgument(const Argument& arg) - { - m_args.push_back(arg.Clone()); - } - - std::string GetString () const; - - private : - std::vector m_args; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/disassembler/instruction.hpp b/libmeteor/include/ameteor/disassembler/instruction.hpp deleted file mode 100644 index 3da87b8be1..0000000000 --- a/libmeteor/include/ameteor/disassembler/instruction.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __INSTRUCTION_H__ -#define __INSTRUCTION_H__ - -#include "arguments.hpp" - -#include -#include - -namespace AMeteor -{ - namespace Disassembler - { - class Instruction - { - public : - Instruction () - { - } - - explicit Instruction (uint32_t offset, uint32_t code) - { - ParseArm (offset, code); - } - - explicit Instruction (uint32_t offset, uint16_t code) - { - ParseThumb(offset, code); - } - - void Clear (); - - void ParseArm (uint32_t offset, uint32_t code); - void ParseThumb (uint32_t offset, uint16_t code); - - const std::string& GetOperator () const - { - return m_operator; - } - - std::string GetArguments () const - { - return m_args.GetString(); - } - - std::string ToString () const - { - return GetOperator() + ' ' + GetArguments(); - } - - private : - std::string m_operator; - Arguments m_args; - - void ParseArmDataProc (uint32_t code); - void ParseArmCondition (uint32_t code); - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/dma.hpp b/libmeteor/include/ameteor/dma.hpp deleted file mode 100644 index d4e31905e5..0000000000 --- a/libmeteor/include/ameteor/dma.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __DMA_H__ -#define __DMA_H__ - -#include -#include -#include - -namespace AMeteor -{ - class Dma - { - public : - enum Reason - { - Immediately = 0, - VBlank, - HBlank, - Special - }; - - Dma () : - m_graphic(false) - { } - - void Reset (); - - bool GraphicDma () const - { - return false; - //return m_graphic; - } - - void SetReload(uint8_t channum, uint16_t reload) - { - m_chans[channum].reload = reload; - } - - void UpdateCnt (uint8_t channum); - void Check(uint8_t channum, uint8_t reason); - inline void CheckAll(uint8_t reason) - { - Check(0, reason); - Check(1, reason); - Check(2, reason); - Check(3, reason); - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - struct Channel - { - Channel () : - reload(0), - src(0), - dest(0), - count(0), - control(0) - { } - - uint16_t reload; - uint32_t src; - uint32_t dest; - uint16_t count; - union Control - { - Control(uint16_t v) : - w(v) - { } - - uint16_t w; - struct - { - unsigned int unused : 5; - unsigned int dest : 2; - unsigned int src : 2; - unsigned int repeat : 1; - unsigned int type : 1; - unsigned int drq : 1; - unsigned int start : 2; - unsigned int irq : 1; - unsigned int enable : 1; - } b; - } control; - }; - - Channel m_chans[4]; - bool m_graphic; - - void Process(uint8_t channel); - void Copy (uint32_t& src, uint32_t& dest, int8_t s_inc, int8_t d_inc, - uint32_t count, bool word); - }; -} - -#endif diff --git a/libmeteor/include/ameteor/eeprom.hpp b/libmeteor/include/ameteor/eeprom.hpp deleted file mode 100644 index 8052a5b393..0000000000 --- a/libmeteor/include/ameteor/eeprom.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __EEPROM_H__ -#define __EEPROM_H__ - -#include "cartmem.hpp" -#include -#include -#include - -namespace AMeteor -{ - class Eeprom : public CartMem - { - public : - Eeprom (bool big); - - void Reset (); - - uint16_t GetSize () const - { - return m_size; - } - - bool Load (std::istream& f); - bool Save (std::ostream& f); - - uint8_t Read (uint16_t add); - bool Write (uint16_t add, uint8_t val); - - uint16_t Read (); - //bool Write (uint16_t val); - - bool Write (uint16_t* data, uint16_t size); - //XXX -#if 0 - void Read (uint16_t* pOut); -#endif - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - enum State - { - IDLE, - //WAITING, - - //READ_ADD, - //READ_END, - READ_GARBAGE, - READ_DATA - - /*WRITE_ADD, - WRITE_DATA, - WRITE_END*/ - }; - - uint8_t m_state; - uint16_t m_add; - uint8_t m_pos; - }; -} - -#endif diff --git a/libmeteor/include/ameteor/flash.hpp b/libmeteor/include/ameteor/flash.hpp deleted file mode 100644 index 3c56d89747..0000000000 --- a/libmeteor/include/ameteor/flash.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __FLASH_H__ -#define __FLASH_H__ - -#include "cartmem.hpp" -#include -#include -#include - -namespace AMeteor -{ - class Flash : public CartMem - { - public : - Flash (bool big); - - void Reset (); - - bool Load (std::istream& f); - bool Save (std::ostream& f); - - uint8_t Read (uint16_t add); - bool Write (uint16_t add, uint8_t val); - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - uint8_t m_device_id; - uint8_t m_manufacturer_id; - - enum State - { - NORMAL, - CMD1, - CMD2, - ID, - ERASE1, - ERASE2, - ERASE3, - WRITE - }; - - State m_state; - }; -} - -#endif diff --git a/libmeteor/include/ameteor/graphics/bglayer.hpp b/libmeteor/include/ameteor/graphics/bglayer.hpp deleted file mode 100644 index 48d19ffe67..0000000000 --- a/libmeteor/include/ameteor/graphics/bglayer.hpp +++ /dev/null @@ -1,100 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __GRAPHICS_BG_LAYER_H__ -#define __GRAPHICS_BG_LAYER_H__ - -#include "ameteor/memory.hpp" -#include "ameteor/io.hpp" - -#include -#include - -namespace AMeteor -{ - namespace Graphics - { - class BgLayer - { - public : - BgLayer (int8_t num, Memory& memory, Io& io, uint16_t* pPalette); - ~BgLayer (); - - inline uint8_t GetNum () const; - inline uint8_t GetPriority () const; - - void DrawLine0 (uint8_t line, uint16_t* ptr); - void DrawLine2 (uint16_t* ptr, - int32_t refX, int32_t refY, - int16_t dx, int16_t dy); - void DrawLine3 (uint16_t* ptr, - int32_t refX, int32_t refY, - int16_t dx, int16_t dy); - void DrawLine4 (uint8_t line, uint16_t* ptr, - int32_t curX, int32_t curY, - int16_t dx, int16_t dmx, int16_t dy, int16_t dmy, bool frame1); - void DrawLine5 (uint16_t* ptr, - int32_t refX, int32_t refY, - int16_t dx, int16_t dy, bool frame1); - void FillList (); - - void UpdateCnt (uint16_t cnt); - inline void UpdateXOff (uint16_t off); - inline void UpdateYOff (uint16_t off); - - private : - Memory& m_memory; - Io& m_io; - - const uint8_t m_num; - uint8_t m_priority; - - uint16_t m_cnt; - bool m_hicolor; - uint16_t m_xoff, m_yoff; - // in text mode - uint8_t m_tWidth, m_tHeight; - // in rotation/scale mode - uint8_t m_rWidth, m_rHeight; - - uint32_t m_mapAdd; - uint32_t m_charAdd; - uint16_t* m_pPalette; - }; - - inline uint8_t BgLayer::GetNum () const - { - return m_num; - } - - inline uint8_t BgLayer::GetPriority () const - { - return m_priority; - } - - inline void BgLayer::UpdateXOff (uint16_t off) - { - m_xoff = off; - } - - inline void BgLayer::UpdateYOff (uint16_t off) - { - m_yoff = off; - } - } -} - -#endif diff --git a/libmeteor/include/ameteor/graphics/object.hpp b/libmeteor/include/ameteor/graphics/object.hpp deleted file mode 100644 index c1611c149b..0000000000 --- a/libmeteor/include/ameteor/graphics/object.hpp +++ /dev/null @@ -1,100 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __GRAPHICS_OBJECT_H__ -#define __GRAPHICS_OBJECT_H__ - -#include -#include -#include - -namespace AMeteor -{ - namespace Graphics - { - class Object - { - public : - static const uint8_t FLIP_HORIZONTAL = 1; - static const uint8_t FLIP_VERTICAL = 2; - - Object (uint16_t* pPalette, uint8_t* pChar); - // Warning : this copy constructor must not be used on an used object - // use it only on just created objects - Object (const Object& obj); - - inline uint8_t GetPriority () const; - inline int8_t GetRotationParam () const; - inline uint16_t GetTileNum () const; - inline bool IsWindow () const; - - void DrawLine (uint8_t line, uint32_t* surface, bool oneDim, - uint8_t mosaic); - void DrawLineRot (uint8_t line, uint32_t* surface, bool oneDim, - int16_t a, int16_t b, int16_t c, int16_t d, uint8_t mosaic); - void DrawWindow (uint8_t line, uint8_t* surface, bool oneDim, - uint8_t mask); - void DrawWindowRot (uint8_t line, uint8_t* surface, - bool oneDim, int16_t a, int16_t b, int16_t c, int16_t d, - uint8_t mask); - - void UpdateAttrs (uint16_t attr0, uint16_t attr1, uint16_t attr2); - void UpdateAttr0 (uint16_t attr); - void UpdateAttr1 (uint16_t attr); - void UpdateAttr2 (uint16_t attr); - - private : - inline void SetSize (); - - enum Shape - { - SHAPE_SQUARE = 0, - SHAPE_HORIZONTAL, - SHAPE_VERTICAL, - SHAPE_PROHIBITED - }; - - uint16_t m_attr0, m_attr1, m_attr2; - uint8_t m_width, m_height; - uint16_t* m_pPalette; - uint8_t* m_pChar; - uint32_t m_charBegin; - uint32_t m_charEnd; - }; - - inline int8_t Object::GetRotationParam () const - { - return (m_attr0 & (0x1 << 8)) ? (m_attr1 >> 9) & 0x1F : -1; - } - - inline uint8_t Object::GetPriority () const - { - return (m_attr2 >> 10) & 0x3; - } - - inline bool Object::IsWindow () const - { - return (m_attr0 & (0x3 << 10)) == (0x2 << 10); - } - - inline uint16_t Object::GetTileNum () const - { - return (m_attr2 & 0x3FF); - } - } -} - -#endif diff --git a/libmeteor/include/ameteor/graphics/objects.hpp b/libmeteor/include/ameteor/graphics/objects.hpp deleted file mode 100644 index a398080bd7..0000000000 --- a/libmeteor/include/ameteor/graphics/objects.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __GRAPHICS_OBJECTS_H__ -#define __GRAPHICS_OBJECTS_H__ - -#include "object.hpp" -#include "ameteor/memory.hpp" -#include "ameteor/io.hpp" - -#include - -namespace AMeteor -{ - namespace Graphics - { - class Objects - { - public : - Objects (Memory& memory, Io& io, uint16_t* pPalette); - - void DrawLine (uint8_t line, uint32_t* surface); - void DrawLineHighOnly (uint8_t line, uint32_t* surface); - void DrawWindow (uint8_t line, uint8_t* surface); - - void OamWrite (uint32_t begin, uint32_t end); - void OamWrite16 (uint32_t add); - void OamWrite32 (uint32_t add); - - private : - typedef std::vector Objs; - - Io& m_io; - Objs m_objs; - uint16_t* m_pOam; - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/graphics/renderer.hpp b/libmeteor/include/ameteor/graphics/renderer.hpp deleted file mode 100644 index d94b63c253..0000000000 --- a/libmeteor/include/ameteor/graphics/renderer.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __GRAPHICS_RENDERER_H__ -#define __GRAPHICS_RENDERER_H__ - -#include - -#include - -namespace AMeteor -{ - namespace Graphics - { - class Renderer - { - public: - typedef syg::slot1 FrameSlot; - - Renderer(const uint16_t* surface); - - inline void SetFrameSlot(const FrameSlot& slot); - - void VBlank(); - - private : - const uint16_t* m_base; - - FrameSlot m_sig_frame; - }; - - void Renderer::SetFrameSlot(const FrameSlot& slot) - { - m_sig_frame = slot; - } - } -} - -#endif diff --git a/libmeteor/include/ameteor/graphics/screen.hpp b/libmeteor/include/ameteor/graphics/screen.hpp deleted file mode 100644 index 4482a7ac68..0000000000 --- a/libmeteor/include/ameteor/graphics/screen.hpp +++ /dev/null @@ -1,148 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __GRAPHICS_SCREEN_H__ -#define __GRAPHICS_SCREEN_H__ - -#include "bglayer.hpp" -#include "objects.hpp" -#include "renderer.hpp" - -#include -#include -#include - -namespace AMeteor -{ - namespace Graphics - { - class Screen - { - public : - static const uint8_t WIDTH = 240; - static const uint8_t HEIGHT = 160; - - // we skip x frames every FRMSKIP_TOTAL frames - static const uint8_t FRMSKIP_TOTAL = 10; - - Screen (Memory& memory, Io& io); - ~Screen (); - - Renderer& GetRenderer() - { - return m_renderer; - } - const Renderer& GetRenderer() const - { - return m_renderer; - } - - const uint16_t* GetSurface () const - { - return m_surface; - } - - void SetFrameskip (uint8_t skip) - { - m_frameskip = skip; - m_curframe = 0; - } - - void DrawLine (uint8_t line); - - void UpdateDispCnt (uint16_t dispcnt) - { - m_dispcnt = dispcnt; - } - -#define UPDATE_BG_CNT(num) \ - void UpdateBg##num##Cnt (uint16_t cnt) \ - { \ - m_bgLayer##num.UpdateCnt(cnt); \ - } - UPDATE_BG_CNT(0) - UPDATE_BG_CNT(1) - UPDATE_BG_CNT(2) - UPDATE_BG_CNT(3) -#undef UPDATE_BG_CNT - -#define UPDATE_BG_OFF(num, coord) \ - void UpdateBg##num##coord##Off (uint16_t off) \ - { \ - m_bgLayer##num.Update##coord##Off(off); \ - } - UPDATE_BG_OFF(0, X) - UPDATE_BG_OFF(0, Y) - UPDATE_BG_OFF(1, X) - UPDATE_BG_OFF(1, Y) - UPDATE_BG_OFF(2, X) - UPDATE_BG_OFF(2, Y) - UPDATE_BG_OFF(3, X) - UPDATE_BG_OFF(3, Y) -#undef UPDATE_BG_OFF - -#define UPDATE_BG_REF(num, coord) \ - void UpdateBg##num##Ref##coord(int32_t x) \ - { \ - m_ref##coord##num = (x & (0x1 << 27)) ? x | 0xF0000000 : x & 0x07FFFFFF; \ - } - UPDATE_BG_REF(2, X) - UPDATE_BG_REF(2, Y) - UPDATE_BG_REF(3, X) - UPDATE_BG_REF(3, Y) -#undef UPDATE_BG_REF - - void OamWrite (uint32_t begin, uint32_t end) - { - m_objs.OamWrite (begin, end); - } - void OamWrite16 (uint32_t add) - { - m_objs.OamWrite16 (add); - } - void OamWrite32 (uint32_t add) - { - m_objs.OamWrite32 (add); - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - Io& m_io; - - uint16_t* m_surface; - - Renderer m_renderer; - - uint8_t m_frameskip, m_curframe; - - uint16_t m_dispcnt; - int32_t m_refX2, m_refY2, m_refX3, m_refY3; - uint16_t* m_pPalette; - - // FIXME is this REALLY useful ? - static BgLayer Screen::* const BgLayers [4]; - BgLayer m_bgLayer0, m_bgLayer1, m_bgLayer2, m_bgLayer3; - Objects m_objs; - - void DrawWindow (uint8_t line, uint8_t* surface, - uint16_t win0v, uint16_t win0h, uint8_t mask); - }; - } -} - -#endif diff --git a/libmeteor/include/ameteor/interpreter.hpp b/libmeteor/include/ameteor/interpreter.hpp deleted file mode 100644 index 5f02df4686..0000000000 --- a/libmeteor/include/ameteor/interpreter.hpp +++ /dev/null @@ -1,133 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __INTERPRETER_H__ -#define __INTERPRETER_H__ - -#include -#include -#include -#include "cpu.hpp" - -#define ARM(name) \ - inline void a##name () -#define NIARM(name) \ - void a##name () -#define THUMB(name) \ - inline void t##name () -#define NITHUMB(name) \ - void t##name () - -namespace AMeteor -{ - class Interpreter : public Cpu - { - public : - Interpreter(); - - void Reset () - { - m_interrupt = m_interrupt_ = false; - m_run = false; - Cpu::Reset(); - } - void SoftReset () - { - m_interrupt_ = m_interrupt = false; - Cpu::SoftReset(); - } - - void SendInterrupt (uint16_t interrupt); - void CheckInterrupt (); - - void Run (unsigned int cycles); - void Stop () - { - m_run = false; - } - bool IsRunning () - { - return m_run; - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - protected : - void SetInterrupt (bool interrupt) - { - m_interrupt = interrupt; - } - - private : - bool m_run; - - bool m_interrupt; - bool m_interrupt_; - uint32_t code; - uint8_t& m_haltcnt; - // only for use in halt mode, in normal mode we use m_interrupt - uint16_t& m_if; - uint16_t& m_ie; - - NIARM(_Code); - inline bool a_CheckCondition (uint8_t cond); - inline void a_DataProcCore(uint8_t rd, uint32_t op1, uint32_t op2, - bool shiftcarry); - - ARM(BXBLX); - ARM(BBL); - NIARM(_DataProcShiftImm); - NIARM(_DataProcShiftReg); - NIARM(_DataProcImm); - ARM(PSR); - ARM(_Multiply); - ARM(LDRSTR); - ARM(STRLDR_HD); - ARM(LDMSTM); - ARM(SWP); - ARM(SWI); - - NITHUMB(_Code); - - THUMB(_Shift); - THUMB(ADDSUB); - THUMB(_Imm); - THUMB(_ALU); - THUMB(_HiRegOp); - THUMB(LDRimm); - THUMB(STRLDRreg); - THUMB(STRLDRoff); - THUMB(LDRHSTRHoff); - THUMB(STRLDRsp); - THUMB(ADDpcsp); - THUMB(ADDsp); - THUMB(PUSHPOP); - THUMB(STMLDM); - THUMB(_CondBranch); - THUMB(SWI); - THUMB(B); - THUMB(_BL1); - THUMB(_BL2); - }; -} - -#undef ARM -#undef NIARM -#undef THUMB -#undef NITHUMB - -#endif diff --git a/libmeteor/include/ameteor/io.hpp b/libmeteor/include/ameteor/io.hpp deleted file mode 100644 index c9b9e9222a..0000000000 --- a/libmeteor/include/ameteor/io.hpp +++ /dev/null @@ -1,219 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __IO_H__ -#define __IO_H__ - -#include -#include -#include - -namespace AMeteor -{ - class Io - { - public : - enum IoAddress - { - // LCD I/O Registers - DISPCNT = 0x000, - DISPSTAT = 0x004, - VCOUNT = 0x006, - BG0CNT = 0x008, - BG1CNT = 0x00A, - BG2CNT = 0x00C, - BG3CNT = 0x00E, - BG0HOFS = 0x010, - BG0VOFS = 0x012, - BG1HOFS = 0x014, - BG1VOFS = 0x016, - BG2HOFS = 0x018, - BG2VOFS = 0x01A, - BG3HOFS = 0x01C, - BG3VOFS = 0x01E, - BG2PA = 0x020, - BG2PB = 0x022, - BG2PC = 0x024, - BG2PD = 0x026, - BG2X_L = 0x028, - BG2X_H = 0x02A, - BG2Y_L = 0x02C, - BG2Y_H = 0x02E, - BG3PA = 0x030, - BG3PB = 0x032, - BG3PC = 0x034, - BG3PD = 0x036, - BG3X_L = 0x038, - BG3X_H = 0x03A, - BG3Y_L = 0x03C, - BG3Y_H = 0x03E, - WIN0H = 0x040, - WIN1H = 0x042, - WIN0V = 0x044, - WIN1V = 0x046, - WININ = 0x048, - WINOUT = 0x04A, - MOSAIC = 0x04C, - BLDCNT = 0x050, - BLDALPHA = 0x052, - BLDY = 0x054, - // Sound Registers - SOUND1CNT_L = 0x060, NR10 = 0x060, - SOUND1CNT_H = 0x062, NR11 = 0x062, - NR12 = 0x063, - SOUND1CNT_X = 0x064, NR13 = 0x064, - NR14 = 0x065, - SOUND2CNT_L = 0x068, NR21 = 0x068, - NR22 = 0x069, - SOUND2CNT_H = 0x06C, NR23 = 0x06C, - NR24 = 0x06D, - SOUND4CNT_L = 0x078, NR41 = 0x078, - NR42 = 0x079, - SOUND4CNT_H = 0x07C, NR43 = 0x07C, - NR44 = 0x07D, - SOUNDCNT_L = 0x080, NR50 = 0x080, - NR51 = 0x081, - SOUNDCNT_H = 0x082, - SOUNDCNT_X = 0x084, NR52 = 0x084, - SOUNDBIAS = 0x088, - FIFO_A = 0x0A0, - FIFO_B = 0x0A4, - // DMA Transfer Channels - DMA0SAD = 0x0B0, - DMA0DAD = 0x0B4, - DMA0CNT_L = 0x0B8, - DMA0CNT_H = 0x0BA, - DMA1SAD = 0x0BC, - DMA1DAD = 0x0C0, - DMA1CNT_L = 0x0C4, - DMA1CNT_H = 0x0C6, - DMA2SAD = 0x0C8, - DMA2DAD = 0x0CC, - DMA2CNT_L = 0x0D0, - DMA2CNT_H = 0x0D2, - DMA3SAD = 0x0D4, - DMA3DAD = 0x0D8, - DMA3CNT_L = 0x0DC, - DMA3CNT_H = 0x0DE, - // Timer Registers - TM0CNT_L = 0x100, - TM0CNT_H = 0x102, - TM1CNT_L = 0x104, - TM1CNT_H = 0x106, - TM2CNT_L = 0x108, - TM2CNT_H = 0x10A, - TM3CNT_L = 0x10C, - TM3CNT_H = 0x10E, - // Keypad Input - KEYINPUT = 0x130, - KEYCNT = 0x132, - // Serial Communication (2) - RCNT = 0x134, - // Interrupt, WaitState, and Power-Down Control - IE = 0x200, - IF = 0x202, - WAITCNT = 0x204, - IME = 0x208, - POSTFLG = 0x300, - HALTCNT = 0x301, - - DMA_CHANSIZE = 0x00C, - TIMER_SIZE = 0x004, - // TODO make tests and everything in Write*() functions so that we can - // make IO_SIZE 0x804 (don't forget mirrors) - IO_SIZE = 0x1000 - }; - - Io (); - ~Io (); - - void Reset (); - void ClearSio (); - void ClearSound (); - void ClearOthers (); - - uint8_t Read8 (uint32_t add); - uint16_t Read16 (uint32_t add); - uint32_t Read32 (uint32_t add); - - void Write8 (uint32_t add, uint8_t val); - void Write16 (uint32_t add, uint16_t val); - void Write32 (uint32_t add, uint32_t val); - - // Direct read and write - // Using theses functions will write directly on IO memory without - // doing anything else (they won't call Dma::Check for example) - // add must be the real address & 0xFFF - // No check is done on the memory, these functions may segfault if - // you give them wrong values ! - - uint8_t DRead8 (uint16_t add) - { - return m_iomem[add]; - } - - uint16_t DRead16 (uint16_t add) - { - return *(uint16_t*)(m_iomem+add); - } - - uint32_t DRead32 (uint16_t add) - { - return *(uint32_t*)(m_iomem+add); - } - - void DWrite8 (uint16_t add, uint8_t val) - { - m_iomem[add] = val; - } - - void DWrite16 (uint16_t add, uint16_t val) - { - *(uint16_t*)(m_iomem+add) = val; - } - - void DWrite32 (uint16_t add, uint32_t val) - { - *(uint32_t*)(m_iomem+add) = val; - } - - uint8_t& GetRef8 (uint16_t add) - { - return m_iomem[add]; - } - - uint16_t& GetRef16 (uint16_t add) - { - return *(uint16_t*)(m_iomem+add); - } - - uint32_t& GetRef32 (uint16_t add) - { - return *(uint32_t*)(m_iomem+add); - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - // this should be considered very dangerous to use - uint8_t* GetIoPointer() {return m_iomem;} - - private : - uint8_t* m_iomem; - }; -} - -#endif diff --git a/libmeteor/include/ameteor/keypad.hpp b/libmeteor/include/ameteor/keypad.hpp deleted file mode 100644 index 9c6493c55b..0000000000 --- a/libmeteor/include/ameteor/keypad.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __KEYPAD_H__ -#define __KEYPAD_H__ - -#include -#include - -namespace AMeteor -{ - class Keypad - { - public : - enum Button - { - BTN_A = 0x001, - BTN_B = 0x002, - BTN_SELECT = 0x004, - BTN_START = 0x008, - BTN_RIGHT = 0x010, - BTN_LEFT = 0x020, - BTN_UP = 0x040, - BTN_DOWN = 0x080, - BTN_R = 0x100, - BTN_L = 0x200 - }; - - Keypad (); - - void Reset () - { - } - - void BindKey(int code, Button btn) - { - m_keys[code] = (uint16_t)btn; - } - void UnbindKey(int code) - { - m_keys.erase(code); - } - void BindJoy(uint16_t joyid, uint16_t button, Button btn) - { - m_joys[((int)joyid) << 16 | button] = (uint16_t)btn; - } - void UnbindJoy(uint16_t joyid, uint16_t button) - { - m_joys.erase(((int)joyid) << 16 | button); - } - void BindAxis(uint16_t joyid, uint16_t axis, Button btn) - { - m_axis[((int)joyid) << 16 | axis] = (uint16_t)btn; - } - void UnbindAxis(uint16_t joyid, uint16_t axis) - { - m_axis.erase(((int)joyid) << 16 | axis); - } - - void ResetBindings() - { - m_keys.clear(); - m_joys.clear(); - m_axis.clear(); - } - - inline void SetPadState(uint16_t keys); - - void KeyPressed(int code); - void KeyReleased(int code); - void JoyButtonPressed (uint16_t joyid, uint16_t button); - void JoyButtonReleased (uint16_t joyid, uint16_t button); - void JoyMoved (uint16_t joyid, uint16_t axis, float pos); - - void VBlank (); - - private : - uint16_t& m_keyinput; - uint16_t& m_keycnt; - - std::map m_keys; - std::map m_joys; - std::map m_axis; - }; - - void Keypad::SetPadState(uint16_t keys) - { - m_keyinput = keys; - } -} - -#endif diff --git a/libmeteor/include/ameteor/lcd.hpp b/libmeteor/include/ameteor/lcd.hpp deleted file mode 100644 index 0068aad295..0000000000 --- a/libmeteor/include/ameteor/lcd.hpp +++ /dev/null @@ -1,129 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __LCD_H__ -#define __LCD_H__ - -#include "clock.hpp" - -#include "memory.hpp" -#include "io.hpp" -#include "graphics/screen.hpp" - -#include -#include -#include - -#include - -namespace AMeteor -{ - class Lcd - { - public : - Lcd (); - - void Reset (); - - const uint16_t* GetSurface () const - { - return m_screen.GetSurface(); - } - - Graphics::Screen& GetScreen() - { - return m_screen; - } - const Graphics::Screen& GetScreen() const - { - return m_screen; - } - - void SetFrameskip (uint8_t skip) - { - m_screen.SetFrameskip(skip); - } - - void UpdateDispCnt (uint16_t dispcnt) - { - m_screen.UpdateDispCnt(dispcnt); - } - -#define UPDATE_BG_CNT(num) \ - void UpdateBg##num##Cnt (uint16_t cnt) \ - { \ - m_screen.UpdateBg##num##Cnt(cnt); \ - } - UPDATE_BG_CNT(0) - UPDATE_BG_CNT(1) - UPDATE_BG_CNT(2) - UPDATE_BG_CNT(3) -#undef UPDATE_BG_CNT - -#define UPDATE_BG_OFF(num, coord) \ - void UpdateBg##num##coord##Off (uint16_t cnt) \ - { \ - m_screen.UpdateBg##num##coord##Off(cnt); \ - } - UPDATE_BG_OFF(0, X) - UPDATE_BG_OFF(0, Y) - UPDATE_BG_OFF(1, X) - UPDATE_BG_OFF(1, Y) - UPDATE_BG_OFF(2, X) - UPDATE_BG_OFF(2, Y) - UPDATE_BG_OFF(3, X) - UPDATE_BG_OFF(3, Y) -#undef UPDATE_BG_OFF - -#define UPDATE_BG_REF(num, coord) \ - void UpdateBg##num##Ref##coord (int32_t cnt) \ - { \ - m_screen.UpdateBg##num##Ref##coord (cnt); \ - } - UPDATE_BG_REF(2, X) - UPDATE_BG_REF(2, Y) - UPDATE_BG_REF(3, X) - UPDATE_BG_REF(3, Y) -#undef UPDATE_BG_REF - - void OamWrite (uint32_t begin, uint32_t end) - { - m_screen.OamWrite(begin, end); - } - void OamWrite16 (uint32_t add) - { - m_screen.OamWrite16(add); - } - void OamWrite32 (uint32_t add) - { - m_screen.OamWrite32(add); - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - //syg::signal sig_vblank; - - private : - Graphics::Screen m_screen; - - void TimeEvent (); - - friend void Clock::Commit(); - }; -} - -#endif diff --git a/libmeteor/include/ameteor/memory.hpp b/libmeteor/include/ameteor/memory.hpp deleted file mode 100644 index f489a00694..0000000000 --- a/libmeteor/include/ameteor/memory.hpp +++ /dev/null @@ -1,162 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __MEMORY_H__ -#define __MEMORY_H__ - -#include "cartmem.hpp" -//XXX -#include "eeprom.hpp" - -#include -#include -#include -#include - -namespace AMeteor -{ - class Memory - { - public : - // in cycles - static const uint32_t CART_SAVE_TIME = 16*1024*1024; // 1 second - - enum CartType - { - CTYPE_UNKNOWN, - CTYPE_EEPROM512, - CTYPE_EEPROM8192, - CTYPE_FLASH64, - CTYPE_FLASH128, - CTYPE_SRAM - }; - enum CartError - { - CERR_NO_ERROR, - CERR_NOT_FOUND, - CERR_FAIL - }; - - Memory (); - ~Memory (); - - uint8_t GetCartType () const - { - return m_carttype; - } - // erases cartridge memory - void SetCartTypeFromSize (uint32_t size); - void SetCartType (uint8_t type); - //void SetCartFile (const char* filename) - //{ - // m_cartfile = filename; - //} - - void Reset (uint32_t params = ~0); - void ClearWbram (); - void ClearWcram (); - void ClearPalette (); - void ClearVram (); - void ClearOam (); - void SoftReset (); - - bool LoadBios (const char* filename); - void LoadBios (const uint8_t* data, uint32_t size); - void UnloadBios () - { - if (m_brom) - { - delete [] m_brom; - m_brom = NULL; - } - } - bool LoadRom (const char* filename); - void LoadRom (const uint8_t* data, uint32_t size); - //CartError LoadCart (); - bool LoadCart (const uint8_t* data, uint32_t size); - bool SaveCart (uint8_t** data, uint32_t* size); - void SaveCartDestroy(uint8_t* data); -#ifdef __LIBRETRO__ - bool LoadCartInferred (); -#endif - bool HasCart () const - { - return m_cart; - } - - void DeleteCart(); - - bool HasBios () const - { - return m_brom; - } - - uint8_t GetCycles16NoSeq (uint32_t add, uint32_t count); - uint8_t GetCycles16Seq (uint32_t add, uint32_t count); - uint8_t GetCycles32NoSeq (uint32_t add, uint32_t count); - uint8_t GetCycles32Seq (uint32_t add, uint32_t count); - void UpdateWaitStates (uint16_t waitcnt); - - uint8_t* GetRealAddress(uint32_t add, uint8_t size = 0); - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - uint8_t Peek8 (uint32_t add); - - // TODO make const members - uint8_t Read8 (uint32_t add); - uint16_t Read16 (uint32_t add); - uint32_t Read32 (uint32_t add); - - void Write8 (uint32_t add, uint8_t val); - void Write16 (uint32_t add, uint16_t val); - void Write32 (uint32_t add, uint32_t val); - - void WriteEepromDma (uint32_t src, uint16_t size); - //void ReadEepromDma (uint32_t dest, uint16_t size); - - void TimeEvent (); - - uint8_t* GetMemoryArea(int which); - - private : - // times for a 8 or 16 bits access - uint8_t m_memtime[0xF]; - // times for a sequential 8 or 16 bits access in GamePak ROM - uint8_t m_memtimeseq[0x3]; - - // General Internal Memory - uint8_t* m_brom; // BIOS - System ROM - uint8_t* m_wbram; // WRAM - On-board Work RAM - uint8_t* m_wcram; // WRAM - In-chip Work RAM - // Internal Display Memory - uint8_t* m_pram; // BG/OBJ Palette RAM - uint8_t* m_vram; // VRAM - Video RAM - uint8_t* m_oram; // OAM - OBJ Attributes - // External Memory (Game Pak) - uint8_t* m_rom; // Game Pake ROM/FlashROM (max 32MB) - - uint8_t m_carttype; - CartMem* m_cart; - //std::string m_cartfile; - - uint8_t ReadCart (uint16_t add); - void WriteCart (uint16_t add, uint8_t val); - }; -} - -#endif diff --git a/libmeteor/include/ameteor/sound.hpp b/libmeteor/include/ameteor/sound.hpp deleted file mode 100644 index 5575048970..0000000000 --- a/libmeteor/include/ameteor/sound.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __SOUND_H__ -#define __SOUND_H__ - -#include "audio/speaker.hpp" -#include "clock.hpp" -#include -#include -#include - -namespace AMeteor -{ - class Sound - { - public : - Sound (); - - void Reset (); - - inline Audio::Speaker& GetSpeaker(); - - void UpdateCntH1 (uint8_t val); - - inline void ResetSound1 (); - inline void ResetSound2 (); - inline void ResetSound4 (); - - inline void ResetSound1Envelope (); - inline void ResetSound2Envelope (); - inline void ResetSound4Envelope (); - - void TimerOverflow (uint8_t timernum); - - inline void SendDigitalA (uint8_t* buffer); - inline void SendDigitalB (uint8_t* buffer); - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - Audio::Speaker m_speaker; - - uint8_t m_fATimer, m_fBTimer; - - inline void TimerOverflowA (); - inline void TimerOverflowB (); - - void TimeEvent () - { - m_speaker.SoundTick(); - } - - friend void Clock::Commit (); - }; - - inline Audio::Speaker& Sound::GetSpeaker() - { - return m_speaker; - } - - inline void Sound::ResetSound1 () - { - m_speaker.ResetSound1(); - } - - inline void Sound::ResetSound2 () - { - m_speaker.ResetSound2(); - } - - inline void Sound::ResetSound4 () - { - m_speaker.ResetSound4(); - } - - inline void Sound::ResetSound1Envelope () - { - m_speaker.ResetSound1Envelope(); - } - - inline void Sound::ResetSound2Envelope () - { - m_speaker.ResetSound2Envelope(); - } - - inline void Sound::ResetSound4Envelope () - { - m_speaker.ResetSound4Envelope(); - } - - inline void Sound::SendDigitalA (uint8_t* buffer) - { - m_speaker.FillFifoA((int8_t*)buffer); - } - - inline void Sound::SendDigitalB (uint8_t* buffer) - { - m_speaker.FillFifoB((int8_t*)buffer); - } -} - -#endif diff --git a/libmeteor/include/ameteor/sram.hpp b/libmeteor/include/ameteor/sram.hpp deleted file mode 100644 index d937d75df7..0000000000 --- a/libmeteor/include/ameteor/sram.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __SRAM_H__ -#define __SRAM_H__ - -#include "cartmem.hpp" -#include -#include -#include -#include - -namespace AMeteor -{ - class Sram : public CartMem - { - public : - Sram (); - - void Reset (); - - bool Load (std::istream& f); - bool Save (std::ostream& f); - - uint8_t Read (uint16_t add) - { - return m_data[add % SIZE]; - } - bool Write (uint16_t add, uint8_t val) - { - m_data[add % SIZE] = val; - return true; - } - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - static const uint16_t SIZE = 0x8000; - }; -} - -#endif diff --git a/libmeteor/include/ameteor/swap.hpp b/libmeteor/include/ameteor/swap.hpp deleted file mode 100644 index ec9d992626..0000000000 --- a/libmeteor/include/ameteor/swap.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __SWAP_H__ -#define __SWAP_H__ - -namespace AMeteor -{ - inline uint16_t Swap16(uint16_t val) - { - return (val << 8) | (val >> 8); - } - - inline uint32_t Swap32(uint32_t val) - { - return (val << 24) | - ((val & 0x0000FF00) << 8) | - ((val & 0x00FF0000) >> 8) | - (val >> 24); - } -} - -#endif diff --git a/libmeteor/include/ameteor/timer.hpp b/libmeteor/include/ameteor/timer.hpp deleted file mode 100644 index ffdd055c51..0000000000 --- a/libmeteor/include/ameteor/timer.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __TIMER_H__ -#define __TIMER_H__ - -#include "clock.hpp" - -#include -#include -#include - -namespace AMeteor -{ - class Timer - { - public : - Timer (int8_t num, Timer* next) : - m_num(num), - m_reload(0), - m_count(0), - m_control(0), - m_next(next) - { - } - - void Reset (); - - void SetReload (uint16_t rel) - { - m_reload = rel; - } - void Reload (); - - uint16_t GetCount () const; - - bool SaveState (std::ostream& stream); - bool LoadState (std::istream& stream); - - private : - union Control - { - Control(uint16_t v) : - w(v) - { } - - uint16_t w; - struct - { - unsigned int prescaler : 2; - unsigned int countup : 1; - unsigned int unused1 : 3; - unsigned int irq : 1; - unsigned int start : 1; - unsigned int unused2 : 8; - } b; - }; - - const int8_t m_num; - uint16_t m_reload; - uint32_t m_count; - Control m_control; - - Timer* m_next; - - void TimeEvent (); - void Countup (); - - friend void Clock::Commit(); - }; -} - -#endif diff --git a/libmeteor/include/syg/signal.hpp b/libmeteor/include/syg/signal.hpp deleted file mode 100644 index 2a3dab12d8..0000000000 --- a/libmeteor/include/syg/signal.hpp +++ /dev/null @@ -1,389 +0,0 @@ -#ifndef SYG_connection_HPP -#define SYG_connection_HPP - -#include - -namespace syg -{ - -//------------------------------ -// connections -//------------------------------ - -template -class connection_base -{ - public: - virtual Tret call() const = 0; - virtual connection_base* clone() const = 0; - virtual ~connection_base() {} -}; - -template -class connection_base1 -{ - public: - virtual Tret call(Targ0) const = 0; - virtual connection_base1* clone() const = 0; - virtual ~connection_base1() {} -}; - -template -class connection_func : public connection_base -{ - public: - typedef Tret (*FuncPtr)(); - - connection_func(FuncPtr ptr): - _func(ptr) - {} - - Tret call() const - { - return _func(); - } - - connection_base* clone() const - { - return new connection_func(*this); - } - - private: - FuncPtr _func; -}; - -template -class connection_func1 : public connection_base1 -{ - public: - typedef Tret (*FuncPtr)(Targ0); - - connection_func1(FuncPtr ptr): - _func(ptr) - {} - - Tret call(Targ0 arg0) const - { - return _func(arg0); - } - - connection_base1* clone() const - { - return new connection_func1(*this); - } - - private: - FuncPtr _func; -}; - -template -class connection_meth : public connection_base -{ - public: - typedef Tobj TypeObj; - typedef Tret (Tobj::*FuncPtr)(); - - connection_meth(TypeObj& obj, FuncPtr ptr): - _obj(obj), - _meth(ptr) - {} - - Tret call() const - { - return (_obj.*_meth)(); - } - - connection_base* clone() const - { - return new connection_meth(*this); - } - - private: - Tobj& _obj; - FuncPtr _meth; -}; - -template -class connection_meth1 : public connection_base1 -{ - public: - typedef Tobj TypeObj; - typedef Tret (Tobj::*FuncPtr)(Targ0); - - connection_meth1(TypeObj& obj, FuncPtr ptr): - _obj(obj), - _meth(ptr) - {} - - Tret call(Targ0 arg0) const - { - return (_obj.*_meth)(arg0); - } - - connection_base1* clone() const - { - return new connection_meth1(*this); - } - - private: - Tobj& _obj; - FuncPtr _meth; -}; - -//------------------------------ -// slots -//------------------------------ - -template -class slot; - -template -class slot1; - -template -slot ptr_fun(Tret (*fun)()); - -template -slot mem_fun(Tobj& obj, Tret (Tobj::*fun)()); - -template -slot1 ptr_fun(Tret (*fun)(Targ0)); - -template -slot1 mem_fun(Tobj& obj, Tret (Tobj::*fun)(Targ0)); - -template -class slot -{ - public: - slot(): - _conn(0) - {} - slot(const slot& s) - { - *this = s; - } - ~slot() - { - delete _conn; - } - - slot& operator=(const slot& s) - { - if (s._conn) - _conn = s._conn->clone(); - else - _conn = 0; - - return *this; - } - - Tret call() const - { - return _conn->call(); - } - - Tret operator()() const - { - return call(); - } - - operator bool() const - { - return _conn; - } - - private: - connection_base* _conn; - - slot(const connection_base& conn): - _conn(conn.clone()) - {} - - friend slot ptr_fun(Tret (*fun)()); - - template - friend slot mem_fun(Tobj2& obj, Tret2 (Tobj2::*fun)()); -}; - -template -class slot1 -{ - public: - typedef slot1 SlotType; - - slot1(): - _conn(0) - {} - slot1(const SlotType& s) - { - *this = s; - } - ~slot1() - { - delete _conn; - } - - slot1& operator=(const SlotType& s) - { - if (s._conn) - _conn = s._conn->clone(); - else - _conn = 0; - - return *this; - } - - Tret call(Targ0 arg0) const - { - return _conn->call(arg0); - } - - Tret operator()(Targ0 arg0) const - { - return call(arg0); - } - - operator bool() const - { - return _conn; - } - - private: - typedef connection_base1 Connection; - - Connection* _conn; - - slot1(const Connection& conn): - _conn(conn.clone()) - {} - - friend SlotType ptr_fun(Tret (*fun)(Targ0)); - - template - friend slot1 mem_fun(Tobj2& obj, - Tret2 (Tobj2::*fun)(Targ02)); -}; - -template -inline slot ptr_fun(Tret (*fun)()) -{ - return slot(connection_func(fun)); -} - -template -inline slot mem_fun(Tobj& obj, Tret (Tobj::*fun)()) -{ - return slot(connection_meth(obj, fun)); -} - -template -inline slot1 ptr_fun(Tret (*fun)(Targ0)) -{ - return slot1(connection_func1(fun)); -} - -template -inline slot1 mem_fun(Tobj& obj, Tret (Tobj::*fun)(Targ0)) -{ - return slot1(connection_meth1(obj, fun)); -} - -//------------------------------ -// signals -//------------------------------ -/* -template -class signal; - -template -class connection -{ - public: - connection(): - _list(0) - { - } - - void disconnect() - { - _list->erase(_iter); - } - - private: - typedef std::list > List; - typedef typename List::iterator Iterator; - - List* _list; - Iterator _iter; - - connection(List* list, Iterator iter): - _list(list), - _iter(iter) - {} - - friend class signal; -}; - -template -class signal -{ - public: - connection connect(const slot s) - { - _slots.push_back(s); - return connection(&_slots, (++_slots.rbegin()).base()); - } - - Tret emit() const - { - for (typename Slots::const_iterator iter = _slots.begin(), - end = (++_slots.rbegin()).base(); - iter != end; ++iter) - iter->call(); - - return _slots.back().call(); - } - - Tret operator()() const - { - return emit(); - } - - private: - typedef std::list > Slots; - - Slots _slots; -}; - -template -class signal1 -{ - public: - void connect(const slot s) - { - _slots.push_back(s); - } - - Tret emit(Targ0 arg0) const - { - for (typename Slots::const_iterator iter = _slots.begin(); iter != _slots.end() - 1; ++iter) - iter->call(); - - return _slots.back().call(arg0); - } - - Tret operator()(Targ0 arg0) const - { - return emit(arg0); - } - - private: - typedef std::list > Slots; - - Slots _slots; -}; -*/ -} // namespace syg - -#endif diff --git a/libmeteor/libmeteor.sln b/libmeteor/libmeteor.sln deleted file mode 100644 index f9def63ac7..0000000000 --- a/libmeteor/libmeteor.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}") = "libmeteor", "libmeteor.vcxproj", "{EE01E7C1-6FC4-497F-82CC-C7C64E3BF9D1}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EE01E7C1-6FC4-497F-82CC-C7C64E3BF9D1}.Debug|Win32.ActiveCfg = Debug|Win32 - {EE01E7C1-6FC4-497F-82CC-C7C64E3BF9D1}.Debug|Win32.Build.0 = Debug|Win32 - {EE01E7C1-6FC4-497F-82CC-C7C64E3BF9D1}.Release|Win32.ActiveCfg = Release|Win32 - {EE01E7C1-6FC4-497F-82CC-C7C64E3BF9D1}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libmeteor/libmeteor.vcxproj b/libmeteor/libmeteor.vcxproj deleted file mode 100644 index 65990cded7..0000000000 --- a/libmeteor/libmeteor.vcxproj +++ /dev/null @@ -1,173 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {EE01E7C1-6FC4-497F-82CC-C7C64E3BF9D1} - Win32Proj - libmeteor - - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - false - true - Unicode - - - - - - - - - - - - - true - $(DXSDK_DIR)Include;$(IncludePath);include;include\ameteor - - - false - $(DXSDK_DIR)Include;$(IncludePath);include;include\ameteor - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBMETEOR_EXPORTS;%(PreprocessorDefinitions);METDEBUG;METDEBUGLOG;_ITERATOR_DEBUG_LEVEL=0;NO_MEMMEM - 4396;4800 - - - Windows - true - - - copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\output\dll\$(TargetFileName) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBMETEOR_EXPORTS;%(PreprocessorDefinitions);NO_MEMMEM - 4396;4800 - - - Windows - true - true - true - - - copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\output\dll\$(TargetFileName) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libmeteor/libmeteor.vcxproj.filters b/libmeteor/libmeteor.vcxproj.filters deleted file mode 100644 index d7e6d24e13..0000000000 --- a/libmeteor/libmeteor.vcxproj.filters +++ /dev/null @@ -1,288 +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 - - - {93df073d-6997-45f7-b85f-a285bca7b310} - - - {f134ab18-d00a-4652-ad25-5179aac22dbc} - - - {b152e4ad-8658-48a8-a214-3d9d1282fc70} - - - {63c54b4d-45ec-46f4-923e-38f486e19909} - - - {e3ba08fe-cf72-4aed-857c-697b3e437472} - - - {486541a1-445b-4012-8c31-218e65ea1e0b} - - - {66d5a4ba-681b-448c-8912-ecbb110d4896} - - - {a989399f-ba01-4804-ae68-ba5f363a2f9f} - - - {05542396-9b85-441b-beb8-8c49f126a881} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\audio - - - Source Files\audio - - - Source Files\audio - - - Source Files\audio - - - Source Files\audio - - - Source Files\graphics - - - Source Files\graphics - - - Source Files\graphics - - - Source Files\graphics - - - Source Files\graphics - - - Source Files\disassembler - - - Source Files\disassembler - - - Source Files\disassembler - - - Source Files\disassembler - - - Source Files\disassembler - - - Source Files\disassembler - - - Source Files\disassembler - - - Source Files\disassembler - - - Source Files\disassembler - - - Source Files\cinterface - - - - - Header Files - - - Header Files\syg - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor\audio - - - Header Files\ameteor\audio - - - Header Files\ameteor\audio - - - Header Files\ameteor\audio - - - Header Files\ameteor\audio - - - Header Files\ameteor\graphics - - - Header Files\ameteor\graphics - - - Header Files\ameteor\graphics - - - Header Files\ameteor\graphics - - - Header Files\ameteor\graphics - - - Header Files\ameteor\disassembler - - - Header Files\ameteor\disassembler - - - Header Files\ameteor\disassembler - - - Header Files\ameteor\disassembler - - - Header Files\ameteor\disassembler - - - Header Files\ameteor\disassembler - - - Header Files\ameteor\disassembler - - - Header Files\ameteor\disassembler - - - Header Files\ameteor\disassembler - - - Header Files\ameteor\disassembler - - - Header Files\ameteor - - - Header Files\ameteor - - - Header Files\ameteor - - - \ No newline at end of file diff --git a/libmeteor/source/ameteor.cpp b/libmeteor/source/ameteor.cpp deleted file mode 100644 index 76d9b187e4..0000000000 --- a/libmeteor/source/ameteor.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor.hpp" -#include "debug.hpp" -#include "globals.hpp" -#include -#include - -// TODO add version -#define SS_MAGIC_STRING ("AMeteor SaveState") -#define SS_MS_SIZE (sizeof(SS_MAGIC_STRING)-1) - -namespace AMeteor -{ - namespace - { - class AMeteor - { - public : - AMeteor () - { - Audio::InitNoise(); - } - } __ameteor; - } - - // the clock must be initialized first since there are devices like - // lcd which needs to set the timer - Clock _clock; - Io _io; - // the interpreter (which is in the cpu) takes io addresses, thus the - // cpu must be initialized after io - Interpreter _cpu; - Memory _memory; - Dma _dma; - // the lcd must be initialized after the memory since it takes - // pointers from it - Lcd _lcd; - // the sound must be initialized after the io since it takes references - // from it - Sound _sound; - // the keypad needs to take the vblank event from lcd, so it must be - // initialized after lcd - // it must also be initialized after io since it takes the keyinput - // reference - Keypad _keypad; - Timer _timer3(3, NULL); - Timer _timer2(2, &_timer3); - Timer _timer1(1, &_timer2); - Timer _timer0(0, &_timer1); - - void Reset (uint32_t units) - { -#define RESET(u, e) \ - if (units & UNIT_##e) \ - _##u.Reset(); - RESET(clock, CLOCK); - RESET(io, IO); - RESET(cpu, CPU); - RESET(dma, DMA); - RESET(lcd, LCD); - RESET(sound, SOUND); - RESET(keypad, KEYPAD); - RESET(timer0, TIMER0); - RESET(timer1, TIMER1); - RESET(timer2, TIMER2); - RESET(timer3, TIMER3); -#undef RESET - if (units & UNIT_MEMORY) - _memory.Reset(units); - } - - bool SaveState (const char* filename) - { - if (_cpu.IsRunning()) - return false; - - std::ostringstream ss; - - if (!SaveState(ss)) - return false; - - std::ofstream file(filename); - - if (!file) - return false; - - std::string buf = ss.str(); - if (!file.write(buf.c_str(), buf.length())) - return false; - - file.close(); - if (file.bad()) - return false; - - return true; - } - - bool LoadState (const char* filename) - { - if (_cpu.IsRunning()) - return false; - - std::istringstream ss; - { - std::ifstream file(filename); - if (!file) - return false; - - // 1Mo - std::vector buf(0x100000); - if (file.read((char*)&buf[0], 0x100000).bad()) - return false; - int nread = file.gcount(); - - file.close(); - if (file.bad()) - return false; - - ss.str(std::string((char*)&buf[0], nread)); - } - - return LoadState(ss); - } - - bool SaveState (std::ostream& stream) - { - if (_cpu.IsRunning()) - return false; - - SS_WRITE_DATA(SS_MAGIC_STRING, SS_MS_SIZE); - -#define SAVE(dev) \ - if (!dev.SaveState(stream)) \ - return false - SAVE(_clock); - SAVE(_io); - SAVE(_cpu); - SAVE(_memory); - SAVE(_dma); - SAVE(_lcd); - SAVE(_sound); - //SAVE(_keypad); - SAVE(_timer0); - SAVE(_timer1); - SAVE(_timer2); - SAVE(_timer3); -#undef SAVE - - return true; - } - - bool LoadState (std::istream& stream) - { - if (_cpu.IsRunning()) - return false; - - { - char buf[SS_MS_SIZE]; - SS_READ_DATA(buf, SS_MS_SIZE); - if (std::memcmp(buf, SS_MAGIC_STRING, SS_MS_SIZE)) - return false; - } - - -#define LOAD(dev) \ - if (!dev.LoadState(stream)) \ - return false - LOAD(_clock); - LOAD(_io); - LOAD(_cpu); - LOAD(_memory); - LOAD(_dma); - LOAD(_lcd); - LOAD(_sound); - //LOAD(_keypad); - LOAD(_timer0); - LOAD(_timer1); - LOAD(_timer2); - LOAD(_timer3); -#undef LOAD - - uint8_t xxx; - // if there is garbage at end of file - if (stream.read((char*)&xxx, 1)) - return false; - - return true; - } -} diff --git a/libmeteor/source/audio/dsound.cpp b/libmeteor/source/audio/dsound.cpp deleted file mode 100644 index 1f06f6a690..0000000000 --- a/libmeteor/source/audio/dsound.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/audio/dsound.hpp" -#include "../globals.hpp" -#include - -namespace AMeteor -{ - namespace Audio - { - DSound::DSound () : - m_rpos(0), - m_wpos(0), - m_size(0) - { - std::memset(m_buffer, 0, sizeof(m_buffer)); - } - - void DSound::FillFifo (int8_t* buffer) - { - int8_t* pmbuf = m_buffer + m_wpos; - // we copy 16 bytes of data - for (int8_t* pbuf = buffer; - pbuf < buffer + BUFFER_SIZE/2 && m_size < 32; ++pbuf, ++pmbuf) - { - if (pmbuf >= m_buffer + BUFFER_SIZE) - pmbuf = m_buffer; - - *pmbuf = *pbuf; - ++m_size; - } - - m_wpos = pmbuf - m_buffer; - } - - void DSound::FillFifo (int8_t sample) - { - if (m_size == 32) - return; - if (m_wpos == BUFFER_SIZE) - m_wpos = 0; - m_buffer[m_wpos++] = sample; - ++m_size; - } - - bool DSound::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_rpos); - SS_WRITE_VAR(m_wpos); - SS_WRITE_VAR(m_size); - - SS_WRITE_ARRAY(m_buffer); - - return true; - } - - bool DSound::LoadState (std::istream& stream) - { - SS_READ_VAR(m_rpos); - SS_READ_VAR(m_wpos); - SS_READ_VAR(m_size); - - SS_READ_ARRAY(m_buffer); - - return true; - } - } -} diff --git a/libmeteor/source/audio/sound1.cpp b/libmeteor/source/audio/sound1.cpp deleted file mode 100644 index da7b587e51..0000000000 --- a/libmeteor/source/audio/sound1.cpp +++ /dev/null @@ -1,202 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/audio/sound1.hpp" -#include "../globals.hpp" -#include - -namespace AMeteor -{ - namespace Audio - { - Sound1::Sound1 (uint16_t& cntl, uint16_t& cnth, uint16_t& cntx, - uint16_t freq) : - m_cntl(cntl), - m_cnth(cnth), - m_cntx(cntx), - m_on(false), - m_posP(0), - m_posS(0), - m_posE(0), - m_sample(0), - m_speriod(16*1024*1024/freq), - m_envelope(0), - m_length(0), - m_timed(false) - { - } - - void Sound1::Reset () - { - m_on = false; - m_timed = false; - m_length = 0; - m_envelope = 0; - m_posP = m_posE = m_posS = 0; - m_sample = 0; - } - - void Sound1::ResetSound () - { - m_on = true; - m_timed = (m_cntx & (0x1 << 14)); - m_length = (64 - (m_cnth & 0x3F)) * ((16*1024*1024)/256); - m_envelope = m_cnth >> 12; - m_posE = m_posS = 0; - } - - void Sound1::SoundTick () - { - // remember here that the processors runs at 16MHz = 16,777,216 cycles/s - // and this function is called normally at 44,100 Hz - - m_posP += m_speriod; - m_posS += m_speriod; - m_posE += m_speriod; - if (m_length > m_speriod) - m_length -= m_speriod; - else - { - if (m_timed) - m_on = false; - m_length = 0; - } - - // sweep time in cycles - // maximum is 917,504, so we need a 32 bits int - uint32_t sweeptime = ((m_cntl >> 4) & 0x7) * ((16*1024*1024)/128); - // period in cycles - // period = 16M/freq - // freq = 128K/(2048 - (SOUND1CNT_X & 0x7FF)) - // maximum is 262,144, so we need a 32 bits int - uint32_t period = - ((16*1024*1024) / (128*1024)) * (2048 - (m_cntx & 0x7FF)); - // frequency as contained in SOUND1CNT_X - uint16_t freq = m_cntx & 0x7FF; - - // we rewind posP - m_posP %= period; - - // the envelope now - // envelope step time in cycles - uint32_t steptime = ((m_cnth >> 8) & 0x7) * ((16*1024*1024)/64); - // the envelope can't do two steps between to calls of SoundTick - if (steptime && m_posE > steptime) - { - if (m_cnth & (0x1 << 11)) - { - if (m_envelope < 15) - ++m_envelope; - } - else - { - if (m_envelope > 0) - --m_envelope; - } - - m_posE -= steptime; - } - - // if the envelope is null or the sound is finished, no need to calculate - // anything - if (m_on && m_envelope) - { - // we set the sample according to the position in the current period - // and the wave duty cycle - switch ((m_cnth >> 6) & 0x3) - { - case 0: // 12.5% - m_sample = m_posP < period/8 ? 112 : -16; - break; - case 1: // 25% - m_sample = m_posP < period/4 ? 96 : -32; - break; - case 2: // 50% - m_sample = m_posP < period/2 ? 64 : -64; - break; - case 3: // 75% - m_sample = m_posP < (3*period)/4 ? 32 : -96; - break; - } - - m_sample = (((int16_t)m_sample) * m_envelope)/15; - } - else - m_sample = 0; - - // there can't have been more than one sweep between two call of - // SoundTick since SoundTick is called at least at a frequency of 4,000Hz - // (alsa can't output at a lower samplerate on my sound card) and sweeps - // happen at maximum at a frequency of 128Hz - - // if the channel is on and sweep is enabled and it's time to sweep - if (m_on && sweeptime && m_posS > sweeptime) - { - // n = sweep shifts (in SOUND1CNT_L) - if (m_cntl & (0x1 << 3)) - // F(t+1) = F(t) - F(t) / 2^n - freq = freq - freq / (1 << (m_cntl & 0x7)); - // freq won't go under 1 since when freq = 2, freq - freq / 2 (the - // minimum sweep shift) = 1 and then freq - freq / 2 = 1 - // because 1/2 = 0 - else - { - // F(t+1) = F(t) + F(t) / 2^n - freq = freq + freq / (1 << (m_cntl & 0x7)); - if (freq > 2047) - { - m_on = false; - freq = 2047; - } - } - - // we update the frequency in the cntx register - m_cntx = (m_cntx & 0xF800) | freq; - - // now we rewind posS - m_posS -= sweeptime; - } - } - - bool Sound1::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_on); - SS_WRITE_VAR(m_posP); - SS_WRITE_VAR(m_posS); - SS_WRITE_VAR(m_posE); - SS_WRITE_VAR(m_sample); - SS_WRITE_VAR(m_envelope); - SS_WRITE_VAR(m_length); - SS_WRITE_VAR(m_timed); - - return true; - } - - bool Sound1::LoadState (std::istream& stream) - { - SS_READ_VAR(m_on); - SS_READ_VAR(m_posP); - SS_READ_VAR(m_posS); - SS_READ_VAR(m_posE); - SS_READ_VAR(m_sample); - SS_READ_VAR(m_envelope); - SS_READ_VAR(m_length); - SS_READ_VAR(m_timed); - - return true; - } - } -} diff --git a/libmeteor/source/audio/sound2.cpp b/libmeteor/source/audio/sound2.cpp deleted file mode 100644 index fe1dd05a4b..0000000000 --- a/libmeteor/source/audio/sound2.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/audio/sound2.hpp" -#include "../globals.hpp" -#include - -namespace AMeteor -{ - namespace Audio - { - Sound2::Sound2 (uint16_t& cntl, uint16_t& cnth, uint16_t freq) : - m_cntl(cntl), - m_cnth(cnth), - m_on(false), - m_posP(0), - m_posE(0), - m_sample(0), - m_speriod(16*1024*1024/freq), - m_envelope(0), - m_length(0), - m_timed(false) - { - } - - void Sound2::Reset () - { - m_on = false; - m_timed = false; - m_length = 0; - m_envelope = 0; - m_posP = m_posE = 0; - m_sample = 0; - } - - void Sound2::ResetSound () - { - m_on = true; - m_timed = (m_cnth & (0x1 << 14)); - m_length = (64 - (m_cntl & 0x3F)) * ((16*1024*1024)/256); - m_envelope = m_cntl >> 12; - m_posE = 0; - } - - void Sound2::SoundTick () - { - // refer at sound1 to know how sound2 works - - m_posP += m_speriod; - m_posE += m_speriod; - if (m_length > m_speriod) - m_length -= m_speriod; - else - { - if (m_timed) - m_on = false; - m_length = 0; - } - - uint32_t period = - ((16*1024*1024) / (128*1024)) * (2048 - (m_cnth & 0x7FF)); - - m_posP %= period; - - uint32_t steptime = ((m_cntl >> 8) & 0x7) * ((16*1024*1024)/64); - if (steptime && m_posE > steptime) - { - if (m_cntl & (0x1 << 11)) - { - if (m_envelope < 15) - ++m_envelope; - } - else - { - if (m_envelope > 0) - --m_envelope; - } - - m_posE -= steptime; - } - - if (m_on && m_envelope) - { - switch ((m_cntl >> 6) & 0x3) - { - case 0: // 12.5% - m_sample = m_posP < period/8 ? 112 : -16; - break; - case 1: // 25% - m_sample = m_posP < period/4 ? 96 : -32; - break; - case 2: // 50% - m_sample = m_posP < period/2 ? 64 : -64; - break; - case 3: // 75% - m_sample = m_posP < (3*period)/4 ? 32 : -96; - break; - } - - m_sample = (((int16_t)m_sample) * m_envelope)/15; - } - else - m_sample = 0; - } - - bool Sound2::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_on); - SS_WRITE_VAR(m_posP); - SS_WRITE_VAR(m_posE); - SS_WRITE_VAR(m_sample); - SS_WRITE_VAR(m_envelope); - SS_WRITE_VAR(m_length); - SS_WRITE_VAR(m_timed); - - return true; - } - - bool Sound2::LoadState (std::istream& stream) - { - SS_READ_VAR(m_on); - SS_READ_VAR(m_posP); - SS_READ_VAR(m_posE); - SS_READ_VAR(m_sample); - SS_READ_VAR(m_envelope); - SS_READ_VAR(m_length); - SS_READ_VAR(m_timed); - - return true; - } - } -} diff --git a/libmeteor/source/audio/sound4.cpp b/libmeteor/source/audio/sound4.cpp deleted file mode 100644 index ef963ecd6e..0000000000 --- a/libmeteor/source/audio/sound4.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/audio/sound4.hpp" -#include "../globals.hpp" - -namespace AMeteor -{ - namespace Audio - { - static bool Noise7Stages[127]; - static bool Noise15Stages[32767]; - - void InitNoise () - { - unsigned short i = 0x7f; - bool* pNoise = Noise7Stages; - do - { - *pNoise++ = i & 1; - i = (i >> 1) | (((i & 1) << 6) ^ ((i & 2) << 5)); - } while (i != 0x7f); - - i = 0x7fff; - pNoise = Noise15Stages; - do - { - *pNoise++ = i & 1; - i = (i >> 1) | (((i & 1) << 14) ^ ((i & 2) << 13)); - } while (i != 0x7fff); - } - - Sound4::Sound4 (uint16_t& cntl, uint16_t& cnth, uint16_t freq) : - m_cntl(cntl), - m_cnth(cnth), - m_on(false), - m_posP(0), - m_posN(0), - m_posE(0), - m_sample(0), - m_speriod(16*1024*1024/freq), - m_envelope(0), - m_length(0), - m_timed(false), - m_div(4*8/2) - { - } - - void Sound4::Reset () - { - m_on = false; - m_timed = false; - m_length = 0; - m_envelope = 0; - m_posP = m_posE = m_posN = 0; - m_sample = 0; - m_div = 4*8/2; - } - - void Sound4::ResetSound () - { - m_on = true; - m_timed = (m_cnth & (0x1 << 14)); - m_length = (64 - (m_cntl & 0x3F)) * ((16*1024*1024)/256); - m_envelope = m_cntl >> 12; - m_div = ((m_cnth & 0x7) ? 4*8*(m_cnth & 0x7) : 4*8/2); - m_posE = m_posP = 0; - } - - void Sound4::SoundTick () - { - // rest is the number of processor clock ticks that were not yet taken by - // the noise clock divider (if the total divider is 8 and we have 10 - // ticks of the processor clock, only 8 were taken by the noise clock), - // the rest will be taken by the next call of SoundTick() - uint16_t rest = m_posP + m_speriod; - // advance is the number of noise ticks that have passed - uint16_t advance = m_posP + m_speriod; - - // time of one sound tick in cycles - uint32_t tick = m_div; - // if shift is 111X in binary - if (((m_cnth >> 5) & 0x7) == 0x7) - // not used - // assume 13 - tick *= 1 << 14; - else - tick *= (2 << ((m_cnth >> 4) & 0xF)); - - rest %= tick; - advance /= tick; - - m_posP = rest; - m_posN += advance; - // we have this modulo on posN so that when you switch from 15 stages to - // 7 stages and then you switch back, you won't restart the 15 stages - // pattern from the beginning - // don't know if GBA handle this like that - m_posN %= 32768; - - m_posE += m_speriod; - if (m_length > m_speriod) - m_length -= m_speriod; - else - { - if (m_timed) - m_on = false; - m_length = 0; - } - - uint32_t steptime = ((m_cntl >> 8) & 0x7) * ((16*1024*1024)/64); - if (steptime && m_posE > steptime) - { - if (m_cnth & (0x1 << 11)) - { - if (m_envelope < 15) - ++m_envelope; - } - else - { - if (m_envelope > 0) - --m_envelope; - } - - m_posE -= steptime; - } - - if (m_on && m_envelope) - { - if (m_cnth & (0x1 << 3)) - m_sample = Noise7Stages[m_posN % 128]; - else - m_sample = Noise15Stages[m_posN]; - - m_sample = m_sample ? 127 : -127; - m_sample = (((int16_t)m_sample) * m_envelope)/15; - } - else - m_sample = 0; - } - - bool Sound4::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_on); - SS_WRITE_VAR(m_posP); - SS_WRITE_VAR(m_posE); - SS_WRITE_VAR(m_posN); - SS_WRITE_VAR(m_sample); - SS_WRITE_VAR(m_envelope); - SS_WRITE_VAR(m_length); - SS_WRITE_VAR(m_timed); - SS_WRITE_VAR(m_div); - - return true; - } - - bool Sound4::LoadState (std::istream& stream) - { - SS_READ_VAR(m_on); - SS_READ_VAR(m_posP); - SS_READ_VAR(m_posE); - SS_READ_VAR(m_posN); - SS_READ_VAR(m_sample); - SS_READ_VAR(m_envelope); - SS_READ_VAR(m_length); - SS_READ_VAR(m_timed); - SS_READ_VAR(m_div); - - return true; - } - } -} diff --git a/libmeteor/source/audio/speaker.cpp b/libmeteor/source/audio/speaker.cpp deleted file mode 100644 index 13e6f1a3d3..0000000000 --- a/libmeteor/source/audio/speaker.cpp +++ /dev/null @@ -1,169 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/audio/speaker.hpp" -#include "../debug.hpp" - -namespace AMeteor -{ - namespace Audio - { - Speaker::Speaker (uint16_t& cnt1l, uint16_t& cnt1h, uint16_t& cnt1x, - uint16_t& cnt2l, uint16_t& cnt2h, - uint16_t& cnt4l, uint16_t& cnt4h, - uint16_t& cntl, uint16_t& cnth, uint16_t& cntx, uint16_t& bias) : - // XXX freq - m_sound1(cnt1l, cnt1h, cnt1x, 44100), - m_sound2(cnt2l, cnt2h, 44100), - m_sound4(cnt4l, cnt4h, 44100), - m_cntl(cntl), - m_cnth(cnth), - m_cntx(cntx), - m_bias(bias) - { - } - - Speaker::~Speaker () - { - } - - void Speaker::Reset () - { - m_sound1.Reset(); - m_sound2.Reset(); - m_sound4.Reset(); - m_dsa.Reset(); - m_dsb.Reset(); - } - - void Speaker::SoundTick () - { - int16_t f[2]; - - // if master is enabled - if (m_cntx & (0x1 << 7)) - { - m_sound1.SoundTick(); - if (m_sound1.IsOn()) - m_cntx |= 0x0001; - else - m_cntx &= 0xFFFE; - m_sound2.SoundTick(); - if (m_sound2.IsOn()) - m_cntx |= 0x0002; - else - m_cntx &= 0xFFFD; - m_sound4.SoundTick(); - if (m_sound4.IsOn()) - m_cntx |= 0x0008; - else - m_cntx &= 0xFFF7; - } - - // left - f[0] = MixSample (m_cntl >> 4, m_cnth >> 9); - // right - f[1] = MixSample (m_cntl, m_cnth >> 8); - - m_sig_frame(f); - } - - int16_t Speaker::MixSample (uint16_t cntl, uint8_t cnth) - { - int16_t sample; - - // if master is enabled - if (m_cntx & (0x1 << 7)) - { - int8_t s1, s2, s4; - s1 = (cntl & (0x1 << 8)) ? m_sound1.GetSample() : 0; - s2 = (cntl & (0x1 << 9)) ? m_sound2.GetSample() : 0; - s4 = (cntl & (0x1 << 11)) ? m_sound4.GetSample() : 0; - - int16_t dmg = s1 + s2 + s4; - dmg = (dmg * (cntl & 0x7)) / 7; - switch (m_cnth & 0x3) - { - case 0: // 25% - dmg /= 4; - break; - case 1: // 50% - dmg /= 2; - break; - case 2: // 100% - break; - case 3: // Prohibited - met_abort("Invalid SOUNDCNT_H sound # 1-4 volume"); - break; - } - - int16_t sA, sB; - sA = (cnth & (0x1 )) ? m_dsa.GetSample() : 0; - sB = (cnth & (0x1 << 4)) ? m_dsb.GetSample() : 0; - - if (!(m_cnth & (0x1 << 2))) - sA /= 2; - if (!(m_cnth & (0x1 << 3))) - sB /= 2; - - // TODO when finished put this all together on one line - sample = (sA + sB) * 4 + dmg; - } - else - sample = 0; - - sample += m_bias & 0x3FF; - if (sample < 0) - sample = 0; - else if (sample >= 0x400) - sample = 0x3FF; - sample -= 0x200; - sample <<= 6; - - return sample; - } - - bool Speaker::SaveState (std::ostream& stream) - { -#define WRITE(var) \ - if (!var.SaveState(stream)) \ - return false - WRITE(m_sound1); - WRITE(m_sound2); - WRITE(m_sound4); - WRITE(m_dsa); - WRITE(m_dsb); -#undef WRITE - - return true; - } - - bool Speaker::LoadState (std::istream& stream) - { -#define READ(var) \ - if (!var.LoadState(stream)) \ - return false - READ(m_sound1); - READ(m_sound2); - READ(m_sound4); - READ(m_dsa); - READ(m_dsb); -#undef READ - - return true; - } - } -} diff --git a/libmeteor/source/bios.cpp b/libmeteor/source/bios.cpp deleted file mode 100644 index 2480fb692c..0000000000 --- a/libmeteor/source/bios.cpp +++ /dev/null @@ -1,919 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/bios.hpp" -#include "ameteor/cpu.hpp" -#include "ameteor/memory.hpp" - -#include "globals.hpp" - -#include "debug.hpp" - -#include - -namespace AMeteor -{ - namespace Bios - { - static const int16_t sineTable[256] = { - (int16_t)0x0000, (int16_t)0x0192, (int16_t)0x0323, (int16_t)0x04B5, - (int16_t)0x0645, (int16_t)0x07D5, (int16_t)0x0964, (int16_t)0x0AF1, - (int16_t)0x0C7C, (int16_t)0x0E05, (int16_t)0x0F8C, (int16_t)0x1111, - (int16_t)0x1294, (int16_t)0x1413, (int16_t)0x158F, (int16_t)0x1708, - (int16_t)0x187D, (int16_t)0x19EF, (int16_t)0x1B5D, (int16_t)0x1CC6, - (int16_t)0x1E2B, (int16_t)0x1F8B, (int16_t)0x20E7, (int16_t)0x223D, - (int16_t)0x238E, (int16_t)0x24DA, (int16_t)0x261F, (int16_t)0x275F, - (int16_t)0x2899, (int16_t)0x29CD, (int16_t)0x2AFA, (int16_t)0x2C21, - (int16_t)0x2D41, (int16_t)0x2E5A, (int16_t)0x2F6B, (int16_t)0x3076, - (int16_t)0x3179, (int16_t)0x3274, (int16_t)0x3367, (int16_t)0x3453, - (int16_t)0x3536, (int16_t)0x3612, (int16_t)0x36E5, (int16_t)0x37AF, - (int16_t)0x3871, (int16_t)0x392A, (int16_t)0x39DA, (int16_t)0x3A82, - (int16_t)0x3B20, (int16_t)0x3BB6, (int16_t)0x3C42, (int16_t)0x3CC5, - (int16_t)0x3D3E, (int16_t)0x3DAE, (int16_t)0x3E14, (int16_t)0x3E71, - (int16_t)0x3EC5, (int16_t)0x3F0E, (int16_t)0x3F4E, (int16_t)0x3F84, - (int16_t)0x3FB1, (int16_t)0x3FD3, (int16_t)0x3FEC, (int16_t)0x3FFB, - (int16_t)0x4000, (int16_t)0x3FFB, (int16_t)0x3FEC, (int16_t)0x3FD3, - (int16_t)0x3FB1, (int16_t)0x3F84, (int16_t)0x3F4E, (int16_t)0x3F0E, - (int16_t)0x3EC5, (int16_t)0x3E71, (int16_t)0x3E14, (int16_t)0x3DAE, - (int16_t)0x3D3E, (int16_t)0x3CC5, (int16_t)0x3C42, (int16_t)0x3BB6, - (int16_t)0x3B20, (int16_t)0x3A82, (int16_t)0x39DA, (int16_t)0x392A, - (int16_t)0x3871, (int16_t)0x37AF, (int16_t)0x36E5, (int16_t)0x3612, - (int16_t)0x3536, (int16_t)0x3453, (int16_t)0x3367, (int16_t)0x3274, - (int16_t)0x3179, (int16_t)0x3076, (int16_t)0x2F6B, (int16_t)0x2E5A, - (int16_t)0x2D41, (int16_t)0x2C21, (int16_t)0x2AFA, (int16_t)0x29CD, - (int16_t)0x2899, (int16_t)0x275F, (int16_t)0x261F, (int16_t)0x24DA, - (int16_t)0x238E, (int16_t)0x223D, (int16_t)0x20E7, (int16_t)0x1F8B, - (int16_t)0x1E2B, (int16_t)0x1CC6, (int16_t)0x1B5D, (int16_t)0x19EF, - (int16_t)0x187D, (int16_t)0x1708, (int16_t)0x158F, (int16_t)0x1413, - (int16_t)0x1294, (int16_t)0x1111, (int16_t)0x0F8C, (int16_t)0x0E05, - (int16_t)0x0C7C, (int16_t)0x0AF1, (int16_t)0x0964, (int16_t)0x07D5, - (int16_t)0x0645, (int16_t)0x04B5, (int16_t)0x0323, (int16_t)0x0192, - (int16_t)0x0000, (int16_t)0xFE6E, (int16_t)0xFCDD, (int16_t)0xFB4B, - (int16_t)0xF9BB, (int16_t)0xF82B, (int16_t)0xF69C, (int16_t)0xF50F, - (int16_t)0xF384, (int16_t)0xF1FB, (int16_t)0xF074, (int16_t)0xEEEF, - (int16_t)0xED6C, (int16_t)0xEBED, (int16_t)0xEA71, (int16_t)0xE8F8, - (int16_t)0xE783, (int16_t)0xE611, (int16_t)0xE4A3, (int16_t)0xE33A, - (int16_t)0xE1D5, (int16_t)0xE075, (int16_t)0xDF19, (int16_t)0xDDC3, - (int16_t)0xDC72, (int16_t)0xDB26, (int16_t)0xD9E1, (int16_t)0xD8A1, - (int16_t)0xD767, (int16_t)0xD633, (int16_t)0xD506, (int16_t)0xD3DF, - (int16_t)0xD2BF, (int16_t)0xD1A6, (int16_t)0xD095, (int16_t)0xCF8A, - (int16_t)0xCE87, (int16_t)0xCD8C, (int16_t)0xCC99, (int16_t)0xCBAD, - (int16_t)0xCACA, (int16_t)0xC9EE, (int16_t)0xC91B, (int16_t)0xC851, - (int16_t)0xC78F, (int16_t)0xC6D6, (int16_t)0xC626, (int16_t)0xC57E, - (int16_t)0xC4E0, (int16_t)0xC44A, (int16_t)0xC3BE, (int16_t)0xC33B, - (int16_t)0xC2C2, (int16_t)0xC252, (int16_t)0xC1EC, (int16_t)0xC18F, - (int16_t)0xC13B, (int16_t)0xC0F2, (int16_t)0xC0B2, (int16_t)0xC07C, - (int16_t)0xC04F, (int16_t)0xC02D, (int16_t)0xC014, (int16_t)0xC005, - (int16_t)0xC000, (int16_t)0xC005, (int16_t)0xC014, (int16_t)0xC02D, - (int16_t)0xC04F, (int16_t)0xC07C, (int16_t)0xC0B2, (int16_t)0xC0F2, - (int16_t)0xC13B, (int16_t)0xC18F, (int16_t)0xC1EC, (int16_t)0xC252, - (int16_t)0xC2C2, (int16_t)0xC33B, (int16_t)0xC3BE, (int16_t)0xC44A, - (int16_t)0xC4E0, (int16_t)0xC57E, (int16_t)0xC626, (int16_t)0xC6D6, - (int16_t)0xC78F, (int16_t)0xC851, (int16_t)0xC91B, (int16_t)0xC9EE, - (int16_t)0xCACA, (int16_t)0xCBAD, (int16_t)0xCC99, (int16_t)0xCD8C, - (int16_t)0xCE87, (int16_t)0xCF8A, (int16_t)0xD095, (int16_t)0xD1A6, - (int16_t)0xD2BF, (int16_t)0xD3DF, (int16_t)0xD506, (int16_t)0xD633, - (int16_t)0xD767, (int16_t)0xD8A1, (int16_t)0xD9E1, (int16_t)0xDB26, - (int16_t)0xDC72, (int16_t)0xDDC3, (int16_t)0xDF19, (int16_t)0xE075, - (int16_t)0xE1D5, (int16_t)0xE33A, (int16_t)0xE4A3, (int16_t)0xE611, - (int16_t)0xE783, (int16_t)0xE8F8, (int16_t)0xEA71, (int16_t)0xEBED, - (int16_t)0xED6C, (int16_t)0xEEEF, (int16_t)0xF074, (int16_t)0xF1FB, - (int16_t)0xF384, (int16_t)0xF50F, (int16_t)0xF69C, (int16_t)0xF82B, - (int16_t)0xF9BB, (int16_t)0xFB4B, (int16_t)0xFCDD, (int16_t)0xFE6E - }; - - void Bios000h () - { - debug("Bios entry point"); - R(13) = 0x03007FE0; - R(15) = 0x08000004; - CPU.SwitchToMode(Cpu::M_IRQ); - R(13) = 0x03007FA0; - CPU.SwitchToMode(Cpu::M_SYS); - R(13) = 0x03007F00; - ICPSR.irq_d = false; - IO.Write8(Io::POSTFLG, 0x01); - } - - void Bios008h () - { - // if we are here, we should be in SVC mode (0x13) - // store the spsr, r11, r12 and r14 on the stack - uint32_t baseadd = R(13) - (4*4), add = (baseadd & 0xFFFFFFFC); - MEM.Write32(add , SPSR); - MEM.Write32(add += 4, R(11)); - MEM.Write32(add += 4, R(12)); - MEM.Write32(add + 4, R(14)); - R(13) = baseadd; - - uint8_t swiComment = MEM.Read8(R(14) - 2); - - // put 0x1F in cpsr but don't touch to the irq disable bit - CPU.SwitchToMode(0x1F); - CPSR = 0x0000001F | (CPSR & (0x1 << 7)); - CPU.UpdateICpsr(); - - // store r11 and r14 (of the user mode) on the stack - baseadd = R(13) - (2*4); add = (baseadd & 0xFFFFFFFC); - MEM.Write32(add , R(11)); - MEM.Write32(add + 4, R(14)); - R(13) = baseadd; - - R(14) = 0x168; - - debug("Software IRQ start"); - switch (swiComment) - { - case 0x04: - IntrWait(); - break; - case 0x05: - VBlankIntrWait(); - break; - default: - met_abort("not implemented : " << (int)swiComment); - break; - } - } - - void Bios168h () - { - uint32_t add = R(13) & 0xFFFFFFFC; - R( 2) = MEM.Read32(add ); - R(14) = MEM.Read32(add += 4); - R(13) += 2*4; - - // SVC with fiq and irq disabled - CPU.SwitchToMode(0x13); // SVC - CPSR = 0x000000D3; - CPU.UpdateICpsr(); - add = R(13) & 0xFFFFFFFC; - - SPSR = MEM.Read32(add); - - R(11) = MEM.Read32(add += 4); - R(12) = MEM.Read32(add += 4); - R(14) = MEM.Read32(add + 4); - R(13) += 4*4; - - // FIXME this works (for thumb) ? - if (CPU.Spsr().b.thumb) - R(15) = R(14) + 2; - else - R(15) = R(14) + 4; - - debug("Software IRQ end"); - CPU.SwitchModeBack(); - } - - void Bios018h () - { - debug("IRQ start"); - // stmfd r13!,r0-r3,r12,r14 - uint32_t baseadd = R(13) - (6*4), add = (baseadd & 0xFFFFFFFC); - MEM.Write32(add , R( 0)); - MEM.Write32(add += 4, R( 1)); - MEM.Write32(add += 4, R( 2)); - MEM.Write32(add += 4, R( 3)); - MEM.Write32(add += 4, R(12)); - MEM.Write32(add + 4, R(14)); - - R(13) = baseadd; - - // add r14,r15,0h - R(14) = 0x00000130; - - R(15) = MEM.Read32(0x03007FFC) + 4; - } - - void Bios130h () - { - debug("IRQ end"); - // ldmfd r13!,r0-r3,r12,r14 - uint32_t add = R(13) & 0xFFFFFFFC; - R( 0) = MEM.Read32(add ); - R( 1) = MEM.Read32(add += 4); - R( 2) = MEM.Read32(add += 4); - R( 3) = MEM.Read32(add += 4); - R(12) = MEM.Read32(add += 4); - R(14) = MEM.Read32(add + 4); - - R(13) += 6*4; - - // subs r15,r14,4h - R(15) = R(14); - if (CPU.Spsr().b.thumb) - R(15) -= 2; - - CPU.SwitchModeBack(); - - // XXX FIXME, usefull ? test on breath of fire ! - /*if (FLAG_T) - R(15) &= 0xFFFFFFFE; - else - R(15) &= 0xFFFFFFFC;*/ - } - - void SoftReset () - { - CPU.SoftReset (); - if (MEM.Read8(0x03007FFA)) - R(15) = 0x02000004; - else - R(15) = 0x08000004; - - MEM.SoftReset (); - } - - void RegisterRamReset () - { - IO.Write16(Io::DISPCNT, 0x0080); - uint8_t flagRes = R(0); - if (flagRes & (0x1 )) - MEM.ClearWbram(); - if (flagRes & (0x1 << 1)) - MEM.ClearWcram(); - if (flagRes & (0x1 << 2)) - MEM.ClearPalette(); - if (flagRes & (0x1 << 3)) - MEM.ClearVram(); - if (flagRes & (0x1 << 4)) - MEM.ClearOam(); - if (flagRes & (0x1 << 5)) - IO.ClearSio (); - if (flagRes & (0x1 << 6)) - IO.ClearSound (); - if (flagRes & (0x1 << 7)) - IO.ClearOthers (); - } - - void Halt () - { - IO.Write8(Io::HALTCNT, 0); - } - - void IntrWait () - { - // FIXME ugly - R(13) -= 8; - MEM.Write32(R(13) & 0xFFFFFFFC, R(4)); - MEM.Write32((R(13)+4) & 0xFFFFFFFC, R(14)); - - uint16_t& intFlags = *(uint16_t*)MEM.GetRealAddress(0x03007FF8); - - if (R(0)) - { - if (intFlags & R(1)) - intFlags = (intFlags & R(1)) ^ intFlags; - else - FLAG_Z = 1; - IO.Write16(Io::IME, 1); - } - - IO.Write8(Io::HALTCNT, 0); - - // return address (after IRQ) - R(15) = 0x33C; - - debug("IntrWait start"); - } - - void Bios338h () - { - uint16_t& intFlags = *(uint16_t*)MEM.GetRealAddress(0x03007FF8); - - if (!(intFlags & R(1))) - { - IO.Write16(Io::IME, 1); - IO.Write8(Io::HALTCNT, 0); - } - else - { - intFlags = (intFlags & R(1)) ^ intFlags; - IO.Write16(Io::IME, 1); - - // FIXME ugly - R(4) = MEM.Read32(R(13) & 0xFFFFFFFC); - R(14) = MEM.Read32((R(13)+4) & 0xFFFFFFFC); - R(13) += 8; - - // should lead to 0x168 - R(15) = R(14)+4; - } - - debug("IntWait end"); - } - - void VBlankIntrWait () - { - R(0) = 1; - R(1) = 1; - IntrWait(); - } - - void Div () - { - if (!R(1)) - met_abort("Div by 0"); - - int32_t number = R(0), denom = R(1); - - int32_t div = number / denom; - R(0) = div; - R(1) = number % denom; - R(3) = div < 0 ? -div : div; - } - - void DivArm () - { - uint32_t tmp = R(0); - R(0) = R(1); - R(1) = tmp; - Div(); - } - - void Sqrt () - { - R(0) = (uint16_t)sqrt((float)R(0)); - } - - void ArcTan () - { - int32_t a = -(((int32_t)R(0) * R(0)) >> 14); - int32_t b = 0xA9; - b = ((a * b) >> 14) + 0x0390; - b = ((a * b) >> 14) + 0x091C; - b = ((a * b) >> 14) + 0x0FB6; - b = ((a * b) >> 14) + 0X16AA; - b = ((a * b) >> 14) + 0X2081; - b = ((a * b) >> 14) + 0X3651; - b = ((a * b) >> 14) + 0XA2F9; - - R(0) = (R(0) * b) >> 16; - } - - void ArcTan2 () - { - int16_t x = R(0), y = R(1); - if (y) - if (x) - if (abs(x) < abs(y)) - { - R(0) <<= 14; - Div(); - ArcTan(); - R(0) = 0x4000 - R(0); - if (y < 0) - R(0) += 0x8000; - } - else - { - uint32_t r1 = R(1); - R(1) = R(0); - R(0) = r1 << 14; - Div(); - ArcTan(); - if (x < 0) - R(0) += 0x8000; - else if (y < 0) - R(0) += 0x10000; - } - else - if (y < 0) - R(0) = 0xc000; - else - R(0) = 0x4000; - else - if (x < 0) - R(0) = 0x8000; - else - R(0) = 0x0000; - } - - void CpuSet () - { - if (R(2) & (0x1 << 26)) // 32 bits - { - if (R(2) & (0x1 << 24)) // fixed source address - { - uint32_t source = MEM.Read32(R(0) & 0xFFFFFFFC); - uint32_t address = R(1) & 0xFFFFFFFC; - for (uint32_t count = (R(2) & 0x001FFFFF); count; --count) - { - MEM.Write32(address, source); - address += 4; - } - } - else // copy - { - uint32_t src = R(0) & 0xFFFFFFFC; - uint32_t dest = R(1) & 0xFFFFFFFC; - for (uint32_t count = (R(2) & 0x001FFFFF); count; --count) - { - MEM.Write32(dest, MEM.Read32(src)); - src += 4; - dest += 4; - } - } - } - else // 16 bits - { - if (R(2) & (0x1 << 24)) // fixed source address - { - uint16_t source = MEM.Read16(R(0)); - uint32_t address = R(1); - for (uint32_t count = (R(2) & 0x001FFFFF); count; --count) - { - MEM.Write16(address, source); - address += 2; - } - } - else // copy - { - uint32_t src = R(0); - uint32_t dest = R(1); - for (uint32_t count = (R(2) & 0x001FFFFF); count; --count) - { - MEM.Write16(dest, MEM.Read16(src)); - src += 2; - dest += 2; - } - } - } - } - - void CpuFastSet () - { - if (R(2) & (0x1 << 24)) // fixed source address - { - uint32_t source = MEM.Read32(R(0)); - uint32_t address = R(1); - for (uint32_t count = (R(2) & 0x001FFFFF); count; --count) - { - MEM.Write32(address, source); - address += 4; - } - } - else // copy - { - uint32_t src = R(0); - uint32_t dest = R(1); - for (uint32_t count = (R(2) & 0x001FFFFF); count; --count) - { - MEM.Write32(dest, MEM.Read32(src)); - src += 4; - dest += 4; - } - } - } - - void BgAffineSet () - { - uint32_t src = R(0); - uint32_t dest = R(1); - uint32_t num = R(2); - - int32_t cx, cy; - int16_t dix, diy, rx, ry; - uint16_t alpha; - - int32_t cos, sin; - int16_t dx, dmx, dy, dmy; - - while (num--) - { - cx = MEM.Read32(src); - src += 4; - cy = MEM.Read32(src); - src += 4; - dix = MEM.Read16(src); - src += 2; - diy = MEM.Read16(src); - src += 2; - rx = MEM.Read16(src); - src += 2; - ry = MEM.Read16(src); - src += 2; - alpha = MEM.Read16(src) >> 8; - src += 2; - - sin = sineTable[alpha]; - cos = sineTable[(alpha + 0x40) & 0xFF]; - - dx = (rx * cos) >> 14; - dmx = -((rx * sin) >> 14); - dy = (ry * sin) >> 14; - dmy = (ry * cos) >> 14; - - MEM.Write16(dest, dx); - dest += 2; - MEM.Write16(dest, dmx); - dest += 2; - MEM.Write16(dest, dy); - dest += 2; - MEM.Write16(dest, dmy); - dest += 2; - - MEM.Write32(dest, cx - dx * dix - dmx * diy); - dest += 4; - MEM.Write32(dest, cy - dy * dix - dmy * diy); - dest += 4; - } - } - - void ObjAffineSet () - { - uint32_t src = R(0); - uint32_t dest = R(1); - uint32_t num = R(2); - uint32_t off = R(3); - - int16_t rx, ry; - uint16_t alpha; - - int32_t cos, sin; - int16_t dx, dmx, dy, dmy; - - while (num--) - { - rx = MEM.Read16(src); - src += 2; - ry = MEM.Read16(src); - src += 2; - alpha = MEM.Read16(src) >> 8; - src += 4; - - sin = sineTable[alpha]; - cos = sineTable[(alpha + 0x40) & 0xFF]; - - dx = (rx * cos) >> 14; - dmx = -((rx * sin) >> 14); - dy = (ry * sin) >> 14; - dmy = (ry * cos) >> 14; - - MEM.Write16(dest, dx); - dest += off; - MEM.Write16(dest, dmx); - dest += off; - MEM.Write16(dest, dy); - dest += off; - MEM.Write16(dest, dmy); - dest += off; - } - } - - void LZ77UnCompWram () - { - uint32_t src = R(0); - uint32_t header = MEM.Read32(src); - src += 4; - if (((header >> 4) & 0xF) != 1) - met_abort("This is not LZ77 data"); - uint32_t size = header >> 8; - debug("LZ77UnCompWram from " << IOS_ADD << R(0) << " to " << IOS_ADD << R(1) << ", len : " << size); - uint32_t dest = R(1); - uint8_t flags; - uint16_t block; - uint8_t blocklen; - uint32_t realaddr; - - // for each block of a flags byte + 8 blocks - while (true) - { - flags = MEM.Read8(src++); - - for (uint8_t i = 0; i < 8; ++i) - { - // compressed block of 2 bytes - if (flags & 0x80) - { - block = MEM.Read8(src) << 8 | MEM.Read8(src+1); - src += 2; - blocklen = (block >> 12) + 3; - realaddr = dest - (block & 0x0FFF) - 1; - for(uint16_t j = 0; j < blocklen; ++j) - { - MEM.Write8(dest++, MEM.Read8(realaddr++)); - - --size; - if(size == 0) - { - size = header >> 8; - return; - } - } - } - // uncompressed block of 1 byte - else - { - MEM.Write8(dest++, MEM.Read8(src++)); - - --size; - if (size == 0) - { - size = header >> 8; - return; - } - } - - flags <<= 1; - } - } - } - - void LZ77UnCompVram () - { - uint32_t src = R(0); - uint32_t header = MEM.Read32(src); - src += 4; - if (((header >> 4) & 0xF) != 1) - met_abort("This is not LZ77 data"); - uint32_t size = header >> 8; - debug("LZ77UnCompVram from " << IOS_ADD << R(0) << " to " << IOS_ADD << R(1) << ", len : " << size); - uint32_t dest = R(1); - uint8_t flags; - uint16_t out = 0; - uint8_t shift = 0; - uint16_t block; - uint8_t blocklen; - uint32_t realaddr; - - // for each block of a flags byte + 8 blocks - while (true) - { - flags = MEM.Read8(src++); - - for (uint8_t i = 0; i < 8; ++i) - { - // compressed block of 2 bytes - if (flags & 0x80) - { - block = MEM.Read8(src) << 8 | MEM.Read8(src+1); - src += 2; - blocklen = (block >> 12) + 3; - realaddr = dest + (shift/8) - (block & 0x0FFF) - 1; - for(uint16_t j = 0; j < blocklen; ++j) { - out |= MEM.Read8(realaddr++) << shift; - shift += 8; - - if(shift == 16) { - MEM.Write16(dest, out); - dest += 2; - out = 0; - shift = 0; - } - - --size; - if(size == 0) - { - size = header >> 8; - return; - } - } - } - // uncompressed block of 1 byte - else - { - out |= MEM.Read8(src++) << shift; - shift += 8; - - if (shift == 16) - { - MEM.Write16(dest, out); - dest += 2; - shift = 0; - out = 0; - } - - --size; - if (size == 0) - { - size = header >> 8; - return; - } - } - - flags <<= 1; - } - } - } - - void HuffUnComp () - { - uint32_t src = R(0) & 0xFFFFFFFC; - uint32_t dest = R(1); - uint32_t header = MEM.Read32(src); - src += 4; - if (((header >> 4) & 0xF) != 2) - met_abort("This is not Huffman data"); - uint8_t blockLen = header & 0xF; - uint32_t size = header >> 8; - if (size % 4) - met_abort("Size not multiple of 4 in HuffUnComp"); - uint32_t treeStart = src + 1; - src += 2 + MEM.Read8(src) * 2; - - uint32_t cData = MEM.Read32(src); - src += 4; - uint32_t mask = 0x80000000; - uint32_t treePos = treeStart; - uint8_t node = MEM.Read8(treePos); - bool endNode = false; - uint32_t oData = 0; - uint8_t oShift = 0; - - while (size) - { - treePos = (treePos & 0xFFFFFFFE) + (node & 0x3F) * 2 + 2; - if (cData & mask) - { - ++treePos; - if (node & (0x1 << 6)) - endNode = true; - } - else - { - if (node & (0x1 << 7)) - endNode = true; - } - node = MEM.Read8(treePos); - - if (endNode) - { - oData |= ((uint32_t)node) << oShift; - oShift += blockLen; - - if (oShift >= 32) - { - MEM.Write32(dest, oData); - dest += 4; - size -= 4; - - oShift -= 32; - if (oShift) - oData = node >> (8 - oShift); - else - oData = 0; - } - endNode = false; - treePos = treeStart; - node = MEM.Read8(treePos); - } - - mask >>= 1; - if (!mask) - { - cData = MEM.Read32(src); - src += 4; - mask = 0x80000000; - } - } - } - - void RLUnCompWram () - { - uint32_t src = R(0); - uint32_t header = MEM.Read32(src); - src += 4; - if (((header >> 4) & 0xF) != 3) - met_abort("This is not RL data"); - uint32_t size = header >> 8; - debug("RLUnCompWram from " << IOS_ADD << R(0) << " to " << IOS_ADD << R(1) << ", len : " << size); - uint32_t dest = R(1); - uint8_t flags; - uint8_t block; - uint8_t blocklen; - - // for each block - while (true) - { - flags = MEM.Read8(src++); - blocklen = flags & 0x7F; - - // compressed block - if (flags & 0x80) - { - blocklen += 3; - block = MEM.Read8(src++); - - for(uint8_t i = 0; i < blocklen; ++i) { - MEM.Write8(dest++, block); - - --size; - if(size == 0) - { - size = header >> 8; - return; - } - } - } - // uncompressed block - else - { - blocklen += 1; - - for (uint8_t i = 0; i < blocklen; ++i) - { - MEM.Write8(dest++, MEM.Read8(src++)); - - --size; - if (size == 0) - { - size = header >> 8; - return; - } - } - } - } - } - - void RLUnCompVram () - { - uint32_t src = R(0); - uint32_t header = MEM.Read32(src); - src += 4; - if (((header >> 4) & 0xF) != 3) - met_abort("This is not RL data"); - uint32_t size = header >> 8; - debug("RLUnCompVram from " << IOS_ADD << R(0) << " to " << IOS_ADD << R(1) << ", len : " << size); - uint32_t dest = R(1); - uint8_t flags; - uint16_t out = 0; - uint8_t shift = 0; - uint8_t block; - uint8_t blocklen; - - // for each block - while (true) - { - flags = MEM.Read8(src++); - blocklen = flags & 0x7F; - - // compressed block - if (flags & 0x80) - { - blocklen += 3; - block = MEM.Read8(src++); - - for(uint8_t i = 0; i < blocklen; ++i) { - out |= block << shift; - shift += 8; - - if(shift == 16) { - MEM.Write16(dest, out); - dest += 2; - out = 0; - shift = 0; - } - - --size; - if(size == 0) - { - size = header >> 8; - return; - } - } - } - // uncompressed block - else - { - blocklen += 1; - - for (uint8_t i = 0; i < blocklen; ++i) - { - out |= MEM.Read8(src++) << shift; - shift += 8; - - if (shift == 16) - { - MEM.Write16(dest, out); - dest += 2; - shift = 0; - out = 0; - } - - --size; - if (size == 0) - { - size = header >> 8; - return; - } - } - } - } - } - } -} diff --git a/libmeteor/source/cartmem.cpp b/libmeteor/source/cartmem.cpp deleted file mode 100644 index 37fa9d78ad..0000000000 --- a/libmeteor/source/cartmem.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/cartmem.hpp" -#include "globals.hpp" - -namespace AMeteor -{ -#ifdef __LIBRETRO__ - uint8_t CartMemData[CartMem::MAX_SIZE+4]; -#endif - - CartMem::CartMem() : -#ifdef __LIBRETRO__ - m_data(CartMemData) -#else - m_data(new uint8_t[MAX_SIZE+4]) -#endif - { - } - - CartMem::~CartMem() - { -#ifndef __LIBRETRO__ - delete [] m_data; -#endif - } - - bool CartMem::SaveState (std::ostream& stream) - { - stream.write((char*)m_data, MAX_SIZE); - SS_WRITE_VAR(m_size); - - return true; - } - - bool CartMem::LoadState (std::istream& stream) - { - stream.read((char*)m_data, MAX_SIZE); - SS_READ_VAR(m_size); - - return true; - } -} diff --git a/libmeteor/source/clock.cpp b/libmeteor/source/clock.cpp deleted file mode 100644 index 66201b1813..0000000000 --- a/libmeteor/source/clock.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/clock.hpp" -#include "globals.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" - -namespace AMeteor -{ - void Clock::Reset () - { - // lcd is enabled by default - m_first = m_count = m_cycles = m_lcd = m_sound = 0; - // timers and battery are disabled by default - /*m_battery =*/ m_timer[0] = m_timer[1] = m_timer[2] = m_timer[3] = - INT_MAX; - } - - void Clock::Commit () - { - unsigned short tocommit; - - //m_count += m_cycles; - - // this loop is here because a timer can trigger a dma which will take a - // long time, during this time the lcd must draw and the timers continue - while (m_cycles >= m_first) - { - m_count += m_cycles; - - tocommit = m_cycles; - m_cycles = 0; - - m_lcd -= tocommit; - while (m_lcd <= 0) - LCD.TimeEvent(); - - m_sound -= tocommit; - while (m_sound <= 0) - { - SOUND.TimeEvent(); - // XXX freq - m_sound += SOUND_PERIOD; - } - -#define COMMIT(dev, obj) \ - if (m_##dev != INT_MAX) \ - { \ - m_##dev -= tocommit; \ - while (m_##dev <= 0) \ - obj.TimeEvent(); \ - } - COMMIT(timer[0], TIMER0) - COMMIT(timer[1], TIMER1) - COMMIT(timer[2], TIMER2) - COMMIT(timer[3], TIMER3) - //COMMIT(battery, MEM) -#undef COMMIT - - SetFirst(); - } - } - - void Clock::WaitForNext () - { - m_cycles = m_first; - Commit(); - } - -#define SETFIRST(dev) \ - if (m_##dev < m_first) \ - m_first = m_##dev - void Clock::SetFirst () - { - m_first = m_lcd; - SETFIRST(timer[0]); - SETFIRST(timer[1]); - SETFIRST(timer[2]); - SETFIRST(timer[3]); - SETFIRST(sound); - //SETFIRST(battery); - } -#undef SETFIRST - - bool Clock::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_cycles); - SS_WRITE_VAR(m_first); - SS_WRITE_VAR(m_lcd); - SS_WRITE_VAR(m_sound); - //SS_WRITE_VAR(m_battery); - - SS_WRITE_ARRAY(m_timer); - - return true; - } - - bool Clock::LoadState (std::istream& stream) - { - SS_READ_VAR(m_cycles); - SS_READ_VAR(m_first); - SS_READ_VAR(m_lcd); - SS_READ_VAR(m_sound); - //SS_READ_VAR(m_battery); - - SS_READ_ARRAY(m_timer); - - return true; - } -} diff --git a/libmeteor/source/cpu.cpp b/libmeteor/source/cpu.cpp deleted file mode 100644 index 0f97835159..0000000000 --- a/libmeteor/source/cpu.cpp +++ /dev/null @@ -1,447 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/cpu.hpp" -#include "ameteor/bios.hpp" -#include "globals.hpp" -#include "cpu_globals.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" - -#include - -namespace AMeteor -{ - Cpu::Cpu () - { - Reset(); - } - - void Cpu::Reset () - { - std::memset(&m_st, 0, sizeof(m_st)); - R(15) = 0x00000004; - m_st.icpsr.mode = M_SVC; - m_st.icpsr.fiq_d = true; - m_st.icpsr.irq_d = true; - } - - void Cpu::SoftReset () - { - std::memset(&m_st, 0, sizeof(m_st)); - R(13) = 0x03007F00; - R(15) = 0x08000004; - m_st.irq_r[0] = 0x03007FA0; // R13 - m_st.svc_r[0] = 0x03007FE0; // R13 - m_st.icpsr.mode = 0x1F; - m_st.icpsr.fiq_d = true; - } - - void Cpu::UpdateICpsr () - { - m_st.icpsr.mode = m_st.cpsr.b.mode; - m_st.icpsr.irq_d = m_st.cpsr.b.irq_d; - m_st.icpsr.fiq_d = m_st.cpsr.b.fiq_d; - m_st.icpsr.thumb = m_st.cpsr.b.thumb; - m_st.icpsr.s_overflow = m_st.cpsr.b.s_overflow; - m_st.icpsr.f_overflow = m_st.cpsr.b.f_overflow; - m_st.icpsr.f_carry = m_st.cpsr.b.f_carry; - m_st.icpsr.f_zero = m_st.cpsr.b.f_zero; - m_st.icpsr.f_sign = m_st.cpsr.b.f_sign; - } - - void Cpu::UpdateCpsr () - { - m_st.cpsr.b.mode = m_st.icpsr.mode; - m_st.cpsr.b.irq_d = m_st.icpsr.irq_d; - m_st.cpsr.b.fiq_d = m_st.icpsr.fiq_d; - m_st.cpsr.b.thumb = m_st.icpsr.thumb; - m_st.cpsr.b.s_overflow = m_st.icpsr.s_overflow; - m_st.cpsr.b.f_overflow = m_st.icpsr.f_overflow; - m_st.cpsr.b.f_carry = m_st.icpsr.f_carry; - m_st.cpsr.b.f_zero = m_st.icpsr.f_zero; - m_st.cpsr.b.f_sign = m_st.icpsr.f_sign; - } - - void Cpu::SwitchToMode (uint8_t newmode) - { - SaveMode(m_st.icpsr.mode); - - switch (newmode) - { - case 0x10: // User (non-privileged) - case 0x1F: // System (privileged 'User' mode) - switch (m_st.icpsr.mode) - { - case 0x10: - case 0x1F: - case 0x11: - std::memcpy(m_st.r + 8, m_st.usr_r, sizeof(m_st.usr_r)); - break; - default: - std::memcpy(m_st.r + 13, m_st.usr_r + 5, 2*4); - break; - } - break; - case 0x11: // FIQ - std::memcpy(m_st.r + 8, m_st.fiq_r, sizeof(m_st.fiq_r)); - break; - case 0x12: // IRQ - std::memcpy(m_st.r + 13, m_st.irq_r, sizeof(m_st.irq_r)); - break; - case 0x13: // Supervisor (SWI) - std::memcpy(m_st.r + 13, m_st.svc_r, sizeof(m_st.svc_r)); - break; - case 0x17: // Abort - std::memcpy(m_st.r + 13, m_st.abt_r, sizeof(m_st.abt_r)); - break; - case 0x1B: // Undefined - std::memcpy(m_st.r + 13, m_st.und_r, sizeof(m_st.und_r)); - break; - default: - met_abort("Unknown CPU mode : " << IOS_ADD << (int)newmode); - break; - } - - UpdateCpsr(); - m_st.spsr.dw = m_st.cpsr.dw; - m_st.icpsr.mode = newmode; - } - - void Cpu::SwitchModeBack () - { - // oldmode is the mode on which we want to switch back - uint8_t oldmode = m_st.spsr.b.mode, curmode = m_st.icpsr.mode; - // we don't care if the spsr of the mode we are using is modified - SaveMode(curmode); - - m_st.cpsr.dw = m_st.spsr.dw; - UpdateICpsr(); - CheckInterrupt(); - switch (oldmode) - { - case 0x10: // User (non-privileged) - case 0x1F: // System (privileged 'User' mode) - switch (curmode) - { - case 0x10: - case 0x1F: - case 0x11: - std::memcpy(m_st.r + 8, m_st.usr_r, sizeof(m_st.usr_r)); - break; - default: - std::memcpy(m_st.r + 13, m_st.usr_r + 5, 2*4); - break; - } - break; - case 0x11: // FIQ - std::memcpy(m_st.r + 8, m_st.fiq_r, sizeof(m_st.fiq_r)); - m_st.spsr.dw = m_st.fiq_spsr.dw; - break; - case 0x12: // IRQ - std::memcpy(m_st.r + 13, m_st.irq_r, sizeof(m_st.irq_r)); - m_st.spsr.dw = m_st.irq_spsr.dw; - break; - case 0x13: // Supervisor (SWI) - std::memcpy(m_st.r + 13, m_st.svc_r, sizeof(m_st.svc_r)); - m_st.spsr.dw = m_st.svc_spsr.dw; - break; - case 0x17: // Abort - std::memcpy(m_st.r + 13, m_st.abt_r, sizeof(m_st.abt_r)); - m_st.spsr.dw = m_st.abt_spsr.dw; - break; - case 0x1B: // Undefined - std::memcpy(m_st.r + 13, m_st.und_r, sizeof(m_st.und_r)); - m_st.spsr.dw = m_st.und_spsr.dw; - break; - default: - met_abort("Unknown CPU mode : " << IOS_ADD << (int)oldmode); - break; - } - } - - void Cpu::SaveMode (uint8_t mode) - { - switch (mode) - { - case 0x10: // User (non-privileged) - case 0x1F: // System (privileged 'User' mode) - std::memcpy(m_st.usr_r, m_st.r + 8, sizeof(m_st.usr_r)); - break; - case 0x11: // FIQ - std::memcpy(m_st.fiq_r, m_st.r + 8, sizeof(m_st.fiq_r)); - m_st.fiq_spsr.dw = m_st.spsr.dw; - break; - case 0x12: // IRQ - std::memcpy(m_st.irq_r, m_st.r + 13, sizeof(m_st.irq_r)); - m_st.irq_spsr.dw = m_st.spsr.dw; - break; - case 0x13: // Supervisor (SWI) - std::memcpy(m_st.svc_r, m_st.r + 13, sizeof(m_st.svc_r)); - m_st.svc_spsr.dw = m_st.spsr.dw; - break; - case 0x17: // Abort - std::memcpy(m_st.abt_r, m_st.r + 13, sizeof(m_st.abt_r)); - m_st.abt_spsr.dw = m_st.spsr.dw; - break; - case 0x1B: // Undefined - std::memcpy(m_st.und_r, m_st.r + 13, sizeof(m_st.und_r)); - m_st.und_spsr.dw = m_st.spsr.dw; - break; - default: - met_abort("Unknown CPU mode : " << IOS_ADD << (int)mode); - break; - } - } - - void Cpu::Interrupt () - { - // Switch mode - SwitchToMode(0x12); // IRQ - // Save PC - R(14) = R(15); - // FIXME : why ? this seems to be USELESS ! (look at bios irq end) - if (m_st.icpsr.thumb) - R(14) += 2; - // Switch to ARM - m_st.icpsr.thumb = false; - // Disable IRQ - m_st.icpsr.irq_d = true; - SetInterrupt(false); - // Branch on 0x18 - R(15) = 0x1C; - } - - void Cpu::SoftwareInterrupt () - { - // Switch mode - SwitchToMode(0x13); // Supervisor - // Save PC - R(14) = R(15) - (m_st.icpsr.thumb ? 2 : 4); - // Switch to ARM - m_st.icpsr.thumb = false; - // Disable IRQ - m_st.icpsr.irq_d = true; - SetInterrupt(false); - // Branch on 0x8 - R(15) = 0xC; - } - - // TODO put this in Bios, no ? - void Cpu::SoftwareInterrupt (uint32_t comment) - { - if (true) - { - char buff[256]; - int pos = 0; - pos += sprintf (buff + pos, "SWI %02xh : ", comment); - switch (comment) // no one cares about the sound driver - { - case 0x00: pos += sprintf (buff + pos, "SoftReset"); - break; - case 0x01: pos += sprintf (buff + pos, "RegisterRamReset"); // todo: display flags - break; - case 0x02: pos += sprintf (buff + pos, "Halt"); - break; - case 0x03: pos += sprintf (buff + pos, "Stop"); - break; - case 0x04: pos += sprintf (buff + pos, "IntrWait"); // todo: display flags - break; - case 0x05: pos += sprintf (buff + pos, "VBlankIntrWait"); - break; - case 0x06: pos += sprintf (buff + pos, "Div: "); - pos += sprintf (buff + pos, "%08xh/%08xh", R(0), R(1)); - break; - case 0x07: pos += sprintf (buff + pos, "DivArm: "); - pos += sprintf (buff + pos, "%08xh/%08xh", R(1), R(0)); - break; - case 0x08: pos += sprintf (buff + pos, "Sqrt: "); - pos += sprintf (buff + pos, "sqrt(%08xh)", R(0)); - break; - case 0x09: pos += sprintf (buff + pos, "ArcTan: "); - pos += sprintf (buff + pos, "atan(%04xh)", R(0) & 0xffff); - break; - case 0x0a: pos += sprintf (buff + pos, "ArcTan2: "); - pos += sprintf (buff + pos, "atan2(%04xh,%04xh)", R(1) & 0xffff, R(0) & 0xffff); - break; - case 0x0b: pos += sprintf (buff + pos, "CpuSet: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], wcnt=%xh, fixed=%c, size=%d", R(0), R(1), R(2) & 0x1fffff, R(2) & 0x1000000 ? 'Y' : 'N', R(2) & 0x4000000 ? 32 : 16); - break; - case 0x0c: pos += sprintf (buff + pos, "CpuFastSet: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], wcnt=%xh, fixed=%c", R(0), R(1), R(2) & 0x1fffff, R(2) & 0x1000000 ? 'Y' : 'N'); - break; - case 0x0d: pos += sprintf (buff + pos, "GetBiosChecksum"); - break; - case 0x0e: pos += sprintf (buff + pos, "BgAffineSet: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], cnt=%d", R(0), R(1), R(2)); - break; - case 0x0f: pos += sprintf (buff + pos, "ObjAffineSet: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], cnt=%d, offs=%d", R(0), R(1), R(2), R(3)); - break; - case 0x10: pos += sprintf (buff + pos, "BitUnPack: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh], info=[%08xh]", R(0), R(1), R(2)); - break; - case 0x11: pos += sprintf (buff + pos, "LZ77UnCompWram: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1)); - break; - case 0x12: pos += sprintf (buff + pos, "LZ77UnCompVram: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1)); - break; - case 0x13: pos += sprintf (buff + pos, "HuffUnComp: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1)); - break; - case 0x14: pos += sprintf (buff + pos, "RLUnCompWram: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1)); - break; - case 0x15: pos += sprintf (buff + pos, "RLUnCompVram: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1)); - break; - case 0x16: pos += sprintf (buff + pos, "Diff8bitUnFilterWram: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1)); - break; - case 0x17: pos += sprintf (buff + pos, "Diff8bitUnFilterVram: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1)); - break; - case 0x18: pos += sprintf (buff + pos, "Diff16bitUnFilter: "); - pos += sprintf (buff + pos, "src=[%08xh], dst=[%08xh]", R(0), R(1)); - break; - case 0x19: pos += sprintf (buff + pos, "SoundBias"); - break; - case 0x1a: pos += sprintf (buff + pos, "SoundDriverInit"); - break; - case 0x1b: pos += sprintf (buff + pos, "SoundDriverMode"); - break; - case 0x1c: pos += sprintf (buff + pos, "SoundDriverMain"); - break; - case 0x1d: pos += sprintf (buff + pos, "SoundDriverVSync"); - break; - case 0x1e: pos += sprintf (buff + pos, "SoundChannelClear"); - break; - case 0x1f: pos += sprintf (buff + pos, "MidiKey2Freq"); - break; - case 0x20: pos += sprintf (buff + pos, "SoundWhatever0"); - break; - case 0x21: pos += sprintf (buff + pos, "SoundWhatever1"); - break; - case 0x22: pos += sprintf (buff + pos, "SoundWhatever2"); - break; - case 0x23: pos += sprintf (buff + pos, "SoundWhatever3"); - break; - case 0x24: pos += sprintf (buff + pos, "SoundWhatever4"); - break; - case 0x25: pos += sprintf (buff + pos, "MultiBoot: "); - pos += sprintf (buff + pos, "mbp=[%08xh], mode=%d", R(0), R(1)); - break; - case 0x26: pos += sprintf (buff + pos, "HardReset"); - break; - case 0x27: pos += sprintf (buff + pos, "CustomHalt: "); - pos += sprintf (buff + pos, "val=%02xh", R(2) & 0xff); - break; - case 0x28: pos += sprintf (buff + pos, "SoundDriverVSyncOff"); - break; - case 0x29: pos += sprintf (buff + pos, "SoundDriverVSyncOnn"); - break; - case 0x2a: pos += sprintf (buff + pos, "SoundGetJumpList"); - break; - default: pos += sprintf (buff + pos, "UNKNOWN"); - break; - } - pos += sprintf (buff + pos, "\n"); - print_bizhawk(buff); - } - if (MEM.HasBios()) - SoftwareInterrupt(); - else - switch (comment) - { - case 0x00: - Bios::SoftReset(); - break; - case 0x01: - Bios::RegisterRamReset(); - break; - case 0x02: - Bios::Halt(); - break; - case 0x04: - case 0x05: - SoftwareInterrupt(); - break; - case 0x06: - Bios::Div(); - break; - case 0x07: - Bios::DivArm(); - break; - case 0x08: - Bios::Sqrt(); - break; - case 0x09: - Bios::ArcTan(); - break; - case 0x0A: - Bios::ArcTan2(); - break; - case 0x0B: - Bios::CpuSet(); - break; - case 0x0C: - Bios::CpuFastSet(); - break; - case 0x0E: - Bios::BgAffineSet(); - break; - case 0x0F: - Bios::ObjAffineSet(); - break; - case 0x11: - Bios::LZ77UnCompWram(); - break; - case 0x12: - Bios::LZ77UnCompVram(); - break; - case 0x13: - Bios::HuffUnComp(); - break; - case 0x14: - Bios::RLUnCompWram(); - break; - case 0x15: - Bios::RLUnCompVram(); - break; - default: - met_abort("Unknown software interrupt : " << IOS_ADD << comment); - break; - } - } - - bool Cpu::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_st); - - return true; - } - - bool Cpu::LoadState (std::istream& stream) - { - SS_READ_VAR(m_st); - - CheckInterrupt(); - - return true; - } -} diff --git a/libmeteor/source/cpu_globals.hpp b/libmeteor/source/cpu_globals.hpp deleted file mode 100644 index e0f73bdd77..0000000000 --- a/libmeteor/source/cpu_globals.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __CPU_GLOBALS_H__ -#define __CPU_GLOBALS_H__ - -#undef R -#define R(reg) m_st.r[reg] - -#undef CPU -#define CPU (*this) - -#undef CPSR -#undef SPSR -#undef FLAG_Z -#undef FLAG_N -#undef FLAG_C -#undef FLAG_V -#undef FLAG_T -#define CPSR (m_st.cpsr.dw) -#define SPSR (m_st.spsr.dw) -#define FLAG_Z (m_st.icpsr.f_zero) -#define FLAG_N (m_st.icpsr.f_sign) -#define FLAG_C (m_st.icpsr.f_carry) -#define FLAG_V (m_st.icpsr.f_overflow) -#define FLAG_T (m_st.icpsr.thumb) - -#endif diff --git a/libmeteor/source/debug.cpp b/libmeteor/source/debug.cpp deleted file mode 100644 index 50365d1a59..0000000000 --- a/libmeteor/source/debug.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "debug.hpp" -#include "ameteor/cpu.hpp" -#include "globals.hpp" -#include "ameteor.hpp" - -#include -#include - -namespace AMeteor -{ - // TODO make this more guidelined (like the above assert) - void debug_bits(uint32_t u) - { -#if defined METDEBUG && defined METDEBUGLOG - for (register int8_t c = 31; c >= 0; --c) - { - STDBG << !!(u & (((uint32_t)0x1) << c)); - if (!(c % 8)) - STDBG << ' '; - } - STDBG << std::endl; -#else - (void)u; -#endif - } - - void debug_bits_16(uint16_t u) - { -#if defined METDEBUG && defined METDEBUGLOG - for (register int8_t c = 15; c >= 0; --c) - { - STDBG << !!(u & (((uint32_t)0x1) << c)); - if (!(c % 8)) - STDBG << ' '; - } - STDBG << std::endl; -#else - (void)u; -#endif - } - -#ifdef MET_REGS_DEBUG - void PrintRegs () - { - static uint32_t regs[17] = {0}; - - for (uint8_t c = 0; c <= 15; ++c) - if (R(c) != regs[c]) - { - STDBG << "R" << std::setbase(10) << (int)c << " = " << IOS_ADD << R(c) << '\n'; - regs[c] = R(c); - } - CPU.UpdateCpsr(); - if (CPSR != regs[16]) - { - STDBG << "R16 = " << IOS_ADD << CPSR << '\n'; - regs[16] = CPSR; - } - } - - void PrintStack (uint32_t stackadd) - { - uint32_t add = stackadd; - debug("Stack : " << IOS_ADD << add); - for (; add < 0x03008000; add += 4) - debug(IOS_ADD << MEM.Read32(add)); - } -#endif -} diff --git a/libmeteor/source/debug.hpp b/libmeteor/source/debug.hpp deleted file mode 100644 index 64d0973709..0000000000 --- a/libmeteor/source/debug.hpp +++ /dev/null @@ -1,109 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __DEBUG_H__ -#define __DEBUG_H__ - -#include -#include -#include -#include - -// for abort macro -#include "ameteor.hpp" - -// from cinterface.cpp -void print_bizhawk(const char *msg); -void print_bizhawk(std::string &msg); -void abort_bizhawk(const char *msg); -void keyupdate_bizhawk(); -extern bool traceenabled; -void trace_bizhawk(std::string msg); -extern int slcallbackline; -void scanlinecallback_bizhawk(); - -#if 0 -#define met_abort(str) \ - { \ - std::cerr << IOS_NOR << "Fatal error :\n" << str << "\nFile : " \ - << __FILE__ << "\nLine : " << __LINE__ << "\nr15 = " \ - << IOS_ADD << ::AMeteor::_cpu.Reg(15) << "\n[r15] = " << IOS_ADD \ - << ::AMeteor::_memory.Read32(::AMeteor::_cpu.Reg(15)) \ - << "\nFlag T : " << ::AMeteor::_cpu.ICpsr().thumb << std::endl; \ - abort(); \ - } -#endif -#ifdef METDEBUG -#include -//extern "C" int __stdcall MessageBoxA(int, const char *, const char *, int); -#define met_abort(_str) if(true)\ - { \ - std::stringstream _zisrny; \ - _zisrny << IOS_NOR << "Fatal error :\n" << _str << "\nFile : " \ - << __FILE__ << "\nLine : " << __LINE__ << "\nr15 = " \ - << IOS_ADD << ::AMeteor::_cpu.Reg(15) << "\n[r15] = " << IOS_ADD \ - << ::AMeteor::_memory.Read32(::AMeteor::_cpu.Reg(15)) \ - << "\nFlag T : " << ::AMeteor::_cpu.ICpsr().thumb << std::endl; \ - abort_bizhawk(_zisrny.str().c_str()); \ - } - -#else -#define met_abort(str) {} -#endif - -#define STDBG std::cout -//#define STDBG debug_stream - -#if defined METDEBUG && defined METDEBUGLOG -//XXX -# define MYDEBUG -# define debug(_str) \ - { \ - std::stringstream _zisrny; \ - _zisrny << _str << std::endl; \ - print_bizhawk(_zisrny.str()); \ - } - //STDBG << str << std::endl -//# define debug_(str) \ -// STDBG << str -#else -# define debug(s) {} -//# define debug_(s) {} -#endif - -#define IOS_ADD \ - "0x" << std::setbase(16) << std::setw(8) << std::setfill('0') \ - << std::uppercase -#define IOS_TRACE \ - std::setbase(16) << std::setw(8) << std::setfill('0') << std::uppercase -#define IOS_NOR \ - std::setbase(10) << std::setw(0) << std::setfill(' ') - -namespace AMeteor -{ - void debug_bits(uint32_t u); - void debug_bits_16(uint16_t u); - -#if defined MET_REGS_DEBUG - void PrintRegs (); - void PrintStack (uint32_t stackadd); -#else -#define PrintRegs() -#define PrintStack(b) -#endif -} - -#endif diff --git a/libmeteor/source/disassembler/argimmediate.cpp b/libmeteor/source/disassembler/argimmediate.cpp deleted file mode 100644 index cf17a5ccf1..0000000000 --- a/libmeteor/source/disassembler/argimmediate.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/disassembler/argimmediate.hpp" - -#include -#include - -namespace AMeteor -{ - namespace Disassembler - { - std::string ArgImmediate::GetString () const - { - std::ostringstream ss; - ss << '#'; - ss << std::hex << std::setw(2) << std::setfill('0') << m_imm << 'h'; - return ss.str(); - } - - Argument* ArgImmediate::Clone () const - { - return new ArgImmediate(*this); - } - } -} diff --git a/libmeteor/source/disassembler/argmulregisters.cpp b/libmeteor/source/disassembler/argmulregisters.cpp deleted file mode 100644 index 5e0bae0822..0000000000 --- a/libmeteor/source/disassembler/argmulregisters.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/disassembler/argmulregisters.hpp" - -#include - -namespace AMeteor -{ - namespace Disassembler - { - std::string ArgMulRegisters::GetString () const - { - std::ostringstream ss; - ss << '{'; - - bool open = false; - - for (Registers::const_iterator iter = m_regs.begin(); - iter != m_regs.end(); ++iter) - { - if (open && - iter + 1 < m_regs.end() && - *(iter + 1) == (*iter) + 1) - { - continue; - } - else if (iter + 2 < m_regs.end() && - *(iter + 1) == (*iter) + 1 && - *(iter + 2) == (*iter) + 2) - { - ss << 'r' << (int)*iter << '-'; - open = true; - } - else - { - ss << 'r' << (int)*iter; - open = false; - if (iter + 1 != m_regs.end()) - ss << ", "; - } - } - - if (m_lastreg == SPREG_LR) - { - if (ss.width() != 1) - ss << ", "; - ss << "lr"; - } - else if (m_lastreg == SPREG_PC) - { - if (ss.width() != 1) - ss << ", "; - ss << "pc"; - } - - ss << '}'; - - if (m_forceuser) - ss << '^'; - - return ss.str(); - } - - Argument* ArgMulRegisters::Clone () const - { - return new ArgMulRegisters(*this); - } - } -} diff --git a/libmeteor/source/disassembler/argpsr.cpp b/libmeteor/source/disassembler/argpsr.cpp deleted file mode 100644 index c03a5e20d6..0000000000 --- a/libmeteor/source/disassembler/argpsr.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/disassembler/argpsr.hpp" - -namespace AMeteor -{ - namespace Disassembler - { - std::string ArgPsr::GetString () const - { - std::string out; - - if (m_spsr) - out = "SPSR"; - else - out = "CPSR"; - - if (m_fields <= 0xF) - { - out += '_'; - if (m_fields & 0x1) - out += 'c'; - if (m_fields & 0x2) - out += 'x'; - if (m_fields & 0x4) - out += 's'; - if (m_fields & 0x8) - out += 'f'; - } - - return out; - } - - Argument* ArgPsr::Clone () const - { - return new ArgPsr(*this); - } - } -} diff --git a/libmeteor/source/disassembler/argregister.cpp b/libmeteor/source/disassembler/argregister.cpp deleted file mode 100644 index 5b00ba1937..0000000000 --- a/libmeteor/source/disassembler/argregister.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/disassembler/argregister.hpp" - -#include - -namespace AMeteor -{ - namespace Disassembler - { - std::string ArgRegister::GetString () const - { - static const char* SpeRegisters[] = {"SP", "LR", "PC"}; - - std::ostringstream ss; - - if (m_memory) - ss << '['; - - if (m_special) - ss << SpeRegisters[m_reg-13]; - else - ss << 'r' << (int)m_reg; - - if (m_memory) - ss << ']'; - - if (m_writeback) - ss << '!'; - - return ss.str(); - } - - Argument* ArgRegister::Clone () const - { - return new ArgRegister(*this); - } - } -} diff --git a/libmeteor/source/disassembler/argrelative.cpp b/libmeteor/source/disassembler/argrelative.cpp deleted file mode 100644 index 16355d104c..0000000000 --- a/libmeteor/source/disassembler/argrelative.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/disassembler/argrelative.hpp" - -#include - -namespace AMeteor -{ - namespace Disassembler - { - ArgRelative::ArgRelative (const ArgRegister& reg, const Argument& off, - bool pre, bool up, bool writeback) : - Argument(), - m_reg(reg), - m_off(off.Clone()), - m_pre(pre), - m_up(up), - m_writeback(writeback) - { } - - ArgRelative::ArgRelative (const ArgRelative& arg) : - Argument(), - m_reg(arg.m_reg), - m_off(arg.m_off->Clone()), - m_pre(arg.m_pre), - m_up(arg.m_up), - m_writeback(arg.m_writeback) - { } - - ArgRelative::~ArgRelative () - { - delete m_off; - } - - Argument* ArgRelative::Clone () const - { - return new ArgRelative(*this); - } - - std::string ArgRelative::GetString () const - { - std::ostringstream ss; - ss << "[r" << (int)m_reg.GetRegister(); - - if (m_pre) - { - ss << (m_up ? ", +" : ", -") << m_off->GetString() << ']'; - if (m_writeback) - ss << '!'; - } - else - ss << (m_up ? "], +" : "], -") << m_off->GetString(); - - return ss.str(); - } - } -} diff --git a/libmeteor/source/disassembler/argshift.cpp b/libmeteor/source/disassembler/argshift.cpp deleted file mode 100644 index 5fa4522537..0000000000 --- a/libmeteor/source/disassembler/argshift.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/disassembler/argshift.hpp" - -#include - -namespace AMeteor -{ - namespace Disassembler - { - ArgShift::ArgShift (const Argument& arg1, const Argument& arg2, - ShiftType type, bool memory) : - Argument(), - m_arg1(arg1.Clone()), - m_arg2(arg2.Clone()), - m_type(type), - m_memory(memory) - { } - - ArgShift::ArgShift (const ArgShift& arg) : - Argument(), - m_arg1(arg.m_arg1->Clone()), - m_arg2(arg.m_arg2->Clone()), - m_type(arg.m_type), - m_memory(arg.m_memory) - { } - - ArgShift::~ArgShift () - { - delete m_arg1; - delete m_arg2; - } - - Argument* ArgShift::Clone () const - { - return new ArgShift(*this); - } - - std::string ArgShift::GetString () const - { - static const char* Shifts[] = {", LSL ", ", LSR ", ", ASR ", ", ROR ", - ", RRX "}; - - std::ostringstream ss; - - if (m_memory) - ss << '['; - - ss << m_arg1->GetString() << Shifts[m_type] << m_arg2->GetString(); - - if (m_memory) - ss << ']'; - - return ss.str(); - } - } -} diff --git a/libmeteor/source/disassembler/arguimmediate.cpp b/libmeteor/source/disassembler/arguimmediate.cpp deleted file mode 100644 index 9d4ce1fd05..0000000000 --- a/libmeteor/source/disassembler/arguimmediate.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/disassembler/arguimmediate.hpp" - -#include -#include - -namespace AMeteor -{ - namespace Disassembler - { - std::string ArgUImmediate::GetString () const - { - std::ostringstream ss; - ss << '#'; - ss << std::hex << std::setw(8) << std::setfill('0') << m_imm << 'h'; - return ss.str(); - } - - Argument* ArgUImmediate::Clone () const - { - return new ArgUImmediate(*this); - } - } -} diff --git a/libmeteor/source/disassembler/arguments.cpp b/libmeteor/source/disassembler/arguments.cpp deleted file mode 100644 index 714ac9a881..0000000000 --- a/libmeteor/source/disassembler/arguments.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/disassembler/arguments.hpp" - -namespace AMeteor -{ - namespace Disassembler - { - Arguments::~Arguments () - { - Clear(); - } - - void Arguments::Clear () - { - for (std::vector::iterator iter = m_args.begin(); - iter != m_args.end(); ++iter) - { - delete *iter; - } - m_args.clear(); - } - - std::string Arguments::GetString () const - { - std::string out; - for (std::vector::const_iterator iter = m_args.begin(); - iter != m_args.end(); ++iter) - { - if (!out.empty()) - out += ", "; - out += (*iter)->GetString(); - } - return out; - } - } -} diff --git a/libmeteor/source/disassembler/instruction.cpp b/libmeteor/source/disassembler/instruction.cpp deleted file mode 100644 index eef4248219..0000000000 --- a/libmeteor/source/disassembler/instruction.cpp +++ /dev/null @@ -1,691 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/disassembler/instruction.hpp" - -#include "ameteor/disassembler/argregister.hpp" -#include "ameteor/disassembler/argrelative.hpp" -#include "ameteor/disassembler/argimmediate.hpp" -#include "ameteor/disassembler/arguimmediate.hpp" -#include "ameteor/disassembler/argshift.hpp" -#include "ameteor/disassembler/argpsr.hpp" -#include "ameteor/disassembler/argmulregisters.hpp" - -#include "../globals.hpp" // for ROR - -namespace AMeteor -{ - namespace Disassembler - { - void Instruction::Clear () - { - m_operator.clear(); - m_args.Clear(); - } - -#define Rn ((code >> 16) & 0xF) -#define Rd ((code >> 12) & 0xF) -#define Rs ((code >> 8) & 0xF) -#define Rm (code & 0xF) - - void Instruction::ParseArm (uint32_t offset, uint32_t code) - { - Clear(); - - if ((code & 0x0FFFFFD0) == 0x12FFF10) - { - if (code & (0x1 << 5)) - m_operator = "BLX"; - else - m_operator = "BX"; - m_args.AddArgument(ArgRegister(Rm)); - ParseArmCondition(code); - } - else if (((code >> 25) & 0x7) == 0x5) - { - if (((code >> 28) & 0xF) == 0xF) - { - m_operator = "BLX"; - m_args.AddArgument(ArgImmediate(offset + 8 + - (((code & (0x1 << 23)) ? 0xFF000000 | (code & 0x00FFFFFF) - : (code & 0x00FFFFFF)) << 2) - + ((code & (0x1 << 24)) ? 2 : 0))); - } - else - { - if (code & (0x1 << 24)) - m_operator = "BL"; - else - m_operator = "B"; - m_args.AddArgument(ArgImmediate(offset + 8 + - (((code & (0x1 << 23)) ? 0xFF000000 | (code & 0x00FFFFFF) - : (code & 0x00FFFFFF)) << 2))); - ParseArmCondition(code); - } - } - else if (((code >> 25) & 0x7) == 0x1) - { - ParseArmDataProc(code); - } - else if (((code >> 26) & 0x3) == 0x1) - { - if ((code & 0xF0100000) != 0xF0100000) // not PLD - m_args.AddArgument(ArgRegister(Rd)); - if (code & (0x1 << 25)) // register offset - { - switch ((code >> 5) & 0x3) - { - case 0: // Logical Shift Left - m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm), - ArgImmediate((code >> 7) & 0x1F), SHIFT_LSL, false), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - break; - case 1: // Logical Shift Right - if (code & (0x1F << 7)) - m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm), - ArgImmediate((code >> 7) & 0x1F), SHIFT_LSR, false), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - else - m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm), - ArgImmediate(32), SHIFT_LSR, false), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - break; - case 2: // Arithmetic Shift Right - if (code & (0x1F << 7)) - m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm), - ArgImmediate((code >> 7) & 0x1F), SHIFT_ASR, false), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - else - m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm), - ArgImmediate(32), SHIFT_ASR, false), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - break; - case 3: // ROtate Right - if (code & (0x1F << 7)) - m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm), - ArgImmediate((code >> 7) & 0x1F), SHIFT_ROR, false), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - else - m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm), - ArgImmediate(1), SHIFT_RRX, false), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - break; - } - } - else // immediate offset - { - m_args.AddArgument(ArgRelative(Rn, ArgImmediate(code & 0xFFF), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - } - - if ((code & 0xF0100000) == 0xF0100000) - m_operator = "PLD"; - else - { - if (code & (0x1 << 20)) - m_operator = "LDR"; - else - m_operator = "STR"; - if (code & (0x1 << 22)) - m_operator += "B"; - - ParseArmCondition(code); - } - } - else if (((code >> 25) & 0x7) == 0x4) - { - if (code & (0x1 << 20)) - m_operator = "LDM"; - else - m_operator = "STM"; - - if (code & (0x1 << 23)) - m_operator += 'I'; - else - m_operator += 'D'; - - if (code & (0x1 << 24)) - m_operator += 'B'; - else - m_operator += 'A'; - - m_args.AddArgument(ArgRegister(Rn, code & (0x1 << 21))); - - ArgMulRegisters argRegs(code & (0x1 << 22)); - for (register uint8_t n = 0; n < 16; ++n) - if (code & (0x1 << n)) - argRegs.AddRegister(n); - m_args.AddArgument(argRegs); - - ParseArmCondition(code); - } - else if (((code >> 25) & 0x7) == 0x0) - { - if ((code & 0x0FC000F0) == 0x00000090 || - (code & 0x0F8000F0) == 0x00800090 || - (code & 0x0F900090) == 0x01000080) - { - // NOTE : In this instruction Rn and Rd are inverted - static const char* Instructions[] = {"MUL", "MLA", "Reserved", - "Reserved", "UMULL", "UMLAL", "SMULL", "SMLAL", "SMLAxy", - "", // This is for SMLAWy and SMULWy - "SMLALxy", "SMULxy", "Reserved", "Reserved", "Reserved", - "Reserved"}; - - uint8_t opcode = (code >> 21) & 0xF; - if (opcode == 0x9) - m_operator = (code & (0x1 << 5)) ? "SMULWy" : "SMLAWy"; - else - m_operator = Instructions[opcode]; - if (!(opcode & (0x1 << 4)) && (code & (0x1 << 20))) - m_operator += 'S'; - - ParseArmCondition(code); - - if ((opcode & 0xC) == 0x4 || opcode == 0xA) - m_args.AddArgument(ArgRegister(Rd)); - m_args.AddArgument(ArgRegister(Rn)); - m_args.AddArgument(ArgRegister(Rm)); - m_args.AddArgument(ArgRegister(Rs)); - if ((opcode & 0xE) == 0x8 || opcode == 0x1) - m_args.AddArgument(ArgRegister(Rd)); - } - else if ((code & (0x1 << 7)) && (code & (0x1 << 4))) - { - if (((code >> 23) & 0x3) == 0x2 && ((code >> 20) & 0x3) == 0x0 - && ((code >> 4) & 0xFF) == 0x09) - { - if (code & (0x1 << 22)) // SWPB - m_operator = "SWPB"; - else // SWP - m_operator = "SWP"; - - ParseArmCondition(code); - - m_args.AddArgument(ArgRegister(Rd)); - m_args.AddArgument(ArgRegister(Rm)); - m_args.AddArgument(ArgRegister(Rn, false, false, true)); - } - else - { - static const char* Instructions[] = {"Reserved", "STRH", "LDRD", - "STRD", "Reserved", "LDRH", "LDRSB", "LDRSH"}; - - m_operator = Instructions[((code >> 18) & 0x4) - | ((code >> 5) & 0x3)]; - - ParseArmCondition(code); - - m_args.AddArgument(ArgRegister(Rd)); - - if (code & (0x1 << 22)) // immediate - { - m_args.AddArgument(ArgRelative(ArgRegister(Rn), - ArgImmediate(((code >> 4) & 0xF0) | (code & 0xF)), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - } - else - { - m_args.AddArgument(ArgRelative(ArgRegister(Rn), - ArgRegister(code & 0xF), - code & (0x1 << 24), code & (0x1 << 23), - code & (0x1 << 21))); - } - } - } - else if (((code >> 23) & 0x3) == 0x2) - { - if (!((code >> 20) & 0x1)) - { - if (code & (0x1 << 21)) - { - m_operator = "MSR"; - - m_args.AddArgument(ArgPsr(code & (0x1 << 22), - (code >> 16) & 0xF)); - - if (code & (0x1 << 25)) // immediate - { - m_args.AddArgument(ArgUImmediate( - ROR(code & 0xFF, (code >> 8) & 0xF))); - } - else - { - m_args.AddArgument(ArgRegister(Rm)); - } - } - else - { - m_operator = "MRS"; - - m_args.AddArgument(ArgRegister(Rd)); - m_args.AddArgument(ArgPsr(code & (0x1 << 22))); - } - - ParseArmCondition(code); - } - else - { - ParseArmDataProc(code); - } - } - else - { - ParseArmDataProc(code); - } - } - else - { - m_operator = "Unknown"; - } - } - - void Instruction::ParseArmDataProc (uint32_t code) - { - static const char* ops[] = {"AND", "EOR", "SUB", "RSB", "ADD", "ADC", - "SBC", "RSC", "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN"}; - - uint8_t opcode = (code >> 21) & 0xF; - - if (opcode < 0x8 || opcode > 0xB) - m_args.AddArgument(ArgRegister(Rd)); - if (opcode != 0xD && opcode != 0xF) - m_args.AddArgument(ArgRegister(Rn)); - - if (code & (0x1 << 25)) // Immediate operand 2 - { - /*if (code & (0xF << 8)) - m_args.AddArgument(ArgShift(ArgImmediate(code & 0xFF), - ArgImmediate(((code >> 8) & 0xF) << 1), SHIFT_ROR, false)); - else - m_args.AddArgument(ArgImmediate(code & 0xFF));*/ - m_args.AddArgument(ArgUImmediate( - ROR(code & 0xFF, (code >> 7) & 0x1E))); - } - else - { - switch ((code >> 5) & 0x3) - { - case 0: // Logical Shift Left - if (code & (0x1 << 4)) // Shift by register - { - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgRegister(Rs), SHIFT_LSL, false)); - } - else // Shift by immediate - { - if (code & (0x1F << 7)) - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgImmediate((code >> 7) & 0x1F), SHIFT_LSL, false)); - else - m_args.AddArgument(ArgRegister(Rm)); - } - break; - case 1: // Logical Shift Right - if (code & (0x1 << 4)) // Shift by register - { - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgRegister(Rs), SHIFT_LSR, false)); - } - else // Shift by immediate - { - if (code & (0x1F << 7)) - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgImmediate((code >> 7) & 0x1F), SHIFT_LSR, false)); - else - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgImmediate(32), SHIFT_LSR, false)); - } - break; - case 2: // Arithmetic Shift Right - if (code & (0x1 << 4)) // Shift by register - { - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgRegister(Rs), SHIFT_ASR, false)); - } - else // Shift by immediate - { - if (code & (0x1F << 7)) - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgImmediate((code >> 7) & 0x1F), SHIFT_ASR, false)); - else - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgImmediate(32), SHIFT_ASR, false)); - } - break; - case 3: // ROtate Right - if (code & (0x1 << 4)) // Shift by register - { - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgRegister(Rs), SHIFT_ROR, false)); - } - else // Shift by immediate - { - if (code & (0x1F << 7)) - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgImmediate((code >> 7) & 0x1F), SHIFT_ROR, false)); - else - m_args.AddArgument(ArgShift(ArgRegister(Rm), - ArgImmediate(1), SHIFT_RRX, false)); - } - break; - } - } - - m_operator = ops[opcode]; - - if (code & (0x1 << 20) && (opcode < 0x8 || opcode > 0xB)) - { - m_operator += "S"; - } - ParseArmCondition(code); - } - - void Instruction::ParseArmCondition (uint32_t code) - { - static const char* Conditions[] = {"EQ", "NE", "CS", "CC", "MI", "PL", - "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"}; - - m_operator += Conditions[code >> 28]; - } - -#undef Rn -#undef Rd -#undef Rs -#undef Rm - -#define Rb ((code >> 8) & 0x7) -#define Ro ((code >> 6) & 0x7) -#define Rs ((code >> 3) & 0x7) -#define Rd ((code ) & 0x7) -#define Imm (code & 0xFF) -#define Off ((code >> 6) & 0x1F) - -#define HiRs ((code >> 3) & 0xF) -#define HiRd (((code & (0x1 << 7)) >> 4) | Rd) - - void Instruction::ParseThumb (uint32_t offset, uint16_t code) - { - Clear (); - - if ((code >> 12) == 0xB && ((code >> 9) & 0x3) == 0x2) // 1011x10 - { - if (code & (0x1 << 11)) - m_operator = "POP"; - else - m_operator = "PUSH"; - - ArgMulRegisters argRegs(false); - for (register uint8_t n = 0; n < 8; ++n) - if (Imm & (0x1 << n)) - argRegs.AddRegister(n); - - if (code & (0x1 << 8)) - { - if (code & (0x1 << 11)) - argRegs.AddLastRegister(SPREG_PC); - else - argRegs.AddLastRegister(SPREG_LR); - } - m_args.AddArgument(argRegs); - } - else if ((code >> 11) == 0x9) // 01001 - { - m_operator = "LDR"; - - m_args.AddArgument(ArgRegister(Rb)); - m_args.AddArgument(ArgRelative(15, ArgImmediate(Imm << 2), - true, true, false)); - } - else if ((code >> 12) == 0x8) // 1000 - { - if (code & (0x1 << 11)) - m_operator = "LDRH"; - else - m_operator = "STRH"; - - m_args.AddArgument(ArgRegister(Rd)); - m_args.AddArgument(ArgRelative(Rs, ArgImmediate(Off << 1), - true, true, false)); - } - else if ((code >> 10) == 0x10) // 010000 - { - static const char* Instructions[] = {"AND", "EOR", "LSL", "LSR", "ASR", - "ADC", "SBC", "ROR", "TST", "NEG", "CMP", "CMN", "ORR", "MUL", "BIC", - "MVN"}; - - m_operator = Instructions[(code >> 6) & 0xF]; - - m_args.AddArgument(ArgRegister(Rd)); - m_args.AddArgument(ArgRegister(Rs)); - } - else if ((code >> 10) == 0x11) // 010001 - { - switch ((code >> 8) & 0x3) - { - case 0x0: // ADD - m_operator = "ADD"; - m_args.AddArgument(ArgRegister(HiRd)); - m_args.AddArgument(ArgRegister(HiRs)); - break; - case 0x1: // CMP - m_operator = "CMP"; - m_args.AddArgument(ArgRegister(HiRd)); - m_args.AddArgument(ArgRegister(HiRs)); - break; - case 0x2: - if (HiRd != 8 || HiRs != 8) // MOV - { - m_operator = "MOV"; - m_args.AddArgument(ArgRegister(HiRd)); - m_args.AddArgument(ArgRegister(HiRs)); - } - else - m_operator = "NOP"; - break; - case 0x3: - if (code & (0x1 << 7)) // BLX - { - m_operator = "BLX"; - m_args.AddArgument(ArgRegister(HiRs)); - } - else // BX - { - m_operator = "BX"; - m_args.AddArgument(ArgRegister(HiRs)); - } - break; - } - } - else if ((code >> 13) == 0x1) // 001 - { - static const char* Instructions[] = {"MOV", "CMP", "ADD", "SUB"}; - - m_operator = Instructions[(code >> 11) & 0x3]; - - m_args.AddArgument(ArgRegister(Rb)); - m_args.AddArgument(ArgImmediate(Imm)); - } - else if ((code >> 13) == 0x3) // 011 - { - static const char* Instructions[] = {"STR", "LDR", "STRB", "LDRB"}; - - m_operator = Instructions[(code >> 11) & 0x3]; - - m_args.AddArgument(ArgRegister(Rd)); - if (code & (0x1 << 12)) - m_args.AddArgument(ArgRelative(Rs, ArgImmediate(Off), true, - true, false)); - else - m_args.AddArgument(ArgRelative(Rs, ArgImmediate(Off << 2), true, - true, false)); - } - else if ((code >> 12) == 0xC) // 1100 - { - if (code & (0x1 << 11)) - m_operator = "LDMIA"; - else - m_operator = "STMIA"; - - m_args.AddArgument(ArgRegister(Rb, true)); - - ArgMulRegisters argRegs(false); - for (register uint8_t n = 0; n < 8; ++n) - if (Imm & (0x1 << n)) - argRegs.AddRegister(n); - m_args.AddArgument(argRegs); - } - else if ((code >> 13) == 0x0) // 000 - { - if ((code >> 11) == 0x3) // 00011 - { - if ((code >> 9) & 0x1) - m_operator = "SUB"; - else - m_operator = "ADD"; - - m_args.AddArgument(ArgRegister(Rd)); - m_args.AddArgument(ArgRegister(Rs)); - - if ((code >> 10) & 0x1) // imm - m_args.AddArgument(ArgImmediate(Ro)); - else // reg - m_args.AddArgument(ArgRegister(Ro)); - } - else // 000 - { - static const char* Instructions[] = {"LSL", "LSR", "ASR", "Reserved"}; - - m_operator = Instructions[(code >> 11) & 0x3]; - - m_args.AddArgument(ArgRegister(Rd)); - m_args.AddArgument(ArgRegister(Rs)); - m_args.AddArgument(ArgImmediate(Off)); - } - } - else if ((code >> 11) == 0x1E) // 11110 - { - m_operator = "BL.W1"; - - m_args.AddArgument(ArgImmediate(offset + 4 + ((code & 0x7FF) << 12))); - } - else if ((code >> 13) == 0x7 && (code & (0x1 << 11))) // 111x1 - { - m_operator = "BL.W2"; - - m_args.AddArgument(ArgImmediate((code & 0x7FF) << 1)); - } - else if ((code >> 11) == 0x1C) // 11100 - { - m_operator = "B"; - - if (code & (0x1 << 10)) - m_args.AddArgument(ArgUImmediate(offset + 4 + - ((int32_t)(((code & 0x3FF) << 1) | 0xFFFFF800)))); - else - m_args.AddArgument(ArgUImmediate(offset + 4 + ((code & 0x3FF) << 1))); - } - else if ((code >> 12) == 0xD) // 1101 - { - if (((code >> 8) & 0xF) == 0xF) // 11011111 - { - m_operator = "SWI"; - - m_args.AddArgument(ArgImmediate(code & 0xFF)); - } - else // 1101 - { - static const char* Conditions[] = {"EQ", "NE", "CS", "CC", "MI", "PL", - "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "__", "**"}; - - m_operator = "B"; - m_operator += Conditions[(code >> 8) & 0xF]; - - m_args.AddArgument(ArgUImmediate(offset + 4 + - (((int32_t)(int8_t)Imm) << 1))); - } - } - else if ((code >> 8) == 0xB0) // 10110000 - { - m_operator = "ADD"; - - m_args.AddArgument(ArgRegister(13, false, true)); - if (code & (0x1 << 7)) // substract - m_args.AddArgument(ArgImmediate(-((code & 0x7F) << 2))); - else // add - m_args.AddArgument(ArgImmediate((code & 0x7F) << 2)); - } - else if ((code >> 12) == 0x5) // 0101 - { - if (code & (0x1 << 11)) - m_operator = "LDR"; - else - m_operator = "STR"; - - if (code & (0x1 << 10)) - m_operator += 'B'; - - m_args.AddArgument(ArgRegister(Rd)); - m_args.AddArgument(ArgRelative(Rs, ArgRegister(Ro), true, true, false)); - } - else if ((code >> 12) == 0x9) // 1001 - { - if (code & (0x1 << 11)) - m_operator = "LDR"; - else - m_operator = "STR"; - - m_args.AddArgument(ArgRegister(Rb)); - m_args.AddArgument(ArgRelative(ArgRegister(13, false, true), - ArgImmediate(Imm << 2), true, true, false)); - } - else if ((code >> 12) == 0xA) // 1010 - { - m_operator = "ADD"; - - m_args.AddArgument(ArgRegister(Rb)); - if (code & (0x1 << 11)) // with SP - m_args.AddArgument(ArgRegister(13, false, true)); - else // with PC - m_args.AddArgument(ArgRegister(15, false, true)); - m_args.AddArgument(ArgImmediate(Imm << 2)); - } - else - { - m_operator = "Unknown"; - } - } - -#undef Rb -#undef Ro -#undef Rs -#undef Rd -#undef Imm -#undef Off - -#undef HiRs -#undef HiRd - } -} diff --git a/libmeteor/source/dma.cpp b/libmeteor/source/dma.cpp deleted file mode 100644 index 04df0f79e4..0000000000 --- a/libmeteor/source/dma.cpp +++ /dev/null @@ -1,317 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/dma.hpp" -#include "ameteor/io.hpp" -#include "ameteor/memory.hpp" -#include "globals.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" -#include - -namespace AMeteor -{ - void Dma::Reset () - { - for (Channel* chan = m_chans; chan < m_chans+4; ++chan) - { - chan->src = 0; - chan->dest = 0; - chan->count = 0; - chan->control.w = 0; - } - m_graphic = 0; - } - - void Dma::UpdateCnt (uint8_t channum) - { - Channel& chan = m_chans[channum]; - - if (chan.control.w != - IO.DRead16(Io::DMA0CNT_H + channum * Io::DMA_CHANSIZE)) - { - if (!chan.control.b.enable && - (IO.DRead16(Io::DMA0CNT_H + channum * Io::DMA_CHANSIZE) - & (0x1 << 15))) - // if we changed enable from 0 to 1 - { - chan.dest = IO.DRead32(Io::DMA0DAD + channum * Io::DMA_CHANSIZE); - if (channum == 3) - chan.dest &= 0x0FFFFFFF; - else - chan.dest &= 0x07FFFFFF; - - chan.src = IO.DRead32(Io::DMA0SAD + channum * Io::DMA_CHANSIZE); - if (channum == 0) - chan.src &= 0x07FFFFFF; - else - chan.src &= 0x0FFFFFFF; - - chan.count = chan.reload; - if (channum != 3) - chan.count &= 0x3FFF; - - chan.control.w = - IO.DRead16(Io::DMA0CNT_H + channum * Io::DMA_CHANSIZE); - - Check(channum, Immediately); - } - else - chan.control.w = - IO.DRead16(Io::DMA0CNT_H + channum * Io::DMA_CHANSIZE); - - if (chan.control.b.start == Special) - { - switch (channum) - { - case 0: - met_abort("prohibited !"); - break; - case 1: - case 2: - // sound dma - if (chan.dest != 0x040000A0 && chan.dest != 0x040000A4) - met_abort("Special DMA 1 or 2 with unauthorized address : " - << IOS_ADD << chan.dest); - if (!chan.control.b.repeat) - met_abort("Special DMA 1 or 2 without repeat"); - - // 4 words of 32 bits - chan.count = 4; - chan.control.b.type = 1; - // no increment - chan.control.b.dest = 2; - break; - case 3: - met_abort("not implemented"); - break; - } - } - } - } - - void Dma::Check (uint8_t channum, uint8_t reason) - { - register Channel::Control cnt = m_chans[channum].control; - - if (cnt.b.enable && - cnt.b.start == reason) - Process(channum); - } - - void Dma::Process (uint8_t channum) - { - Channel& chan = m_chans[channum]; - - int8_t s_inc, d_inc; - s_inc = d_inc = 2; // increment or increment reload - - if (chan.control.b.src == 1) // decrement - s_inc = -2; - else if (chan.control.b.src == 2) // fixed - s_inc = 0; - else if (chan.control.b.src == 3) - met_abort("prohibited"); - - if (chan.control.b.dest == 1) - d_inc = -2; - else if (chan.control.b.dest == 2) - d_inc = 0; - //else if (chan.control.b.dest == 3) - // same as 0, but we do something at the end - - if (chan.control.b.type) // 32 bits transfer - { - s_inc <<= 1; - d_inc <<= 1; - } - - if (chan.count == 0) - { - if (channum != 3) - chan.count = 0x4000; - // 0x10000 doesn't fill in 16 bits, we treat this case in the Copy() call - } - - //printf("DMA%hhu from %08X to %08X of %hu %s\n", channum, chan.src, chan.dest, chan.count, chan.control.b.type ? "words":"halfwords"); - //if (i > debut) - debug ("DMA" << IOS_NOR << (int)channum << ", from " << IOS_ADD << chan.src - << " to " << IOS_ADD << chan.dest - << " of " << IOS_NOR << (chan.count ? chan.count : 0x10000) - << (chan.control.b.type ? " words" : " halfwords")); - if (traceenabled) - { - std::stringstream ss; - ss << "DMA" << IOS_NOR << (int)channum << ", from " << IOS_ADD << chan.src - << " to " << IOS_ADD << chan.dest - << " of " << IOS_NOR << (chan.count ? chan.count : 0x10000) - << (chan.control.b.type ? " words" : " halfwords"); - trace_bizhawk(ss.str()); - } -#if 0 - if (channum == 3 && (chan.dest >> 24) == 0x0D || (chan.src >> 24) == 0x0D) - { - if (chan.control.b.type) - met_abort("Word copy for EEPROM DMA3"); - if (d_inc != 2 || s_inc != 2) - met_abort("Source or destination not incremeting in EEPROM DMA3"); - if ((chan.dest >> 24) == 0x0D) - MEM.WriteEepromDma(chan.src, chan.count ? chan.count : 0x10000); - else if ((chan.src >> 24) == 0x0D) - MEM.ReadEepromDma(chan.dest, chan.count ? chan.count : 0x10000); - chan.src += chan.count * 2; - chan.dest += chan.count * 2; - } - else -#endif - if (channum == 3 && (chan.dest >> 24) == 0x0D) - { - if (chan.control.b.type) - met_abort("Word copy for EEPROM DMA3"); - if (d_inc != 2 || s_inc != 2) - met_abort("Source or destination not incremeting in EEPROM DMA3"); - MEM.WriteEepromDma(chan.src, chan.count); - chan.src += chan.count * 2; - chan.dest += chan.count * 2; - } - else - Copy(chan.src, chan.dest, s_inc, d_inc, - chan.count ? chan.count : 0x10000, chan.control.b.type); - - if (chan.control.b.type) - { - CYCLES32NSeq(chan.src, chan.count); - CYCLES32NSeq(chan.dest, chan.count); - ICYCLES(2); - } - else - { - CYCLES16NSeq(chan.src, chan.count); - CYCLES16NSeq(chan.dest, chan.count); - ICYCLES(2); - } - uint32_t d = chan.dest >> 24; - uint32_t s = chan.src >> 24; - if (d >= 0x08 && d <= 0x0D && s >= 0x08 && s <= 0x0D) - // if both source and destination are in GamePak - ICYCLES(2); - - if (chan.control.b.irq) - CPU.SendInterrupt(0x1 << (8 + channum)); - - if (chan.control.b.dest == 3) - { - chan.dest = IO.DRead32(Io::DMA0DAD + channum * Io::DMA_CHANSIZE); - if (channum == 3) - chan.dest &= 0x0FFFFFFF; - else - chan.dest &= 0x07FFFFFF; - } - - // if repeat but not sound dma - //if (!((channum == 1 || channum == 2) && chan.control.b.start == Special) && chan.control.b.repeat) - if (((channum != 1 && channum != 2) || chan.control.b.start != Special) - && chan.control.b.repeat) - { - chan.count = chan.reload; - } - - if (!chan.control.b.repeat || chan.control.b.start == Immediately) - { - chan.control.b.enable = 0; - IO.GetRef16(Io::DMA0CNT_H + channum * Io::DMA_CHANSIZE) &= 0x7FFF; - } - } - - void Dma::Copy (uint32_t& src, uint32_t& dest, int8_t s_inc, int8_t d_inc, - uint32_t count, bool word) - { - uint32_t basedest = dest; - - if (word) - { - src &= 0xFFFFFFFC; - dest &= 0xFFFFFFFC; - } - else - { - src &= 0xFFFFFFFE; - dest &= 0xFFFFFFFE; - } - - // sound - if (dest == 0x040000A0) - { - SOUND.SendDigitalA((uint8_t*)MEM.GetRealAddress(src)); - src += 4*4; - if (d_inc != 0) - met_abort("dinc != 0 on dma sound, should not happen"); - return; - } - if (dest == 0x040000A4) - { - SOUND.SendDigitalB((uint8_t*)MEM.GetRealAddress(src)); - src += 4*4; - if (d_inc != 0) - met_abort("dinc != 0 on dma sound, should not happen"); - return; - } - - if ((dest >> 24) >= 0x05 && - (dest >> 24) <= 0x07) - m_graphic = true; - - if (word) - { - for (uint32_t cur = 0; cur < count; ++cur) - { - MEM.Write32(dest, MEM.Read32(src)); - src += s_inc; - dest += d_inc; - } - } - else - { - for (uint32_t cur = 0; cur < count; ++cur) - { - MEM.Write16(dest, MEM.Read16(src)); - src += s_inc; - dest += d_inc; - } - } - - m_graphic = false; - //if ((basedest >> 24) == 0x07) - // LCD.OamWrite(basedest, dest); - } - - bool Dma::SaveState (std::ostream& stream) - { - SS_WRITE_ARRAY(m_chans); - // no need to save or load m_graphic since we shouldn't save or load during - // a dma - - return true; - } - - bool Dma::LoadState (std::istream& stream) - { - SS_READ_ARRAY(m_chans); - - return true; - } -} diff --git a/libmeteor/source/eeprom.cpp b/libmeteor/source/eeprom.cpp deleted file mode 100644 index 3dd99f07d3..0000000000 --- a/libmeteor/source/eeprom.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/eeprom.hpp" -#include "globals.hpp" -#include "debug.hpp" - -#include - -namespace AMeteor -{ - Eeprom::Eeprom (bool big) : - CartMem(), - m_state(IDLE), - m_add(0), - m_pos(0) - { - if (big) - m_size = 0x2000; - else - m_size = 0x0200; - - *(uint32_t*)(m_data+MAX_SIZE) = m_size; - } - - void Eeprom::Reset () - { - std::memset(m_data, 0, m_size); - } - - bool Eeprom::Load (std::istream& f) - { - f.read((char*)m_data, m_size); - return f.good(); - } - - bool Eeprom::Save (std::ostream& f) - { - f.write((char*)m_data, m_size); - return f.good(); - } - - uint8_t Eeprom::Read (uint16_t MET_UNUSED(add)) - { - met_abort("8 bits write to EEPROM"); - return 0; - } - - uint16_t Eeprom::Read () - { - switch (m_state) - { - case READ_GARBAGE: - ++m_pos; - if (m_pos == 4) - { - m_pos = 0; - m_state = READ_DATA; - } - return 0; - case READ_DATA: - { - uint16_t ret = - (m_data[m_add + m_pos / 8] & (0x1 << (7 - (m_pos % 8)))) ? 1 : 0; - ++m_pos; - if (m_pos == 64) - m_state = IDLE; - return ret; - } - default: - return 1; - } - } - - bool Eeprom::Write (uint16_t MET_UNUSED(add), uint8_t MET_UNUSED(val)) - { - met_abort("8 bits write to EEPROM"); - return false; - } - //XXX -#if 0 - bool Eeprom::Write (uint16_t val) - { - switch (m_state) - { - case IDLE: - if (val & 0x1) - m_state = WAITING; - else - met_abort("First bit is not 1"); - return false; - case WAITING: - m_add = 0; - m_pos = 0; - if (val & 0x1) - m_state = READ_ADD; - else - m_state = WRITE_ADD; - return false; - - case READ_ADD: - m_add <<= 1; - m_add |= val & 0x1; - ++m_pos; - if (m_size == 0x0200 && m_pos == 6 || - m_size == 0x2000 && m_pos == 14) - { - m_state = READ_END; - if (m_size == 0x2000 && (m_add & 0x3C000)) - met_abort("In large EEPROM, 4 upper address bits are not 0"); - } - return false; - case READ_END: - if (val & 0x1) - met_abort("Last bit of EEPROM read request is not 0"); - m_pos = 0; - m_state = READ_GARBAGE; - return false; - - case WRITE_ADD: - m_add <<= 1; - m_add |= val & 0x1; - ++m_pos; - if (m_size == 0x0200 && m_pos == 6 || - m_size == 0x2000 && m_pos == 14) - { - m_state = WRITE_DATA; - m_pos = 0; - if (m_size == 0x2000 && (m_add & 0x3C000)) - met_abort("In large EEPROM, 4 upper address bits are not 0"); - } - return false; - case WRITE_DATA: - { - uint8_t& d = m_data[m_add + m_pos / 8]; - d <<= 1; - d |= val & 0x1; - } - ++m_pos; - if (m_pos == 64) - m_state = WRITE_END; - return true; - case WRITE_END: - if (val & 0x1) - met_abort("Last bit of EEPROM write request is not 0"); - return false; - } - } -#endif - - bool Eeprom::Write (uint16_t* pData, uint16_t size) - { - if (!(*pData & 0x1)) - met_abort("Bit 1 is not 1 in EEPROM DMA"); - ++pData; - - uint16_t add = 0; - if (*pData & 0x1) // read - { - if (size != 9 && size != 17) - met_abort("Invalid size for read"); - ++pData; - - // read address - for (uint8_t i = 0, end = (m_size == 0x0200) ? 6 : 14; i < end; - ++i, ++pData) - add = (add << 1) | (*pData & 0x1); - if (m_size == 0x2000 && (add & 0x3C00)) - met_abort("In large EEPROM, 4 upper address bits are not 0"); - - //XXX - /*if (*pData & 0x1) - met_abort("Last bit of EEPROM read request is not 0");*/ - - m_add = add*8; - m_state = READ_GARBAGE; - m_pos = 0; - - return false; - } - else // write - { - if (size != 73 && size != 81) - met_abort("Invalid size for write"); - ++pData; - - // read address - for (uint8_t i = 0, end = (m_size == 0x0200) ? 6 : 14; i < end; - ++i, ++pData) - add = (add << 1) | (*pData & 0x1); - if (m_size == 0x2000 && (add & 0x3C00)) - met_abort("In large EEPROM, 4 upper address bits are not 0"); - - // read data - uint8_t* pMem = m_data + add*8; - for (uint8_t i = 0; i < 8; ++i, ++pMem) - { - for (uint8_t j = 0; j < 8; ++j, ++pData) - { - *pMem <<= 1; - *pMem |= (*pData & 0x1); - } - } - - if (*pData & 0x1) - met_abort("Last bit of EEPROM write request is not 0"); - - m_state = IDLE; - - return true; - } - } - - //XXX -#if 0 - void Eeprom::Read (uint16_t* pOut) - { - if (m_state != READ) - met_abort("Read in invalid EEPROM state"); - - pOut += 4; // ignore these - uint8_t* pData = m_data + m_add; - uint8_t cur; - for (uint8_t i = 0; i < 8; ++i, ++pData) - { - cur = *pData; - pOut += 7; - for (uint8_t j = 0; j < 8; ++j, --pOut, cur >>= 1) - *pOut = cur & 0x1; - pOut += 9; - } - - m_state = NORMAL; - } -#endif - - bool Eeprom::SaveState (std::ostream& stream) - { - //XXX TODO - SS_WRITE_VAR(m_size); - SS_WRITE_VAR(m_state); - SS_WRITE_VAR(m_add); - - SS_WRITE_DATA(m_data, m_size); - - return true; - } - - bool Eeprom::LoadState (std::istream& stream) - { - SS_READ_VAR(m_size); - SS_READ_VAR(m_state); - SS_READ_VAR(m_add); - - SS_READ_DATA(m_data, m_size); - - return true; - } -} diff --git a/libmeteor/source/flash.cpp b/libmeteor/source/flash.cpp deleted file mode 100644 index 1493cc0715..0000000000 --- a/libmeteor/source/flash.cpp +++ /dev/null @@ -1,178 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/flash.hpp" -#include "globals.hpp" -#include -#include - -namespace AMeteor -{ - Flash::Flash (bool big) : - CartMem(), - m_state(NORMAL) - { - if (big) - { - m_device_id = 0x13; - m_manufacturer_id = 0x62; - m_size = 128*1024; - } - else - { - m_device_id = 0x1B; - m_manufacturer_id = 0x32; - m_size = 64*1024; - } - - *(uint32_t*)(m_data+MAX_SIZE) = m_size; - } - - void Flash::Reset () - { - std::memset(m_data, 0, m_size); - } - - bool Flash::Load (std::istream& f) - { - f.read((char*)m_data, m_size); - return f.good(); - } - - bool Flash::Save (std::ostream& f) - { - f.write((char*)m_data, m_size); - return f.good(); - } - - uint8_t Flash::Read (uint16_t add) - { - switch (m_state) - { - case NORMAL: - return m_data[add]; - case ID: - switch (add) - { - case 0: return m_manufacturer_id; - case 1: return m_device_id; - default: return 0; - } - // FIXME vba returns 0xff after an erase regardless of the read address - default: - return 0; - } - } - - bool Flash::Write (uint16_t add, uint8_t val) - { - switch (m_state) - { - case ID: - case NORMAL: - if (add == 0x5555 && val == 0xAA) - m_state = CMD1; - else - m_state = NORMAL; // for case ID - break; - case CMD1: - if (add == 0x2AAA && val == 0x55) - m_state = CMD2; - else - m_state = NORMAL; - break; - case CMD2: - if (add == 0x5555) - switch (val) - { - case 0x80: // erase mode - m_state = ERASE1; - break; - case 0x90: // id mode - m_state = ID; - break; - case 0xA0: // write byte - m_state = WRITE; - break; - case 0xF0: - m_state = NORMAL; - break; - default: - m_state = NORMAL; - break; - } - else - m_state = NORMAL; - break; - case ERASE1: - if (add == 0x5555 && val == 0xAA) - m_state = ERASE2; - else - m_state = NORMAL; - break; - case ERASE2: - if (add == 0x2AAA && val == 0x55) - m_state = ERASE3; - else - m_state = NORMAL; - break; - case ERASE3: - // according to vba, after a whole erase command we can juste repeat the - // last byte of the command to execute another erase command - switch (val) - { - case 0x10: // erase entire chip - if (add == 0x5555) - memset(m_data, 0xFF, m_size); - m_state = NORMAL; - break; - case 0x30: // erase sector - if (!(add & 0x0FFF)) - memset(m_data+add, 0xFF, 0x1000); - m_state = NORMAL; - break; - default: - m_state = NORMAL; - break; - } - break; - case WRITE: - // I think this is how it works - m_data[add] &= val; - m_state = NORMAL; - return true; - } - return false; - } - - bool Flash::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_state); - - SS_WRITE_DATA(m_data, m_size); - - return true; - } - - bool Flash::LoadState (std::istream& stream) - { - SS_READ_VAR(m_state); - - SS_READ_DATA(m_data, m_size); - - return true; - } -} diff --git a/libmeteor/source/globals.hpp b/libmeteor/source/globals.hpp deleted file mode 100644 index 393b597438..0000000000 --- a/libmeteor/source/globals.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __GLOBALS_H__ -#define __GLOBALS_H__ - -#include -#include - -#define SPDUP_FRMSKIP 9 -#define SPDUP_SNDSKIP 3969 - -#define R(reg) CPU.Reg(reg) - -#define CPU _cpu -#define MEM _memory -#define IO _io -#define DMA _dma -#define LCD _lcd -#define SOUND _sound -#define KEYPAD _keypad -#define CLOCK _clock -#define TIMER0 _timer0 -#define TIMER1 _timer1 -#define TIMER2 _timer2 -#define TIMER3 _timer3 - -#define CYCLES16NSeq(add, count) \ - CLOCK.TimePass(MEM.GetCycles16NoSeq(add, count)) -#define CYCLES16Seq(add, count) \ - CLOCK.TimePass(MEM.GetCycles16Seq(add, count)) -#define CYCLES32NSeq(add, count) \ - CLOCK.TimePass(MEM.GetCycles32NoSeq(add, count)) -#define CYCLES32Seq(add, count) \ - CLOCK.TimePass(MEM.GetCycles32Seq(add, count)) -#define ICYCLES(i) \ - CLOCK.TimePass(i) -// we don't mind if the following code is slow since a MUL -// instruction is slow on a GBA too -#define MULICYCLES(reg) \ - { \ - uint32_t rs = R(reg) >> 8; \ - for (uint8_t i = 1; i <= 4; ++i, rs >>= 8) \ - { \ - if (!rs || rs == (0xFFFFFFFF >> (i*8))) \ - { \ - ICYCLES(i); \ - break; \ - } \ - } \ - } - -#define CPSR (CPU.Cpsr().dw) -#define ICPSR (CPU.ICpsr()) -#define SPSR (CPU.Spsr().dw) -#define FLAG_Z (CPU.ICpsr().f_zero) -#define FLAG_N (CPU.ICpsr().f_sign) -#define FLAG_C (CPU.ICpsr().f_carry) -#define FLAG_V (CPU.ICpsr().f_overflow) -#define FLAG_T (CPU.ICpsr().thumb) -#define SETF(flag, val) \ - FLAG_##flag = (val) ? 1 : 0 -#define SETFB(flag, val) \ - FLAG_##flag = (val) - -#define FZ(val) \ - SETF(Z, !(val)) -#define FN(val) \ - SETF(N, NEG(val)) - -#define POS(a) ((~a) >> 31) -#define NEG(a) ((a) >> 31) - -// inspired by VisualBoyAdvance -#define ADDCARRY(a, b, c) \ - ((NEG(a) & NEG(b)) | \ - (NEG(a) & POS(c)) | \ - (NEG(b) & POS(c))) -#define ADDOVERFLOW(a, b, c) \ - ((NEG(a) & NEG(b) & POS(c)) | \ - (POS(a) & POS(b) & NEG(c))) -#define SUBCARRY(a, b, c) \ - ((NEG(a) & POS(b)) | \ - (NEG(a) & POS(c)) | \ - (POS(b) & POS(c))) -#define SUBOVERFLOW(a, b, c) \ - ((NEG(a) & POS(b) & POS(c)) | \ - (POS(a) & NEG(b) & NEG(c))) - -// Save states macros -#define SS_WRITE_VAR(var) \ - if (!stream.write((char*)&var, sizeof(var))) \ - return false -#define SS_WRITE_ARRAY(var) \ - if (!stream.write((char*)var, sizeof(var))) \ - return false -#define SS_WRITE_DATA(var, size) \ - if (!stream.write((char*)var, size)) \ - return false -#define SS_READ_VAR(var) \ - if (!stream.read((char*)&var, sizeof(var))) \ - return false -#define SS_READ_ARRAY(var) \ - if (!stream.read((char*)var, sizeof(var))) \ - return false -#define SS_READ_DATA(var, size) \ - if (!stream.read((char*)var, size)) \ - return false - -// macro to avoid getting warnings about and unused parameter on GCC -#ifdef _MSC_VER -#define MET_UNUSED(v) -#else -#define MET_UNUSED(v) \ - __attribute__((unused)) MET_UNUSED_##v -#endif - -namespace AMeteor -{ - // ROtate Right - inline uint32_t ROR(uint32_t val, uint8_t shift) - { - return (val >> shift) | (val << (32 - shift)); - } -} - -#endif diff --git a/libmeteor/source/graphics/bglayer.cpp b/libmeteor/source/graphics/bglayer.cpp deleted file mode 100644 index 9cc193b2fa..0000000000 --- a/libmeteor/source/graphics/bglayer.cpp +++ /dev/null @@ -1,475 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/graphics/bglayer.hpp" -#include "ameteor/graphics/screen.hpp" -#include "../debug.hpp" - -namespace AMeteor -{ - namespace Graphics - { - BgLayer::BgLayer (int8_t num, Memory& memory, Io& io, uint16_t* pPalette) : - m_memory(memory), - m_io(io), - m_num(num), - m_priority(0), - m_cnt(0), - m_xoff(0), - m_yoff(0), - m_tWidth(32), - m_tHeight(32), - m_rWidth(16), - m_rHeight(16), - m_mapAdd(0x06000000), - m_charAdd(0x06000000), - m_pPalette(pPalette) - { - } - - BgLayer::~BgLayer () - { - } - - void BgLayer::DrawLine0 (uint8_t line, uint16_t* ptr) - { - uint8_t mosH; - if (m_cnt & (0x1 << 6)) - { - mosH = m_io.DRead8(Io::MOSAIC); - uint8_t mosV = mosH >> 4; - mosH &= 0x0F; - - ++mosV; - if (mosH) // let it be 0 if it's 0 (=> no mosaic) - ++mosH; - - line /= mosV; - line *= mosV; - } - else - mosH = 0; - - uint16_t* pMap = (uint16_t*)m_memory.GetRealAddress(m_mapAdd), *pTile; - uint8_t* pChar = m_memory.GetRealAddress(m_charAdd), *tpChar; - uint8_t i = 0; - - // theses are the coordinates on the layer from which we will draw a line - uint16_t xoff = m_xoff % (m_tWidth * 8); - uint16_t yoff = (m_yoff + line) % (m_tHeight * 8); - - // theses are the coordinates on the tile of the pixels we are drawing - // NOTE : if the tile is horizontally flipped tileX = 8 - tileX, thus - // when we draw it is ALWAYS incremented no matter how the tile is - // flipped - // NOTE : tileY is NOT redefined if the tile is flipped vertically - int8_t tileX = xoff % 8, tileY; - bool flipH; - - // sets pTile to the tile we must draw first - // +---+---+ - // | 1 | 2 | - // +---+---+ - // | 3 | 4 | - // +---+---+ - if (yoff >= 256) - if (m_tWidth == 64) - if (xoff >= 256) - // zone 4 - pTile = pMap + 32*32 + 32*32 + 32*32 - + 32 * ((yoff-256)/8) + (xoff-256)/8; - else - // zone 3 (large map) - pTile = pMap + 32*32 + 32*32 + 32 * ((yoff-256)/8) + xoff/8; - else - // zone 3 (no large map) - pTile = pMap + 32*32 + 32 * ((yoff-256)/8) + xoff/8; - else - if (xoff >= 256) - // zone 2 - pTile = pMap + 32*32 + 32 * (yoff/8) + (xoff-256)/8; - else - // zone 1 - pTile = pMap + 32 * (yoff/8) + xoff/8; - - if (m_hicolor) - { - while (i < 240) - { - flipH = (bool)(*pTile & (0x1 << 10)); - - // if the tile is vertically fliped - if (*pTile & (0x1 << 11)) - tileY = 7 - (yoff % 8); - else - tileY = yoff % 8; - - if (flipH) - tpChar = pChar + (*pTile & 0x3FF)*8*8 + tileY*8 + 7 - tileX; - else - tpChar = pChar + (*pTile & 0x3FF)*8*8 + tileY*8 + tileX; - - while (tileX < 8) - { - if (mosH && i % mosH) - *ptr = ptr[-1]; - else - { - if (*tpChar) - *ptr = m_pPalette[*tpChar] | 0x8000; - else - *ptr = 0x0; - } - if (flipH) - --tpChar; - else - ++tpChar; - - ++ptr; - ++tileX; - ++i; - - if (i == 240) - return; - } - tileX = 0; - ++pTile; - - // support for big maps and wrap around - if (!((pTile - pMap) % 32)) - if (m_tWidth == 32) - pTile -= 32; - else - if (yoff >= 256 && pTile - pMap > 32*32 * 3 - || yoff < 256 && pTile - pMap > 32*32) - pTile -= 32*33; - else - pTile += 32*31; - } - } - else - { - uint16_t* pPalette; - uint8_t colorInd; - - // for each pixel of the line we are drawing - while (i < 240) - { - pPalette = m_pPalette + ((*pTile >> 12) & 0xF) * 16; - flipH = (bool)(*pTile & (0x1 << 10)); - - // if the tile is vertically fliped - if (*pTile & (0x1 << 11)) - tileY = 7 - (yoff % 8); - else - tileY = yoff % 8; - - if (flipH) - tpChar = pChar + ((*pTile & 0x3FF)*8*8 + tileY*8 + 7 - tileX)/2; - else - tpChar = pChar + ((*pTile & 0x3FF)*8*8 + tileY*8 + tileX)/2; - - // we draw until the end of the tile or the line - while (tileX < 8) - { - if (flipH) - if (tileX % 2) - { - colorInd = *tpChar & 0xF; - --tpChar; - } - else - colorInd = *tpChar >> 4; - else - if (tileX % 2) - { - colorInd = *tpChar >> 4; - ++tpChar; - } - else - colorInd = *tpChar & 0xF; - - if (mosH && i % mosH) - *ptr = ptr[-1]; - else - { - if (colorInd) - *ptr = pPalette[colorInd] | 0x8000; - else - *ptr = 0x0; - } - - ++ptr; - ++tileX; - ++i; - - // if this was the last pixel of the line - if (i == 240) - return; - } - - // we have finished drawing a tile, so we go to the next tile - tileX = 0; - ++pTile; - - // support for big maps and wrap around - if (!((pTile - pMap) % 32)) - if (m_tWidth == 32) - pTile -= 32; - else - if (yoff >= 256 && pTile - pMap > 32*32 * 3 - || yoff < 256 && pTile - pMap > 32*32) - pTile -= 32*33; - else - pTile += 32*31; - } - } - } - - void BgLayer::DrawLine2 (uint16_t* ptr, - int32_t curX, int32_t curY, - int16_t dx, int16_t dy) - { - if (!m_hicolor) - { - //FIXME is this possible ?? - //this seems to be impossible, but we should not crash since some games - //do it - //puts("rotated layer with 16 colors"); - //abort(); - // XXX - //it seems now that we should not care about this flag, we draw in 256 - //colors, that's all - //return; - } - int32_t intX, intY; - - uint16_t colorInd; - - uint8_t* pMap = (uint8_t*)m_memory.GetRealAddress(m_mapAdd); - uint8_t* pChar = m_memory.GetRealAddress(m_charAdd); - - for (uint8_t x = 0; x < 240; ++x, ++ptr, curX += dx, curY += dy) - { - intX = curX >> 8; - intY = curY >> 8; - - // if we are off layer - if (intX < 0 || intX >= m_rWidth*8) - if (m_cnt & (0x1 << 13)) - { - // NOTE : in C++, the modulus can be negative, this is because in - // x86, the IDIV instruction gives a remainder of the same sign of - // the dividend - curX %= m_rWidth*8 << 8; - if (curX < 0) - curX += m_rWidth*8 << 8; - intX = curX >> 8; - } - else - continue; - if (intY < 0 || intY >= m_rHeight*8) - if (m_cnt & (0x1 << 13)) - { - curY %= m_rHeight*8 << 8; - if (curY < 0) - curY += m_rHeight*8 << 8; - intY = curY >> 8; - } - else - continue; - - colorInd = pChar[pMap[intY / 8 * m_rWidth + intX / 8] * 8 * 8 - + (intY % 8) * 8 + intX % 8]; - - if (colorInd) - *ptr = m_pPalette[colorInd] | 0x8000; - else - *ptr = 0x0; - } - } - - void BgLayer::DrawLine3 (uint16_t* ptr, - int32_t curX, int32_t curY, - int16_t dx, int16_t dy) - { - int32_t intX, intY; - - uint16_t* pChar = (uint16_t*) m_memory.GetRealAddress(0x06000000); - - for (uint8_t x = 0; x < 240; ++x, ++ptr, curX += dx, curY += dy) - { - intX = curX >> 8; - intY = curY >> 8; - - // if we are off layer - if (intX < 0 || intX >= 240) - /* - if (m_cnt & (0x1 << 13)) - { - // NOTE : in C++, the modulus can be negative - intX %= 240; - if (intX < 0) - intX += 240; - } - else*/ - continue; - if (intY < 0 || intY >= 160) - /* - if (m_cnt & (0x1 << 13)) - { - intY %= 160; - if (intY < 0) - intY += 160; - } - else*/ - continue; - - *ptr = pChar[intY * 240 + intX] | 0x8000; - } - } - - void BgLayer::DrawLine4 (uint8_t line, uint16_t* ptr, - int32_t curX, int32_t curY, - int16_t dx, int16_t dmx, int16_t dy, int16_t dmy, bool frame1) - { - uint8_t mosH; - if (m_cnt & (0x1 << 6)) - { - // TODO horizontal mosaic not implemented - mosH = m_io.DRead8(Io::MOSAIC); - uint8_t mosV = mosH >> 4; - mosH &= 0x0F; - - ++mosV; - if (mosH) // let it be 0 if it's 0 (=> no mosaic) - ++mosH; - - uint8_t back = line % mosV; - - curX -= back*dmx; - curY -= back*dmy; - } - else - mosH = 0; - - int32_t intX, intY; - - uint16_t colorInd; - - uint8_t* pChar = - m_memory.GetRealAddress(frame1 ? 0x0600A000 : 0x06000000); - - for (uint8_t x = 0; x < 240; ++x, ++ptr, curX += dx, curY += dy) - { - if (mosH && x % mosH) - { - *ptr = ptr[-1]; - continue; - } - - intX = curX >> 8; - intY = curY >> 8; - - // if we are off layer - if (intX < 0 || intX >= 240) - if (m_cnt & (0x1 << 13)) - { - // NOTE : in C++, the modulus can be negative - intX %= 240; - if (intX < 0) - intX += 240; - } - else - continue; - if (intY < 0 || intY >= 160) - if (m_cnt & (0x1 << 13)) - { - intY %= 160; - if (intY < 0) - intY += 160; - } - else - continue; - - colorInd = pChar[intY * 240 + intX]; - - if (colorInd) - *ptr = m_pPalette[colorInd] | 0x8000; - else - *ptr = 0x0; - } - } - - void BgLayer::DrawLine5 (uint16_t* ptr, - int32_t curX, int32_t curY, - int16_t dx, int16_t dy, bool frame1) - { - int32_t intX, intY; - - uint16_t* pChar = (uint16_t*) m_memory.GetRealAddress(frame1 ? 0x0600A000 : 0x06000000); - - for (uint8_t x = 0; x < 240; ++x, ++ptr, curX += dx, curY += dy) - { - intX = curX >> 8; - intY = curY >> 8; - - // if we are off layer - if (intX < 0 || intX >= 160) - continue; - if (intY < 0 || intY >= 128) - continue; - - *ptr = pChar[intY * 160 + intX] | 0x8000; - } - } - - void BgLayer::UpdateCnt (uint16_t cnt) - { - if (m_cnt == cnt) - return; - - switch (cnt >> 14) - { - case 0: - m_tWidth = m_tHeight = 32; - m_rWidth = m_rHeight = 16; - break; - case 1: - m_tWidth = 64; - m_tHeight = 32; - m_rWidth = m_rHeight = 32; - break; - case 2: - m_tWidth = 32; - m_tHeight = 64; - m_rWidth = m_rHeight = 64; - break; - case 3: - m_tWidth = m_tHeight = 64; - m_rWidth = m_rHeight = 128; - break; - } - - m_priority = (cnt & 0x3); - m_charAdd = 0x06000000 + ((cnt >> 2) & 0x3) * 0x4000; - m_hicolor = cnt & (0x1 << 7); - m_mapAdd = 0x06000000 + ((cnt >> 8) & 0x1F) * 0x0800; - - m_cnt = cnt; - } - } -} diff --git a/libmeteor/source/graphics/object.cpp b/libmeteor/source/graphics/object.cpp deleted file mode 100644 index b4257e08c5..0000000000 --- a/libmeteor/source/graphics/object.cpp +++ /dev/null @@ -1,698 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/graphics/object.hpp" -#include "ameteor/graphics/screen.hpp" -#include "../debug.hpp" - -namespace AMeteor -{ - namespace Graphics - { - Object::Object (uint16_t* pPalette, uint8_t* pChar) : - m_attr0(0), - m_attr1(0), - m_attr2(0), - m_width(1), - m_height(1), - m_pPalette(pPalette), - m_pChar(pChar), - m_charBegin(0x06010000), - m_charEnd(0x06010020) - { - } - - Object::Object (const Object& obj) : - m_attr0(obj.m_attr0), - m_attr1(obj.m_attr1), - m_attr2(obj.m_attr2), - m_width(obj.m_width), - m_height(obj.m_height), - m_pPalette(obj.m_pPalette), - m_pChar(obj.m_pChar), - m_charBegin(obj.m_charBegin), - m_charEnd(obj.m_charEnd) - { - } - - void Object::DrawLine (uint8_t line, uint32_t* surface, bool oneDim, - uint8_t mosaic) - { - // if the object is disabled or it's an obj window - if (m_attr0 & (0x1 << 9) || ((m_attr0 >> 10) & 0x3) == 2) - return; - - // don't draw sprites with "prohibited" size - if (m_width == 0) - return; - - int16_t yoff = (m_attr0 & 0xFF); - if (yoff > Screen::HEIGHT) - yoff -= 256; - - // if the object does not appear on the line - if (yoff > line || yoff + m_height*8 <= line) - return; - - uint8_t mosH; - if (m_attr0 & (0x1 << 12)) - { - uint8_t mosV = mosaic >> 4; - mosH = mosaic & 0xF; - - ++mosV; - if (mosH) // let it be 0 if it's 0 (=> no mosaic) - ++mosH; - - line /= mosV; - line *= mosV; - } - else - mosH = 0; - - int16_t xoff = (m_attr1 & 0x1FF); - if (xoff & (0x1 << 8)) - xoff |= 0xFE00; // extend sign bit - - uint32_t* ptr = surface + xoff; - - uint32_t prio = (((uint32_t)m_attr2) << 6) & (0x3 << 16); - uint32_t mask = prio; - // if semi transparent - if (((m_attr0 >> 10) & 0x3) == 0x1) - mask |= (0x1 << 18); - uint8_t* pChar = m_pChar + (m_attr2 & 0x3FF) * 32; - bool flipH = m_attr1 & (0x1 << 12); - if (m_attr0 & (0x1 << 13)) // if 256 colors mode - { - // if the tile is vertically flipped - if (m_attr1 & (0x1 << 13)) - { - // go to the tile - if (oneDim) - pChar += m_width * (8 * 8) * (m_height -1 -((line-yoff) / 8)); - else - pChar += (16 * 8 * 8) * (m_height -1 -((line-yoff) / 8)); - // advance to the right line - pChar += 8 * (7 - ((line-yoff) % 8)); - } - else - { - // go to the tile - if (oneDim) - pChar += m_width * (8 * 8) * ((line-yoff) / 8); - else - pChar += (16 * 8 * 8) * ((line-yoff) / 8); - // advance to the right line - pChar += 8 * ((line-yoff) % 8); - } - // go to the end of the line if the object is flipped - if (flipH) - pChar += (m_width-1) * (8*8) + 8 - 1; - - for (uint8_t j = 0; j < m_width*8; ++j, ++ptr) - { - // if we are on screen - if (ptr - surface < Screen::WIDTH && ptr >= surface) - { - if (mosH && (ptr - surface) % mosH) - *ptr = ptr[-1]; - else - { - // if there is something to draw - if (*pChar) - { - // if we have priority or there is nothing behind - if (prio < (*ptr & (0x3 << 16)) || !(*ptr & 0x8000)) - *ptr = m_pPalette[*pChar] | 0x8000 | mask; - } - // if we have nothing to draw - else - // if we have better priority - if (prio < (*ptr & (0x3 << 16))) - // we just modify priority and keep what was behind - *ptr = (*ptr & ~(0x3 << 16)) | (mask & (0x3 << 16)); - } - } - - if (flipH) - if ((j % 8) == 7) - // go to previous tile - pChar -= ((8*8) - (8) + 1); - else - --pChar; - else - if ((j % 8) == 7) - // go to next tile - pChar += ((8*8) - (8) + 1); - else - ++pChar; - } - } - else - { - // if the tile is vertically flipped - if (m_attr1 & (0x1 << 13)) - { - // go to the tile - if (oneDim) - pChar += m_width * (8 * 8 / 2) * (m_height -1 -((line-yoff) / 8)); - else - pChar += (32 * 8 * 8 / 2) * (m_height -1 -((line-yoff) / 8)); - // advance to the right line - pChar += (8/2) * (7 - ((line-yoff) % 8)); - } - else - { - // go to the tile - if (oneDim) - pChar += m_width * (8 * 8 / 2) * ((line-yoff) / 8); - else - pChar += (32 * 8 * 8 / 2) * ((line-yoff) / 8); - // advance to the right line - pChar += (8/2) * ((line-yoff) % 8); - } - // go to the end of the line if the object is flipped - if (flipH) - pChar += (m_width-1) * (8*8/2) + 8/2 - 1; - - uint16_t* pPalette = m_pPalette + 16 * (m_attr2 >> 12); - uint8_t colorInd; - for (uint8_t j = 0; j < m_width*8; ++j, ++ptr) - { - if (flipH) - if (j % 2) - { - colorInd = *pChar & 0xF; - - if ((j % 8) == 7) - // go to next tile - // it doesn't matter if we are in one or two dimensions mapping - // since we never go on the next line - pChar -= ((8*8/2) - (8/2) + 1); - else - --pChar; - } - else - colorInd = *pChar >> 4; - else - if (j % 2) - { - colorInd = *pChar >> 4; - - if ((j % 8) == 7) - // go to next tile - // it doesn't matter if we are in one or two dimensions mapping - // since we never go on the next line - pChar += ((8*8/2) - (8/2) + 1); - else - ++pChar; - } - else - colorInd = *pChar & 0xF; - - // if we are on screen - if (ptr - surface < Screen::WIDTH && ptr >= surface) - { - if (mosH && (ptr - surface) % mosH) - *ptr = ptr[-1]; - else - { - // if there is something to draw - if (colorInd) - { - // if we have priority or there is nothing behind - if (prio < (*ptr & (0x3 << 16)) || !(*ptr & 0x8000)) - *ptr = pPalette[colorInd] | 0x8000 | mask; - } - // if we have nothing to draw - else - // if we have better priority - if (prio < (*ptr & (0x3 << 16))) - // we just modify priority and keep what was behind - *ptr = (*ptr & ~(0x3 << 16)) | (mask & (0x3 << 16)); - } - } - } - } - } - - void Object::DrawLineRot (uint8_t line, uint32_t* surface, bool oneDim, - int16_t a, int16_t b, int16_t c, int16_t d, uint8_t mosaic) - { - // if it's an obj window - if (((m_attr0 >> 10) & 0x3) == 2) - return; - - // don't draw sprites with "prohibited" size - if (m_width == 0) - return; - - int16_t yoff = (m_attr0 & 0xFF); - if (yoff > Screen::HEIGHT) - yoff -= 256; - - int16_t xoff = (m_attr1 & 0x1FF); - if (xoff & (0x1 << 8)) - xoff |= 0xFE00; // extend sign bit - - uint8_t fwidth = m_width*8, fheight = m_height*8; - if (m_attr0 & (0x1 << 9)) - { - fwidth *= 2; - fheight *= 2; - } - - // if the object does not appear on the line - if (yoff > line || yoff + fheight <= line) - return; - - uint8_t mosH; - if (m_attr0 & (0x1 << 12)) - { - uint8_t mosV = mosaic >> 4; - mosH = mosaic & 0xF; - - ++mosV; - if (mosH) // let it be 0 if it's 0 (=> no mosaic) - ++mosH; - - line /= mosV; - line *= mosV; - } - else - mosH = 0; - - int32_t curX = ((m_width*8) << 8)/2 - + (-fwidth/2) * a + (line-yoff-fheight/2) * b; - int32_t curY = ((m_height*8) << 8)/2 - + (-fwidth/2) * c + (line-yoff-fheight/2) * d; - int32_t intX, intY; - - uint32_t* ptr = surface + xoff; - - uint32_t prio = (((uint32_t)m_attr2) << 6) & (0x3 << 16); - uint32_t mask = prio; - // if semi transparent - if (((m_attr0 >> 10) & 0x3) == 0x1) - mask |= (0x1 << 18); - uint8_t* pChar = m_pChar + (m_attr2 & 0x3FF) * 32; - uint8_t colorInd; - if (m_attr0 & (0x1 << 13)) // if 256 colors mode - { - for (uint8_t i = 0; i < fwidth; ++i) - { - intX = curX >> 8; - intY = curY >> 8; - - // if we are on the object - if (intX >= 0 && intX < m_width*8 && - intY >= 0 && intY < m_height*8 && - // and we are on screen - ptr - surface < Screen::WIDTH && ptr >= surface) - { - if (mosH && (ptr - surface) % mosH) - *ptr = ptr[-1]; - else - { - colorInd = pChar[ - (intY/8) * (oneDim ? m_width : 16) * 8*8 - + (intX/8) * 8*8 - + (intY%8) * 8 - + (intX%8)]; - - // if there is something to draw - if (colorInd) - { - // if we have priority or there is nothing behind - if (prio < (*ptr & (0x3 << 16)) || !(*ptr & 0x8000)) - *ptr = m_pPalette[colorInd] | 0x8000 | mask; - } - // if we have nothing to draw - else - // if we have better priority - if (prio < (*ptr & (0x3 << 16))) - // we just modify priority and keep what was behind - *ptr = (*ptr & ~(0x3 << 16)) | (mask & (0x3 << 16)); - } - } - - ++ptr; - curX += a; - curY += c; - } - } - else - { - uint16_t* pPalette = m_pPalette + 16 * (m_attr2 >> 12); - for (uint8_t i = 0; i < fwidth; ++i) - { - intX = curX >> 8; - intY = curY >> 8; - - // if we are on the object - if (intX >= 0 && intX < m_width*8 && - intY >= 0 && intY < m_height*8 && - // and we are on screen - ptr - surface < Screen::WIDTH && ptr >= surface) - { - if (mosH && (ptr - surface) % mosH) - *ptr = ptr[-1]; - else - { - colorInd = pChar[( - (intY/8) * (oneDim ? m_width : 32) * 8*8 - + (intX/8) * 8*8 - + (intY%8) * 8 - + (intX%8) - ) / 2]; - - if (intX % 2) - colorInd >>= 4; - else - colorInd &= 0xF; - - // if there is something to draw - if (colorInd) - { - // if we have priority or there is nothing behind - if (prio < (*ptr & (0x3 << 16)) || !(*ptr & 0x8000)) - *ptr = pPalette[colorInd] | 0x8000 | mask; - } - // if we have nothing to draw - else - // if we have better priority - if (prio < (*ptr & (0x3 << 16))) - // we just modify priority and keep what was behind - *ptr = (*ptr & ~(0x3 << 16)) | (mask & (0x3 << 16)); - } - } - - ++ptr; - curX += a; - curY += c; - } - } - } - - void Object::DrawWindow (uint8_t line, uint8_t* surface, bool oneDim, - uint8_t mask) - { - // if the object is disabled or it's not an obj window - if (m_attr0 & (0x1 << 9) || ((m_attr0 >> 10) & 0x3) != 2) - return; - - // don't draw sprites with "prohibited" size - if (m_width == 0) - return; - - int16_t yoff = (m_attr0 & 0xFF); - if (yoff > Screen::HEIGHT) - yoff -= 256; - - // if the object does not appear on the line - if (yoff > line || yoff + m_height*8 <= line) - return; - - int16_t xoff = (m_attr1 & 0x1FF); - if (xoff & (0x1 << 8)) - xoff |= 0xFE00; // extend sign bit - - bool flipH = m_attr1 & (0x1 << 12); - uint8_t* ptr = surface + xoff; - if (flipH) - ptr += m_width * 8 - 1; - uint8_t* pChar = m_pChar + (m_attr2 & 0x3FF) * 32; - if (m_attr0 & (0x1 << 13)) // if 256 colors mode - { - // TODO 2d map, vert flips - // we set pChar on the tile - if (oneDim) - pChar += m_width * (8 * 8) * ((line-yoff) / 8); - else - pChar += (16 * 8 * 8) * ((line-yoff) / 8); - // and we go to the first pixel we need to draw - pChar += 8 * ((line-yoff) % 8); - for (uint8_t j = 0; j < m_width*8; ++j) - { - if (ptr - surface < Screen::WIDTH && ptr >= surface && *pChar) - *ptr = mask; - - if (flipH) - --ptr; - else - ++ptr; - - if ((j % 8) == 7) - // go to next tile - pChar += ((8*8) - (8) + 1); - else - ++pChar; - } - } - else - { - // TODO verts flips - // we set pChar on the tile - if (oneDim) - pChar += m_width * (8 * 8 / 2) * ((line-yoff) / 8); - else - pChar += (32 * 8 * 8 / 2) * ((line-yoff) / 8); - // and we go to the first pixel we need to draw - pChar += (8/2) * ((line-yoff) % 8); - uint8_t colorInd; - for (uint8_t j = 0; j < m_width*8; ++j) - { - if (j % 2) - { - colorInd = *pChar >> 4; - - if ((j % 8) == 7) - // go to next tile - // it doesn't matter if we are in one or two dimensions mapping - // since we never go on the next line - pChar += ((8*8/2) - (8/2) + 1); - else - ++pChar; - } - else - colorInd = *pChar & 0xF; - - // if we are not offscreen and there is a color - if (ptr - surface < Screen::WIDTH && ptr >= surface && colorInd) - *ptr = mask; - - if (flipH) - --ptr; - else - ++ptr; - } - } - } - - void Object::DrawWindowRot (uint8_t line, uint8_t* surface, - bool oneDim, int16_t a, int16_t b, int16_t c, int16_t d, uint8_t mask) - { - // if it's not an obj window - if (((m_attr0 >> 10) & 0x3) != 2) - return; - - // don't draw sprites with "prohibited" size - if (m_width == 0) - return; - - int16_t yoff = (m_attr0 & 0xFF); - if (yoff > Screen::HEIGHT) - yoff -= 256; - - int16_t xoff = (m_attr1 & 0x1FF); - if (xoff & (0x1 << 8)) - xoff |= 0xFE00; // extend sign bit - - uint8_t fwidth = m_width*8, fheight = m_height*8; - if (m_attr0 & (0x1 << 9)) - { - fwidth *= 2; - fheight *= 2; - } - - // if the object does not appear on the line - if (yoff > line || yoff + fheight <= line) - return; - - int32_t curX = ((m_width*8) << 8)/2 - + (-fwidth/2) * a + (line-yoff-fheight/2) * b; - int32_t curY = ((m_height*8) << 8)/2 - + (-fwidth/2) * c + (line-yoff-fheight/2) * d; - int32_t intX, intY; - - uint8_t* ptr = surface + xoff; - uint8_t* pChar = m_pChar + (m_attr2 & 0x3FF) * 32; - uint8_t colorInd; - if (m_attr0 & (0x1 << 13)) // if 256 colors mode - { - for (uint8_t i = 0; i < fwidth; ++i) - { - intX = curX >> 8; - intY = curY >> 8; - - if (intX >= 0 && intX < m_width*8 && - intY >= 0 && intY < m_height*8) - { - colorInd = pChar[ - (intY/8) * (oneDim ? m_width : 32) * 8*8 - + (intX/8) * 8*8 - + (intY%8) * 8 - + (intX%8)]; - - if (ptr - surface < Screen::WIDTH && ptr >= surface && colorInd) - *ptr = mask; - } - - ++ptr; - curX += a; - curY += c; - } - } - else - { - for (uint8_t i = 0; i < fwidth; ++i) - { - intX = curX >> 8; - intY = curY >> 8; - - if (intX >= 0 && intX < m_width*8 && - intY >= 0 && intY < m_height*8) - { - colorInd = pChar[( - (intY/8) * (oneDim ? m_width : 32) * 8*8 - + (intX/8) * 8*8 - + (intY%8) * 8 - + (intX%8) - ) / 2]; - - if (intX % 2) - colorInd >>= 4; - else - colorInd &= 0xF; - - if (ptr - surface < Screen::WIDTH && ptr >= surface && colorInd) - *ptr = mask; - } - - ++ptr; - curX += a; - curY += c; - } - } - } - - - void Object::UpdateAttrs (uint16_t attr0, uint16_t attr1, uint16_t attr2) - { - bool setsize = false, reload = false; - if ((m_attr0 & 0xFF00) != (attr0 & 0xFF00)) - { - reload = true; - setsize = true; - } - m_attr0 = attr0; - - if ((m_attr1 & 0xF000) != (attr1 & 0xF000)) - { - reload = true; - setsize = true; - } - m_attr1 = attr1; - - if ((m_attr2 & 0xF1FF) != (attr2 & 0xF1FF)) - reload = true; - m_attr2 = attr2; - - if (setsize) - { - SetSize(); - - if (reload) - { - m_charBegin = 0x06010000 + (m_attr2 & 0x3FF)*32; - m_charEnd = m_charBegin + m_width*m_height*8* - ((m_attr0 & (0x1 << 13)) ? 8 : 4); - } - } - } - - void Object::UpdateAttr0 (uint16_t attr0) - { - // FIXME : we can do a more restrictive condition - if ((m_attr0 & 0xFF00) != (attr0 & 0xFF00)) - { - m_attr0 = attr0; - SetSize(); - m_charEnd = m_charBegin + m_width*m_height*8* - ((m_attr0 & (0x1 << 13)) ? 8 : 4); - } - else - m_attr0 = attr0; - } - - void Object::UpdateAttr1 (uint16_t attr1) - { - // if the size has changed - if ((m_attr1 & 0xC000) != (attr1 & 0xC000)) - { - m_attr1 = attr1; - SetSize(); - m_charEnd = m_charBegin + m_width*m_height*8* - ((m_attr0 & (0x1 << 13)) ? 8 : 4); - } - else - m_attr1 = attr1; - } - - void Object::UpdateAttr2 (uint16_t attr2) - { - if ((m_attr2 & 0xF1FF) != (attr2 & 0xF1FF)) - { - m_attr2 = attr2; - m_charBegin = 0x06010000 + (m_attr2 & 0x3FF)*32; - m_charEnd = m_charBegin + m_width*m_height*8* - ((m_attr0 & (0x1 << 13)) ? 8 : 4); - } - else - m_attr2 = attr2; - } - - inline void Object::SetSize () - { - static const uint8_t Width[4][4] = { - {1, 2, 4, 8}, // Square - {2, 4, 4, 8}, // Horizontal - {1, 1, 2, 4}, // Vertical - {0, 0, 0, 0} // Prohibited - }; - static const uint8_t Height[4][4] = { - {1, 2, 4, 8}, // Square - {1, 1, 2, 4}, // Horizontal - {2, 4, 4, 8}, // Vertical - {0, 0, 0, 0} // Prohibited - }; - - m_width = Width[m_attr0 >> 14][m_attr1 >> 14]; - m_height = Height[m_attr0 >> 14][m_attr1 >> 14]; - } - } -} diff --git a/libmeteor/source/graphics/objects.cpp b/libmeteor/source/graphics/objects.cpp deleted file mode 100644 index 6de598a3c7..0000000000 --- a/libmeteor/source/graphics/objects.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/graphics/objects.hpp" -#include "../debug.hpp" -#include - -namespace AMeteor -{ - namespace Graphics - { - Objects::Objects (Memory& memory, Io& io, uint16_t* pPalette) : - m_io(io), - m_objs(128, Object(pPalette, - memory.GetRealAddress(0x06010000))), - m_pOam((uint16_t*)memory.GetRealAddress(0x07000000)) - { - } - - void Objects::DrawLine (uint8_t line, uint32_t* surface) - { - bool oneDim = m_io.DRead16(Io::DISPCNT) & (0x1 << 6); - uint8_t mosaic = m_io.DRead8(Io::MOSAIC+1); - int16_t rotSel; - for (Objs::iterator iter = m_objs.begin(); - iter != m_objs.end(); ++iter) - { - rotSel = iter->GetRotationParam(); - if (rotSel == -1) - iter->DrawLine (line, surface, oneDim, mosaic); - else - { - rotSel *= 16; - iter->DrawLineRot (line, surface, oneDim, m_pOam[rotSel + 3], - m_pOam[rotSel + 7], m_pOam[rotSel + 11], m_pOam[rotSel + 15], - mosaic); - } - } - } - - void Objects::DrawLineHighOnly (uint8_t line, uint32_t* surface) - { - bool oneDim = m_io.DRead16(Io::DISPCNT) & (0x1 << 6); - uint8_t mosaic = m_io.DRead8(Io::MOSAIC+1); - int16_t rotSel; - for (Objs::iterator iter = m_objs.begin(); - iter != m_objs.end(); ++iter) - if (iter->GetTileNum() >= 512) - { - rotSel = iter->GetRotationParam(); - if (rotSel == -1) - iter->DrawLine (line, surface, oneDim, mosaic); - else - { - rotSel *= 16; - iter->DrawLineRot (line, surface, oneDim, m_pOam[rotSel + 3], - m_pOam[rotSel + 7], m_pOam[rotSel + 11], m_pOam[rotSel + 15], - mosaic); - } - } - } - - void Objects::DrawWindow (uint8_t line, uint8_t* surface) - { - bool oneDim = m_io.DRead16(Io::DISPCNT) & (0x1 << 6); - int16_t rotSel; - uint8_t mask = (m_io.DRead16(Io::WINOUT) >> 8) & 0x3F; - for (Objs::iterator iter = m_objs.begin(); iter != m_objs.end(); ++iter) - if (iter->IsWindow()) - { - rotSel = iter->GetRotationParam(); - if (rotSel == -1) - iter->DrawWindow (line, surface, oneDim, mask); - else - { - rotSel *= 16; - iter->DrawWindowRot (line, surface, oneDim, m_pOam[rotSel + 3], - m_pOam[rotSel + 7], m_pOam[rotSel + 11], m_pOam[rotSel + 15], - mask); - } - } - } - - void Objects::OamWrite (uint32_t begin, uint32_t end) - { - uint32_t objnum; - // FIXME is this possible ? - if (begin & 0x3) - met_abort("OamWrite not 4 byte aligned"); - if (begin <= 0x07000000) - objnum = 0; - else - objnum = (begin - 0x07000000); - uint16_t* pOam = m_pOam + objnum/2; - objnum /= 8; - - Objs::iterator iterStart; - iterStart = m_objs.begin() + objnum; - Objs::iterator iterEnd = m_objs.begin() + (end - 0x07000000 + 7)/8; - if (iterEnd > m_objs.end()) - iterEnd = m_objs.end(); - - for (Objs::iterator iter = iterStart; iter != iterEnd; ++iter, ++objnum) - { - iter->UpdateAttrs(pOam[0], pOam[1], pOam[2]); - pOam += 4; - } - } - - void Objects::OamWrite16 (uint32_t add) - { - uint16_t objnum = (add - 0x07000000) / 8; - uint16_t* pOam = m_pOam + objnum*4; - Objs::iterator iter = m_objs.begin() + objnum; - switch ((add - 0x07000000) % 8) - { - case 0: - iter->UpdateAttr0(pOam[0]); - break; - case 2: - iter->UpdateAttr1(pOam[1]); - break; - case 4: - iter->UpdateAttr2(pOam[2]); - break; - case 6: - break; - default : - met_abort("Oam access not 16 bits aligned"); - break; - } - } - - void Objects::OamWrite32 (uint32_t add) - { - add -= 0x07000000; - uint16_t objnum = add / 8; - uint16_t* pOam = m_pOam + objnum * 4; - Objs::iterator iter = m_objs.begin() + objnum; - switch (add % 8) - { - case 0: - iter->UpdateAttr0(pOam[0]); - iter->UpdateAttr1(pOam[1]); - break; - case 4: - iter->UpdateAttr2(pOam[2]); - break; - default : - met_abort("Oam access not 32 bits aligned"); - break; - } - } - } -} diff --git a/libmeteor/source/graphics/renderer.cpp b/libmeteor/source/graphics/renderer.cpp deleted file mode 100644 index 2d689aaf08..0000000000 --- a/libmeteor/source/graphics/renderer.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/graphics/renderer.hpp" -#include "ameteor.hpp" - -namespace AMeteor -{ - namespace Graphics - { - Renderer::Renderer (const uint16_t* surface) : - m_base(surface) - { - } - - void Renderer::VBlank () - { - if (m_sig_frame) - m_sig_frame(m_base); - } - } -} diff --git a/libmeteor/source/graphics/screen.cpp b/libmeteor/source/graphics/screen.cpp deleted file mode 100644 index 06a3d86cc0..0000000000 --- a/libmeteor/source/graphics/screen.cpp +++ /dev/null @@ -1,423 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/graphics/screen.hpp" -#include "../globals.hpp" -#include "../debug.hpp" -#include "ameteor.hpp" - -#include - -namespace AMeteor -{ - namespace Graphics - { - BgLayer Screen::* const Screen::BgLayers [4] = - { &Screen::m_bgLayer0, &Screen::m_bgLayer1, - &Screen::m_bgLayer2, &Screen::m_bgLayer3 }; - - // TODO there is no more need to pass theses references - Screen::Screen (Memory& memory, Io& io) : - m_io(io), - m_surface(new uint16_t[WIDTH*HEIGHT]), - m_renderer(m_surface), - m_frameskip(0), - m_curframe(0), - m_dispcnt(0), - m_refX2(0), m_refY2(0), m_refX3(0), m_refY3(0), - m_pPalette((uint16_t*)memory.GetRealAddress(0x05000000)), - m_bgLayer0(0, memory, io, m_pPalette), - m_bgLayer1(1, memory, io, m_pPalette), - m_bgLayer2(2, memory, io, m_pPalette), - m_bgLayer3(3, memory, io, m_pPalette), - m_objs(memory, io, m_pPalette + 256) - { - } - - Screen::~Screen () - { - delete [] m_surface; - } - - void Screen::DrawLine (uint8_t line) - { - if (m_curframe < m_frameskip) - { - // we skip this frame - // VBlank - if (line == 159) - // we don't update screen since we haven't drawn anything on it, it - // would show up a buffer with the previous image or maybe only - // garbage (we use double buffering) - m_curframe = (m_curframe + 1) % FRMSKIP_TOTAL; - return; - } - - uint16_t* lineBg = new uint16_t[4*WIDTH]; - // layers may draw transparent pixels, so we need to clear them - memset(lineBg, 0, 4*WIDTH*sizeof(uint16_t)); - uint32_t* lineObj = new uint32_t[WIDTH]; - for (uint32_t* p = lineObj + WIDTH - 1; p >= lineObj; --p) - *p = 0x00030000; - uint8_t prio[4]; - prio[0] = m_bgLayer0.GetPriority(); - prio[1] = m_bgLayer1.GetPriority(); - prio[2] = m_bgLayer2.GetPriority(); - prio[3] = m_bgLayer3.GetPriority(); - uint8_t layersOn = (m_dispcnt >> 8) & 0x1F; - - switch (m_dispcnt & 0x7) - { - case 0: // all in mode 0 - // if the bg is enabled draw it - if (layersOn & (0x1 )) m_bgLayer0.DrawLine0(line, lineBg); - if (layersOn & (0x1 << 1)) m_bgLayer1.DrawLine0(line, lineBg+WIDTH); - if (layersOn & (0x1 << 2)) m_bgLayer2.DrawLine0(line, lineBg+2*WIDTH); - if (layersOn & (0x1 << 3)) m_bgLayer3.DrawLine0(line, lineBg+3*WIDTH); - // if objects are enabled draw them - if (layersOn & (0x1 << 4)) m_objs.DrawLine(line, lineObj); - break; - case 1: // bg0 and bg1 in mode 0 and bg2 in mode 2, no bg3 - // disable layer 3 - layersOn &= 0xF7; - // if the bg is enabled draw it - if (layersOn & (0x1 )) m_bgLayer0.DrawLine0(line, lineBg); - if (layersOn & (0x1 << 1)) m_bgLayer1.DrawLine0(line, lineBg+WIDTH); - if (layersOn & (0x1 << 2)) - m_bgLayer2.DrawLine2(lineBg+2*WIDTH, - m_refX2, m_refY2, - m_io.DRead16(Io::BG2PA), - m_io.DRead16(Io::BG2PC)); - // if objects are enabled draw them - if (layersOn & (0x1 << 4)) m_objs.DrawLine(line, lineObj); - break; - case 2: // bg2 and bg3 in mode 2, no bg0 and bg1 - // disable layers 0 and 1 - layersOn &= 0xFC; - // if the bg is enabled draw it - if (layersOn & (0x1 << 2)) - m_bgLayer2.DrawLine2(lineBg+2*WIDTH, - m_refX2, m_refY2, - m_io.DRead16(Io::BG2PA), - m_io.DRead16(Io::BG2PC)); - if (layersOn & (0x1 << 3)) - m_bgLayer3.DrawLine2(lineBg+3*WIDTH, - m_refX3, m_refY3, - m_io.DRead16(Io::BG3PA), - m_io.DRead16(Io::BG3PC)); - // if objects are enabled draw them - if (layersOn & (0x1 << 4)) m_objs.DrawLine(line, lineObj); - break; - case 3: // bg2 only 15 bit direct color 240x160 - layersOn &= 0xF4; - if (layersOn & (0x1 << 2)) - m_bgLayer2.DrawLine3(lineBg+2*WIDTH, - m_refX2, m_refY2, - m_io.DRead16(Io::BG2PA), - m_io.DRead16(Io::BG2PC)); - if (layersOn & (0x1 << 4)) - m_objs.DrawLineHighOnly(line, lineObj); - break; - // TODO (remember, HIGH ONLY for objs, don't make shitty copy paste) - case 4: // bg2 only in mode 4 (bitmap 256) - layersOn &= 0xF4; - // if bg2 is enabled - if (layersOn & (0x1 << 2)) - // draw it - m_bgLayer2.DrawLine4( - line, - lineBg+2*WIDTH, - m_refX2, m_refY2, - m_io.DRead16(Io::BG2PA), - m_io.DRead16(Io::BG2PB), - m_io.DRead16(Io::BG2PC), - m_io.DRead16(Io::BG2PD), - m_dispcnt & (0x1 << 4)); - // if objs are enabled - if (layersOn & (0x1 << 4)) - // all objs with the current priority - m_objs.DrawLineHighOnly(line, lineObj); - break; - case 5: // bg2 only 15 bit direct color 160x128 2 frames - layersOn &= 0xF4; - if (layersOn & (0x1 << 2)) - m_bgLayer2.DrawLine5(lineBg+2*WIDTH, - m_refX2, m_refY2, - m_io.DRead16(Io::BG2PA), - m_io.DRead16(Io::BG2PC), - m_dispcnt & (0x1 << 4)); - if (layersOn & (0x1 << 4)) - m_objs.DrawLineHighOnly(line, lineObj); - break; - default : - met_abort("not supported : " << (m_dispcnt & 0x7)); - break; - } - - // windows - /* I got very little information for this, it may not be accurate. All - * the sources don't say the same thing */ - uint8_t* window = NULL; - if (m_dispcnt >> 13) - { - window = new uint8_t[WIDTH]; - // Outside window - memset(window, m_io.DRead16(Io::WINOUT) & 0x3F, WIDTH*sizeof(uint8_t)); - // OBJ window - if (m_dispcnt & (0x1 << 15)) - m_objs.DrawWindow(line, window); - // Window 1 - if (m_dispcnt & (0x1 << 14)) - DrawWindow(line, window, - m_io.DRead16(Io::WIN1V), m_io.DRead16(Io::WIN1H), - (m_io.DRead16(Io::WININ) >> 8) & 0x3F); - // Window 0 - if (m_dispcnt & (0x1 << 13)) - DrawWindow(line, window, - m_io.DRead16(Io::WIN0V), m_io.DRead16(Io::WIN0H), - m_io.DRead16(Io::WININ) & 0x3F); - } - - // color effects - uint16_t bldcnt = m_io.DRead16(Io::BLDCNT); - uint8_t colorEffect = (bldcnt >> 6) & 0x3; - uint8_t eva = std::min(m_io.DRead8(Io::BLDALPHA) & 0x1F, 16); - uint8_t evb = std::min(m_io.DRead8(Io::BLDALPHA+1) & 0x1F, 16); - uint8_t evy = std::min(m_io.DRead8(Io::BLDY) & 0x1F, 16); - - // blending - uint16_t* surface = m_surface + line*WIDTH; - uint16_t out, bout; - // top and back are formated as follow : - // 4 bits | 4 bits - // priority | layer - uint8_t top, back; - uint8_t curprio; - uint32_t* pObj = lineObj; - uint16_t* pBg = lineBg; - uint8_t* pWin = window; - uint8_t winmask; - // if window are disabled, we draw everything which is enabled by - // layersOn - if (!window) - winmask = 0xFF; - for (uint8_t x = 0; x < WIDTH; ++x, ++pBg, ++pObj, ++pWin) - { - if (window) - winmask = *pWin; - - // backdrop - bout = out = m_pPalette[0]; - back = top = 0xF5; - - // for each layer - for (uint8_t l = 0; l < 4; ++l) - // if layer is enabled and - if ((layersOn & (0x1 << l)) && - // pixel to draw is not transparent - (pBg[l*WIDTH] & 0x8000)) - { - curprio = ((prio[l] << 4) | l); - - if (curprio < back && curprio > top) - { - bout = pBg[l*WIDTH]; - back = curprio; - } - else if ( - // priority is lower than current top pixel and - curprio < top && - // this layer should be drawn in current window - (winmask & (0x1 << l))) - { - bout = out; - out = pBg[l*WIDTH]; - back = top; - top = curprio; - } - } - - // now objects - // if objects are enabled - if ((layersOn & (0x1 << 4)) && - // pixel to draw is not transparent - (*pObj & 0x8000)) - { - curprio = ((*pObj >> (16 - 4)) & (0x3 << 4)); - - if (curprio <= (back & 0xF0) && curprio > (top & 0xF0)) - { - bout = *pObj; - back = curprio | 4; - } - else if (// priority is lower than current top pixel and - // NOTE : objects are OVER bg with same priority - curprio <= (top & 0xF0) && - // objects should be drawn in current window - (winmask & (0x1 << 4))) - { - bout = out; - out = *pObj; - back = top; - top = curprio | 4; - } - } - - // if we have an object on top and it has semi transparency - if ((top & 0xF) == 4 && (*pObj & (0x1 << 18))) - { - // if second target is just behind - if (bldcnt & ((0x1 << 8) << (back & 0xF))) - // apply alpha blend - out = - std::min(((bout & 0x001F) * evb + - (out & 0x001F) * eva) / 16, 0x001F) | - std::min((((bout & 0x03E0) * evb + - (out & 0x03E0) * eva) / 16) & 0xFFE0, 0x03E0) | - // no need to take care of over flow since u16 & s32 = s32 - std::min((((bout & 0x7C00) * evb + - (out & 0x7C00) * eva) / 16) & 0xFC00, 0x7C00); - } - // else if no window or window and effects are enabled in window - // and we have a first target on top - else if ((!window || (*pWin & (0x1 << 5))) - && (bldcnt & (0x1 << (top & 0xF)))) - switch (colorEffect) - { - case 1: // alpha blend - // if second target is just behind - // TODO optimization : special cases for eva = 0 or evb = 0 - if (bldcnt & ((0x1 << 8) << (back & 0xF))) - // apply alpha blend - out = - std::min(((bout & 0x001F) * evb + - (out & 0x001F) * eva) / 16, 0x001F) | - std::min((((bout & 0x03E0) * evb + - (out & 0x03E0) * eva) / 16) & 0xFFE0, 0x03E0) | - // no need to take care of over flow since u16 & s32 = s32 - std::min((((bout & 0x7C00) * evb + - (out & 0x7C00) * eva) / 16) & 0xFC00, 0x7C00); - break; - case 2: // brightness increase - // we don't need saturation since the formula makes it so it never - // goes above 0x1F - out = - (((out & 0x001F) + - ((0x001F - (out & 0x001F)) * evy) / 16) & 0x001F) | - (((out & 0x03E0) + - ((0x03E0 - (out & 0x03E0)) * evy) / 16) & 0x03E0) | - (((out & 0x7C00) + - ((0x7C00 - (out & 0x7C00)) * evy) / 16) & 0x7C00); - break; - case 3: // brightness decrease - // we don't need saturation since the formula makes it so it never - // goes below 0 - out = - ((((out & 0x001F) * (16-evy)) / 16) & 0x001F) | - ((((out & 0x03E0) * (16-evy)) / 16) & 0x03E0) | - ((((out & 0x7C00) * (16-evy)) / 16) & 0x7C00); - break; - } - - *surface = out; - ++surface; - } - - m_refX2 += (int16_t)m_io.DRead16(Io::BG2PB); - m_refY2 += (int16_t)m_io.DRead16(Io::BG2PD); - m_refX3 += (int16_t)m_io.DRead16(Io::BG3PB); - m_refY3 += (int16_t)m_io.DRead16(Io::BG3PD); - - if (window) - delete [] window; - delete [] lineBg; - delete [] lineObj; - - // VBlank - if (line == 159) - { - m_curframe = (m_curframe + 1) % FRMSKIP_TOTAL; - m_renderer.VBlank(); - } - } - - void Screen::DrawWindow (uint8_t line, uint8_t* surface, - uint16_t win0v, uint16_t win0h, uint8_t mask) - { - // the variables are called win0, but this function works also for win1 - uint8_t win0t = win0v >> 8, win0b = win0v & 0xFF; - // VBA says that if t == b and they are greater than 228, we are in the - // window - // This is from Tonc documentation - if (win0t >= 227) - return; - else if (win0b > win0t && line >= win0t && line < win0b - // the above is the normal behaviour - || win0b < win0t && (line >= win0t || line < win0b) - // the above is the "inverted" behaviour - ) - { - uint8_t win0l, win0r; - uint8_t* ptr; - win0l = win0h >> 8; - win0r = win0h & 0xFF; - // this seems wrong - //if (win0l > 240) - // win0l = 240; - //if (win0r > 240) - // win0r = 240; - - // if this is the normal behaviour - if (win0l <= win0r) - { - ptr = surface + win0l; - for (uint8_t i = win0l; i < win0r && i < 240; ++i, ++ptr) - *ptr = mask; - } - // else, this is the inverted behaviour - else - { - ptr = surface; - for (uint8_t i = 0; i < win0r && i < 240; ++i, ++ptr) - *ptr = mask; - ptr = surface + win0l; - for (uint8_t i = win0l; i < 240; ++i, ++ptr) - *ptr = mask; - } - } - } - - bool Screen::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_refX2); - SS_WRITE_VAR(m_refY2); - SS_WRITE_VAR(m_refX3); - SS_WRITE_VAR(m_refY3); - - return true; - } - - bool Screen::LoadState (std::istream& stream) - { - SS_READ_VAR(m_refX2); - SS_READ_VAR(m_refY2); - SS_READ_VAR(m_refX3); - SS_READ_VAR(m_refY3); - - return true; - } - } -} diff --git a/libmeteor/source/interpreter.cpp b/libmeteor/source/interpreter.cpp deleted file mode 100644 index 66731435a9..0000000000 --- a/libmeteor/source/interpreter.cpp +++ /dev/null @@ -1,222 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/interpreter.hpp" -#include "ameteor/cpu.hpp" -#include "ameteor/memory.hpp" -#include "ameteor/bios.hpp" -#include "ameteor/disassembler/instruction.hpp" -#include "globals.hpp" -#include "cpu_globals.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" -#include - -namespace AMeteor -{ - Interpreter::Interpreter() : - m_run(false), - m_interrupt_(false), - m_haltcnt(IO.GetRef8(Io::HALTCNT)), - m_if(IO.GetRef16(Io::IF)), - m_ie(IO.GetRef16(Io::IE)) - { - } - - void Interpreter::SendInterrupt (uint16_t interrupt) - { - IO.GetRef16(Io::IF) |= interrupt; - if ((interrupt & IO.DRead16(Io::IE)) && - (IO.DRead16(Io::IME) & 0x1) && - !m_st.icpsr.irq_d) - // irq are enabled and theses irq are enabled... - m_interrupt = true; - } - - void Interpreter::CheckInterrupt () - { - m_interrupt = - (IO.DRead16(Io::IF) & IO.DRead16(Io::IE)) && - (IO.DRead16(Io::IME) & 0x1) && - !m_st.icpsr.irq_d; - } - - void Interpreter::Run (unsigned int cycles) - { - m_run = true; - CLOCK.ResetCounter(); - while(m_run && CLOCK.GetCounter() < cycles) - { - switch (m_haltcnt) - { - case 255: // normal mode - PrintRegs(); - if (FLAG_T) - { - if (R(15) & 0x1) - met_abort("PC not 16 bit aligned : " << IOS_ADD << R(15)); - - code = MEM.Read16(R(15)-2); - if (traceenabled) - { - std::stringstream ss; - ss << IOS_TRACE << R(15) - 2 << ':' << std::setw(4) << code << " "; - ss.setf(std::ios::left, std::ios::adjustfield); - ss << std::setw(32) << std::setfill(' ') << Disassembler::Instruction(R(15), (uint16_t)code).ToString(); - ss.setf(std::ios::right, std::ios::adjustfield); - ss << IOS_TRACE; - for (int i = 0; i < 16; i++) - ss << std::setw(8) << R(i) << ' '; - UpdateCpsr(); - ss << std::setw(8) << m_st.cpsr.dw << ' '; - ss << std::setw(8) << m_st.spsr.dw << ' '; - trace_bizhawk(ss.str()); - } - R(15) += 2; - t_Code(); - } - else - { - if (R(15) & 0x3) - met_abort("PC not 32 bit aligned : " << IOS_ADD << R(15)); - - if (R(15) < 0x01000000 && !MEM.HasBios()) - { - switch (R(15)) - { - case 0x004: - Bios::Bios000h(); - break; - case 0x00C: - Bios::Bios008h(); - break; - case 0x01C: - Bios::Bios018h(); - break; - case 0x134: - Bios::Bios130h(); - break; - case 0x33C: - Bios::Bios338h(); - break; - case 0x16C: - Bios::Bios168h(); - break; - default: - met_abort("Jump to " << IOS_ADD << R(15)); - } - } - else - { - code = MEM.Read32(R(15)-4); - if (traceenabled) - { - std::stringstream ss; - ss << IOS_TRACE << R(15) - 4 << ':' << std::setw(8) << code << ' '; - ss.setf(std::ios::left, std::ios::adjustfield); - ss << std::setw(32) << std::setfill(' ') << Disassembler::Instruction(R(15), (uint32_t)code).ToString(); - ss.setf(std::ios::right, std::ios::adjustfield); - ss << IOS_TRACE; - for (int i = 0; i < 16; i++) - ss << std::setw(8) << R(i) << ' '; - UpdateCpsr(); - ss << std::setw(8) << m_st.cpsr.dw << ' '; - ss << std::setw(8) << m_st.spsr.dw << ' '; - trace_bizhawk(ss.str()); - } - R(15) += 4; - a_Code(); - } - } - if (R(15) < 0x01000000 && FLAG_T && !MEM.HasBios()) - met_abort("Jump to " << IOS_ADD << R(15)); - - CLOCK.Commit(); - - if (m_interrupt) - // irq are enabled and there are irq waiting... - { - // FIXME : do we really need this ?? - // if not, we can get rid of save and load state and reset - if (m_interrupt_) - { - m_interrupt_ = false; - // XXX we must be sure the cpu isn't halted when an interrupt - // occurs - // should be removed after since it takes no time to make a new - // iteration of the loop - m_haltcnt = 255; - CPU.Interrupt(); - } - else - { - // XXX - if (m_haltcnt != 255) - { - m_haltcnt = 255; - CPU.Interrupt(); - } - else - m_interrupt_ = true; - } - } - - break; - case 0: // halt mode - if (m_if & m_ie) // interrupt occured - { - m_haltcnt = 255; // return to normal mode - CPU.Interrupt(); - // XXX use an else - break; - } - - CLOCK.WaitForNext(); - - // XXX remove this block - if (m_if & m_ie) // interrupt occured - { - m_haltcnt = 255; // return to normal mode - CPU.Interrupt(); - } - - break; - case 1: // stop mode - met_abort("Stop mode not implemented"); - break; - default: - met_abort("Unknown HALTCNT value : " << (int)m_haltcnt); - break; - } - } - m_run = false; - } - - bool Interpreter::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_interrupt_); - - return Cpu::SaveState(stream); - } - - bool Interpreter::LoadState (std::istream& stream) - { - SS_READ_VAR(m_interrupt_); - - return Cpu::LoadState(stream); - } -} diff --git a/libmeteor/source/interpreter_arm.cpp b/libmeteor/source/interpreter_arm.cpp deleted file mode 100644 index 731972848d..0000000000 --- a/libmeteor/source/interpreter_arm.cpp +++ /dev/null @@ -1,1477 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __INTERPRETER_ARM_H__ -#define __INTERPRETER_ARM_H__ - -/* - -- From GBATEK - - -ARM Binary Opcode Format - -|..3 ..................2 ..................1 ..................0| -|1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0| -|_Cond__|0_0_0|___Op__|S|__Rn___|__Rd___|__Shift__|Typ|0|__Rm___| DataProc -|_Cond__|0_0_0|___Op__|S|__Rn___|__Rd___|__Rs___|0|Typ|1|__Rm___| DataProc -|_Cond__|0_0_1|___Op__|S|__Rn___|__Rd___|_Shift_|___Immediate___| DataProc -|_Cond__|0_0_1_1_0|P|1|0|_Field_|__Rd___|_Shift_|___Immediate___| PSR Imm -|_Cond__|0_0_0_1_0|P|L|0|_Field_|__Rd___|0_0_0_0|0_0_0_0|__Rm___| PSR Reg -|_Cond__|0_0_0_1_0_0_1_0_1_1_1_1_1_1_1_1_1_1_1_1|0_0|L|1|__Rn___| BX,BLX -|1_1_1_0|0_0_0_1_0_0_1_0|_____immediate_________|0_1_1_1|_immed_| BKPT ARM9 -|_Cond__|0_0_0_1_0_1_1_0_1_1_1_1|__Rd___|1_1_1_1|0_0_0_1|__Rm___| CLZ ARM9 -|_Cond__|0_0_0_1_0|Op_|0|__Rn___|__Rd___|0_0_0_0|0_1_0_1|__Rm___| QALU ARM9 -|_Cond__|0_0_0_0_0_0|A|S|__Rd___|__Rn___|__Rs___|1_0_0_1|__Rm___| Multiply -|_Cond__|0_0_0_0_1|U|A|S|_RdHi__|_RdLo__|__Rs___|1_0_0_1|__Rm___| MulLong -|_Cond__|0_0_0_1_0|Op_|0|Rd/RdHi|Rn/RdLo|__Rs___|1|y|x|0|__Rm___| MulHalf -|_Cond__|0_0_0_1_0|B|0_0|__Rn___|__Rd___|0_0_0_0|1_0_0_1|__Rm___| TransSwp12 -|_Cond__|0_0_0|P|U|0|W|L|__Rn___|__Rd___|0_0_0_0|1|S|H|1|__Rm___| TransReg10 -|_Cond__|0_0_0|P|U|1|W|L|__Rn___|__Rd___|OffsetH|1|S|H|1|OffsetL| TransImm10 -|_Cond__|0_1_0|P|U|B|W|L|__Rn___|__Rd___|_________Offset________| TransImm9 -|_Cond__|0_1_1|P|U|B|W|L|__Rn___|__Rd___|__Shift__|Typ|0|__Rm___| TransReg9 -|_Cond__|0_1_1|________________xxx____________________|1|__xxx__| Undefined -|_Cond__|1_0_0|P|U|S|W|L|__Rn___|__________Register_List________| BlockTrans -|_Cond__|1_0_1|L|___________________Offset______________________| B,BL,BLX -|_Cond__|1_1_0|P|U|N|W|L|__Rn___|__CRd__|__CP#__|____Offset_____| CoDataTrans -|_Cond__|1_1_0_0_0_1_0|L|__Rn___|__Rd___|__CP#__|_CPopc_|__CRm__| CoRR ARM9 -|_Cond__|1_1_1_0|_CPopc_|__CRn__|__CRd__|__CP#__|_CP__|0|__CRm__| CoDataOp -|_Cond__|1_1_1_0|CPopc|L|__CRn__|__Rd___|__CP#__|_CP__|1|__CRm__| CoRegTrans -|_Cond__|1_1_1_1|_____________Ignored_by_Processor______________| SWI - -*/ - -#include "ameteor/interpreter.hpp" -#include "globals.hpp" -#include "cpu_globals.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" - -#define Rn ((code >> 16) & 0xF) -#define Rd ((code >> 12) & 0xF) -#define Rs ((code >> 8) & 0xF) -#define Rm (code & 0xF) - -// Load/Store immediate offset -#define LSOff (code & 0xFFF) - -#ifdef METDEBUG -# define NOT_PC(reg) \ - if (reg == 15) \ - met_abort("Register is PC") -# define NOT_PC_ALL() \ - NOT_PC(Rn); \ - NOT_PC(Rd); \ - NOT_PC(Rs); \ - NOT_PC(Rm) -# define NOT_SAME2(reg1, reg2) \ - if (reg1 == reg2) \ - met_abort("Two same registers") -# define NOT_SAME3(reg1, reg2, reg3) \ - NOT_SAME2(reg1, reg2); \ - NOT_SAME2(reg2, reg3); \ - NOT_SAME2(reg1, reg3) -#else -# define NOT_PC(reg) {} -# define NOT_PC_ALL() {} -# define NOT_SAME2(reg1, reg2) {} -# define NOT_SAME3(reg1, reg2, reg3) {} -#endif - -#define ARM(name) \ - inline void Interpreter::a##name () -#define NIARM(name) \ - void Interpreter::a##name () - -namespace AMeteor -{ - // Branch and Exchange - ARM(BXBLX) - { - if ((code & 0x0FFFFF00) != 0x012FFF00) - met_abort("Bits 8-27 must be 0001 00101111 11111111 for BX/BLX instructions"); - - if (Rm == 15) - met_abort("Branching on PC is undefined"); - - if (code & (0x1 << 5)) // BLX - { - R(14) = R(15); - met_abort("BLX not completly implemented"); - } - // else BX - - if (R(Rm) & 0x1) - { - FLAG_T = 1; - R(15) = R(Rm) + 1; - CYCLES32NSeq(R(15), 3); - } - else - { - if (R(Rm) & 0x3) - met_abort("BX with ARM on non 32 bit aligned address"); - R(15) = R(Rm)+4; - CYCLES32NSeq(R(15), 3); - } - } - - // Branch and Branch with Link - ARM(BBL) - { - if (((code >> 25) & 0x7) != 0x5) - met_abort("Bits 25-27 must be 101 for B/BL/BLX instructions"); - - if (((code >> 28) & 0xF) == 0xF) - met_abort("BLX not implemented"); - - int32_t off = code & 0x00FFFFFF; - // Extend the sign bit - off <<= 8; - off >>= 8; - // off is in steps of 4 - off *= 4; - - if (code & (0x1 << 24)) // BL - { - // R(15) points two instructions later, R(14) should point to next - // instruction - // LR = PC + 4 and R15 = PC + 8 - R(14) = R(15) - 4 ; - } - // else B - R(15) += off + 4; - CYCLES32NSeq(R(15), 3); - } - - // Data Processing - NIARM(_DataProcShiftImm) - { - if ((code >> 26) & 0x3) - met_abort("Bits 26-27 must be 00 for DataProc instructions"); - - uint8_t shift; - uint32_t op2 = 0; // to avoid a warning - bool shiftcarry = FLAG_C; - uint8_t rd = Rd; - - uint8_t rm = Rm; - if (rm == 15 && !(code & (0x1 << 20)) && (code & (0x1 << 4))) - met_abort("Rm = 15, not implemented"); - - shift = (code >> 7) & 0x1F; - switch ((code >> 5) & 0x3) - { - case 0: // Logical Shift Left - if (shift) - { - op2 = R(rm) << shift; - shiftcarry = (R(rm) >> (32-shift)) & 0x1; - } - else // LSL#0 - op2 = R(rm); - break; - case 1: // Logical Shift Right - if (shift) - { - op2 = R(rm) >> shift; - shiftcarry = (R(rm) >> (shift-1)) & 0x1; - } - else // LSR#32 - { - op2 = 0; - shiftcarry = R(rm) >> 31; - } - break; - case 2: // Arithmetic Shift Right - if (shift) - { - op2 = ((int32_t)R(rm)) >> shift; - shiftcarry = (((int32_t)R(rm)) >> (shift-1)) & 0x1; - } - else // ASR#32 - { - op2 = ((int32_t)R(rm)) >> 31; - shiftcarry = op2 & 0x1; - } - break; - case 3: // ROtate Right - if (shift) - { - op2 = ROR(R(rm), shift); - shiftcarry = op2 >> 31; - } - else // RRX#1 - { - shiftcarry = R(rm) & 0x1; - op2 = (FLAG_C << 31) | (R(rm) >> 1); - } - break; - } - - a_DataProcCore(rd, R(Rn), op2, shiftcarry); - } - - NIARM(_DataProcShiftReg) - { - if ((code >> 26) & 0x3) - met_abort("Bits 26-27 must be 00 for DataProc instructions"); - if (code & (0x1 << 7)) - met_abort("Bit 7 must be 0 for DataProc with shift by register instructions"); - - uint8_t shift; - uint32_t op1, op2 = 0; // to avoid a warning - bool shiftcarry = FLAG_C; - uint8_t rd = Rd; - - uint8_t rm = Rm; - if (rm == 15 && !(code & (0x1 << 20)) && (code & (0x1 << 4))) - met_abort("Rm = 15, not implemented"); - - op1 = R(Rn); - - NOT_PC(Rs); - ICYCLES(1); - if (Rn == 15) - op1 += 4; - - shift = R(Rs) & 0xFF; // only first byte used - if (shift) - switch ((code >> 5) & 0x3) - { - case 0: // Logical Shift Left - if (shift == 32) - { - op2 = 0; - shiftcarry = R(rm) & 0x1; - } - else if (shift < 32) - { - op2 = R(rm) << shift; - shiftcarry = (R(rm) >> (32-shift)) & 0x1; - } - else - { - op2 = 0; - shiftcarry = 0; - } - break; - case 1: // Logical Shift Right - if (shift == 32) - { - op2 = 0; - shiftcarry = R(rm) >> 31; - } - else if (shift < 32) - { - op2 = R(rm) >> shift; - shiftcarry = (R(rm) >> (shift-1)) & 0x1; - } - else - { - op2 = 0; - shiftcarry = 0; - } - break; - case 2: // Arithmetic Shift Right - if (shift >= 32) - { - op2 = ((int32_t)R(rm)) >> 31; - shiftcarry = op2 & 0x1; - } - else - { - op2 = ((int32_t)R(rm)) >> shift; - shiftcarry = (((int32_t)R(rm)) >> (shift-1)) & 0x1; - } - break; - case 3: // ROtate Right - op2 = ROR(R(rm), shift % 32); - shiftcarry = op2 >> 31; - break; - } - else - op2 = R(rm); - - a_DataProcCore(rd, op1, op2, shiftcarry); - } - - NIARM(_DataProcImm) - { - if ((code >> 26) & 0x3) - met_abort("Bits 26-27 must be 00 for DataProc instructions"); - - uint32_t op2; - bool shiftcarry = FLAG_C; - uint8_t rd = Rd; - - uint8_t shift = ((code >> 8) & 0xF); - if (shift) - { - op2 = ROR(code & 0xFF, shift * 2); - shiftcarry = op2 >> 31; - } - else - op2 = code & 0xFF; - - a_DataProcCore(rd, R(Rn), op2, shiftcarry); - } - - inline void Interpreter::a_DataProcCore(uint8_t rd, - uint32_t op1, uint32_t op2, bool shiftcarry) - { - uint8_t opcode = (code >> 21) & 0xF; - - if (opcode < 0x8 || opcode > 0xB) - { - } - else if (!((code >> 20) & 0x1) || (rd != 0x0 && rd != 0xF)) - met_abort("Set condition bit not set for test operation or Rd not acceptable for a test"); - if ((opcode == 0xD || opcode == 0xF) && Rn) - met_abort("Rn not null for MOV or MVN"); - -#ifndef X86_ASM - uint32_t res; -#endif - - if (code & (0x1 << 20)) // if set condition - { - switch (opcode) - { - case 0x0 : // AND -#ifdef X86_ASM - asm("andl %4, %3\n" - "setzb %1\n" - "setsb %2\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N) - :"0"(op1), "r"(op2)); -#else - res = R(rd) = op1 & op2; - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - FLAG_C = shiftcarry; - break; - case 0x1 : // EOR -#ifdef X86_ASM - asm("xorl %4, %3\n" - "setzb %1\n" - "setsb %2\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N) - :"0"(op1), "r"(op2)); -#else - res = R(rd) = op1 ^ op2; - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - FLAG_C = shiftcarry; - break; - case 0x2 : // SUB -#ifdef X86_ASM - asm("subl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setncb %3\n" - "setob %4\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), - "=m"(FLAG_V) - :"0"(op1), "r"(op2)); -#else - res = R(rd) = op1 - op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); -#endif - break; - case 0x3 : // RSB -#ifdef X86_ASM - asm("subl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setncb %3\n" - "setob %4\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), - "=m"(FLAG_V) - :"0"(op2), "r"(op1)); -#else - res = R(rd) = op2 - op1; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); -#endif - break; - case 0x4 : // ADD -#ifdef X86_ASM - asm("addl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setcb %3\n" - "setob %4\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), - "=m"(FLAG_V) - :"0"(op1), "r"(op2)); -#else - res = R(rd) = op1 + op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = ADDCARRY(op1, op2, res); - FLAG_V = ADDOVERFLOW(op1, op2, res); -#endif - break; - case 0x5 : // ADC - // TODO test on hardware how overflow and carry work for this - // instruction -#ifdef X86_ASM - asm("addl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setcb %3\n" - "setob %4\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), - "=m"(FLAG_V) - :"0"(op1+FLAG_C), "r"(op2)); -#else - res = R(rd) = op1 + op2 + FLAG_C; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = ADDCARRY(op1, op2, res); - FLAG_V = ADDOVERFLOW(op1, op2, res); -#endif - break; - case 0x6 : // SBC - // TODO test on hardware how overflow and carry work for this - // instruction -#ifdef X86_ASM - asm("subl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setncb %3\n" - "setob %4\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), - "=m"(FLAG_V) - :"0"(op1+FLAG_C-1), "r"(op2)); -#else - res = R(rd) = op1 - op2 + FLAG_C - 1; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); -#endif - break; - case 0x7 : // RSC -#ifdef X86_ASM - asm("subl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setncb %3\n" - "setob %4\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), - "=m"(FLAG_V) - :"0"(op2+FLAG_C-1), "r"(op1)); -#else - res = R(rd) = op2 - op1 + FLAG_C - 1; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); -#endif - break; - case 0x8 : // TST -#ifdef X86_ASM - asm("testl %3, %2\n" - "setzb %0\n" - "setsb %1\n" - :"=m"(FLAG_Z), "=m"(FLAG_N) - :"r"(op1), "r"(op2)); -#else - res = op1 & op2; - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - SETFB(C, shiftcarry); - break; - case 0x9 : // TEQ -#ifdef X86_ASM - asm("xorl %3, %2\n" - "setzb %0\n" - "setsb %1\n" - :"=m"(FLAG_Z), "=m"(FLAG_N) - :"r"(op1), "r"(op2) - :"2"); -#else - res = op1 ^ op2; - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - SETFB(C, shiftcarry); - break; - case 0xA : // CMP -#ifdef X86_ASM - asm("cmpl %5, %4\n" - "setzb %0\n" - "setsb %1\n" - "setncb %2\n" - "setob %3\n" - :"=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"r"(op1), "r"(op2)); -#else - res = op1 - op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); -#endif - break; - case 0xB : // CMN -#ifdef X86_ASM - asm("addl %5, %4\n" - "setzb %0\n" - "setsb %1\n" - "setcb %2\n" - "setob %3\n" - :"=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"r"(op1), "r"(op2) - :"4"); -#else - res = op1 + op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = ADDCARRY(op1, op2, res); - FLAG_V = ADDOVERFLOW(op1, op2, res); -#endif - break; - case 0xC : // ORR -#ifdef X86_ASM - asm("orl %4, %3\n" - "setzb %1\n" - "setsb %2\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N) - :"0"(op1), "r"(op2)); -#else - res = R(rd) = op1 | op2; - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - FLAG_C = shiftcarry; - break; - case 0xD : // MOV -#ifdef X86_ASM - R(rd) = op2; - asm("testl %2, %2\n" - "setzb %0\n" - "setsb %1\n" - :"=m"(FLAG_Z), "=m"(FLAG_N) - :"r"(op2)); -#else - res = R(rd) = op2; - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - FLAG_C = shiftcarry; - break; - case 0xE : // BIC -#ifdef X86_ASM - asm("not %3\n" - "andl %4, %3\n" - "setzb %1\n" - "setsb %2\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N) - :"0"(op2), "r"(op1)); -#else - res = R(rd) = op1 & ~op2; - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - FLAG_C = shiftcarry; - break; - case 0xF : // MVN -#ifdef X86_ASM - asm("xorl $0xffffffff, %3\n" - "setzb %1\n" - "setsb %2\n" - :"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N) - :"0"(op2)); -#else - res = R(rd) = ~op2; - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - FLAG_C = shiftcarry; - break; - } - - if (rd == 15) - CPU.SwitchModeBack(); - } - else - switch (opcode) - { - case 0x0 : // AND - R(rd) = op1 & op2; - break; - case 0x1 : // EOR - R(rd) = op1 ^ op2; - break; - case 0x2 : // SUB - R(rd) = op1 - op2; - break; - case 0x3 : // RSB - R(rd) = op2 - op1; - break; - case 0x4 : // ADD - R(Rd) = op1 + op2; - break; - case 0x5 : // ADC - R(rd) = op1 + op2 + FLAG_C; - break; - case 0x6 : // SBC - R(rd) = op1 - op2 + FLAG_C - 1; - break; - case 0x7 : // RSC - R(rd) = op2 - op1 + FLAG_C - 1; - break; - case 0x8 : // TST - case 0x9 : // TEQ - case 0xA : // CMP - case 0xB : // CMN - met_abort("Comparison or test without set flags bit"); - break; - case 0xC : // ORR - R(rd) = op1 | op2; - break; - case 0xD : // MOV - R(rd) = op2; - break; - case 0xE : // BIC - R(rd) = op1 & ~op2; - break; - case 0xF : // MVN - R(rd) = ~op2; - break; - } - - if (rd == 15 && (opcode < 0x8 || opcode > 0xB)) - { - if (FLAG_T) - { - CYCLES16NSeq(R(15), 3); - R(15) += 2; - } - else - { - CYCLES32NSeq(R(15), 3); - R(15) += 4; - } - } - else - CYCLES32Seq(R(15), 1); - - if (opcode >= 0x8 && opcode <= 0xB && rd == 0xF) - met_abort("P test instruction (not implemented)"); - } - - // PSR Transfer (MRS, MSR) - ARM(PSR) - { - if ((code >> 26) & 0x3) - met_abort("Bits 26-27 must be 00 for PSR instructions"); - if (((code >> 23) & 0x3) != 0x2) - met_abort("Bits 23-24 must be 10 for PSR instructions"); - if (code & (0x1 << 20)) - met_abort("Bit 20 must be 0 for PSR instructions"); - - bool oncpsr = !(code & (0x1 << 22)); - if (oncpsr) - CPU.UpdateCpsr(); - uint32_t& psr = oncpsr ? CPSR : SPSR; - - if (code & (0x1 << 21)) // MSR - { - if (((code >> 12) & 0xF) != 0xF) - met_abort("Bits 12-15 must be 0xF for MSR instruction"); - - uint32_t val; - if (code & (0x1 << 25)) - { - //val = ROR(code & 0xF, ((code >> 8) & 0x4) * 2); - val = ROR(code & 0xF, (code >> 7) & 0x6); - } - else - { - if ((code >> 4) & 0xFF) - met_abort("Bits 4-11 must be 0 for MSR instruction"); - val = R(Rm); - } - if (!(code & (0x1 << 19))) - val = (val & 0x00FFFFFF) | (psr & 0xFF000000); - if (!(code & (0x1 << 18))) - val = (val & 0xFF00FFFF) | (psr & 0x00FF0000); - if (!(code & (0x1 << 17))) - val = (val & 0xFFFF00FF) | (psr & 0x0000FF00); - if (!(code & (0x1 << 16))) - val = (val & 0xFFFFFF00) | (psr & 0x000000FF); - else if (oncpsr && - (psr & 0x1F) != (val & 0x1F)) // have we changed mode ? - CPU.SwitchToMode(val & 0x1F); - psr = val; - if (oncpsr) - { - CPU.UpdateICpsr(); - CPU.CheckInterrupt(); - } - } - else // MRS - { - if ((code >> 25) & 0x1) - met_abort("Bit 25 must be 0 for MRS instruction"); - if (((code >> 16) & 0xF) != 0xF) - met_abort("Bits 16-19 must be 0xF for MRS instruction"); - if (code & 0xFFF) - met_abort("Bits 0-11 must be 0 for MRS instruction"); - R(Rd) = psr; - } - - CYCLES32Seq(R(15), 1); - } - - // Multiply and Multiply-Accumulate (MUL,MLA) - ARM(_Multiply) - { - // NOTE : In this instruction Rn and Rd are inverted - if ((code >> 25) & 0x7) - met_abort("Bits 25-27 must be 000 for Multiply instructions"); - if (code & (0x1 << 24)) - { - if (!(code & (0x1 << 7))) - met_abort("Bit 7 must be 1 for halfword multiply"); - if (code & (0x1 << 4)) - met_abort("Bit 7 must be 0 for halfword multiply"); - } - else - { - if (((code >> 4) & 0xF) != 0x9) - met_abort("Bits 4-7 must be 1001 for non halfword multiplies"); - } - NOT_PC_ALL(); - - switch ((code >> 21) & 0xF) - { - case 0x0 : // MUL - if (Rd != 0) - met_abort("Rd must be 0 for MUL instructions"); - NOT_SAME2(Rn, Rm); - R(Rn) = R(Rm)*R(Rs); - if (code & (0x1 << 20)) - { - FZ(R(Rn)); - FN(R(Rn)); - } - MULICYCLES(Rs); - CYCLES32Seq(R(15), 1); - break; - case 0x1 : // MLA - NOT_SAME2(Rn, Rm); - R(Rn) = R(Rm)*R(Rs)+R(Rd); - if (code & (0x1 << 20)) - { - FZ(R(Rn)); - FN(R(Rn)); - } - MULICYCLES(Rs); - ICYCLES(1); - CYCLES32Seq(R(15), 1); - break; - case 0x4 : // UMULL - { - NOT_SAME3(Rn, Rd, Rm); - uint64_t out = ((uint64_t)R(Rm))*((uint64_t)R(Rs)); - R(Rn) = out >> 32; - R(Rd) = out & 0xFFFFFFFF; - if (code & (0x1 << 20)) - { - FZ(out); - FN(R(Rn)); - } - } - MULICYCLES(Rs); - ICYCLES(1); - CYCLES32Seq(R(15), 1); - break; - case 0x5 : // UMLAL - { - NOT_SAME3(Rn, Rd, Rm); - uint64_t out = - ((uint64_t)R(Rm)) * ((uint64_t)R(Rs)) + - ((((uint64_t)R(Rn)) << 32) | ((uint64_t)R(Rd))); - R(Rn) = out >> 32; - R(Rd) = out & 0xFFFFFFFF; - if (code & (0x1 << 20)) - { - FZ(out); - FN(R(Rn)); - } - } - MULICYCLES(Rs); - ICYCLES(2); - CYCLES32Seq(R(15), 1); - break; - case 0x6 : // SMULL - { - NOT_SAME3(Rn, Rd, Rm); - int64_t out = ((int64_t)(int32_t)R(Rm)) * ((int64_t)(int32_t)R(Rs)); - R(Rn) = out >> 32; - R(Rd) = out & 0xFFFFFFFF; - if (code & (0x1 << 20)) - { - FZ(out); - FN(R(Rn)); - } - } - MULICYCLES(Rs); - ICYCLES(1); - CYCLES32Seq(R(15), 1); - break; - case 0x7 : // SMLAL - { - NOT_SAME3(Rn, Rd, Rm); - int64_t out = ((int64_t)(int32_t)R(Rm)) * ((int64_t)(int32_t)R(Rs)) - + ((((int64_t)R(Rn)) << 32) | ((int64_t)R(Rd))); - R(Rn) = out >> 32; - R(Rd) = out & 0xFFFFFFFF; - if (code & (0x1 << 20)) - { - FZ(out); - FN(R(Rn)); - } - } - MULICYCLES(Rs); - ICYCLES(2); - CYCLES32Seq(R(15), 1); - break; - case 0x8 : // SMLAxy - case 0x9 : // SMLAW/SMULW - case 0xA : // SMLALxy - case 0xB : // SMULxy - default : - met_abort("Not implemented multiply instruction or unknown"); - } - } - - // Single Data Transfer (LDR, STR, PLD) - - // Load and store - // FIXME : should this support Prepare Cache for Load instructions ? - ARM(LDRSTR) - { - if (((code >> 28) & 0xF) == 0xF) - met_abort("PLD instructions not implemented"); - if (((code >> 26) & 0x3) != 0x1) - met_abort("Bits 26-27 must be 01 for LDR/STR instructions"); - - uint32_t offset; - - if (code & (0x1 << 25)) // register offset - { - if (code & (0x1 << 4)) - met_abort("Bit 4 must be 0 for LDR or STR instruction with register offset"); - offset = (code >> 7) & 0x1F; - switch ((code >> 5) & 0x3) - { - case 0: // Logical Shift Left - if (offset) - offset = R(Rm) << offset; - else - offset = R(Rm); - break; - case 1: // Logical Shift Right - if (offset) - offset = R(Rm) >> offset; - else - offset = 0; - break; - case 2: // Arithmetic Shift Right - if (offset) - offset = ((int32_t)R(Rm)) >> offset; - else - { - if (R(Rm) >> 31) - offset = 0xFFFFFFFF; - else - offset = 0; - } - break; - case 3: // ROtate Right - if (offset) - offset = ROR(R(Rm), offset); - else - offset = (FLAG_C << 31) | (R(Rm) >> 1); - break; - } - } - else // immediate offset - { - offset = code & 0xFFF; - } - - // bit 24 : 0 = add offset after and write-back, 1 = add offset before - uint32_t add = R(Rn); - if (code & (0x1 << 24)) - { - if (code & (0x1 << 23)) - add += offset; - else - add -= offset; - } - - /* bit 22 : 0 = write word, 1 = write byte - * bit 20 : 0 = store, 1 = load */ - if (code & (0x1 << 22)) - { - if (code & (0x1 << 20)) // LDRB - { - R(Rd) = MEM.Read8(add); - if (Rd == 15) - met_abort("LDRB to R15 !"); - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES32Seq(R(15), 1); - } - else // STRB - { - MEM.Write8(add, R(Rd)); - CYCLES16NSeq(add, 1); - CYCLES32NSeq(R(15), 1); - } - } - else - { - if (code & (0x1 << 20)) // LDR - { - R(Rd) = MEM.Read32(add); - CYCLES32NSeq(add, 1); - ICYCLES(1); - if (Rd == 15) - { - CYCLES32NSeq(R(15), 3); - R(Rd) += 4; - } - else - CYCLES32Seq(R(15), 1); - } - else // STR - { - MEM.Write32(add, R(Rd)); - CYCLES32NSeq(add, 1); - CYCLES32NSeq(R(15), 1); - } - } - - // bit 21 if write before : 0 = nothing, 1 = write-back - if (!(code & (0x1 << 24))) // in post, writeback is always enabled - { - if (code & (0x1 << 23)) - R(Rn) = add + offset; - else - R(Rn) = add - offset; - } - else if (code & (0x1 << 21)) - R(Rn) = add; - } - - // Halfword, Doubleword, and Signed Data Transfer - ARM(STRLDR_HD) - { - if ((code >> 25) & 0x7) - met_abort("Bits 25-27 must be 000 for halfword transfer instructions"); - if (!(code & (0x1 << 7)) || !(code & (0x1 << 4))) - met_abort("Bits 4 and 7 must be 1 for halfword transfer instructions"); - if (Rd == 15) - met_abort("operation on r15, not implemented"); - - uint8_t rd = Rd; - - uint32_t off; - if (code & (0x1 << 22)) // immediate offset - off = ((code >> 4) & 0xF0) | (code & 0xF); - else // register offset - { - if ((code >> 8) & 0xF) - met_abort("Bits 8-11 must be 0 for halfword transfer with register offset instructions"); - NOT_PC(Rm); - off = R(Rm); - } - - uint32_t add = R(Rn); - if (code & (0x1 << 24)) - { - if (code & (0x1 << 23)) - add += off; - else - add -= off; - } - else if (code & (0x1 << 21)) - met_abort("Bit 21 must be 0 for post indexed halfword transfers instructions"); - - switch (((code >> 18) & 0x4) | ((code >> 5) & 0x3)) - { - case 0x0: - met_abort("Reserved for SWP instruction !"); - break; - case 0x1: // STRH - MEM.Write16(add, rd == 15 ? R(15) + 4 : R(rd)); - CYCLES16NSeq(add, 1); - CYCLES32NSeq(R(15), 1); - break; - case 0x2: // LDRD - if (rd % 2) - met_abort("Register number not even for double word transfer"); - if (add % 8) - met_abort("Address not double word aligned"); - if (rd == 15) - met_abort("Rd is 15 for double word transfer !"); - R(rd) = MEM.Read32(add); - R(rd+1) = MEM.Read32(add+4); - CYCLES32NSeq(add, 2); - ICYCLES(1); - CYCLES32Seq(R(15), 1); - break; - case 0x3: // STRD - if (rd % 2) - met_abort("Register number not even for double word transfer"); - if (add % 8) - met_abort("Address not double word aligned"); - if (rd == 15) - met_abort("Rd is 15 for double word transfer !"); - MEM.Write32(add, R(rd)); - MEM.Write32(add + 4, rd == 14 ? R(15) + 4 : R(rd+1)); - CYCLES32NSeq(add, 2); - CYCLES32NSeq(R(15), 1); - break; - case 0x4: - met_abort("Reserved !"); - break; - case 0x5: // LDRH - R(rd) = MEM.Read16(add); - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES32Seq(R(15), 1); - break; - case 0x6: // LDRSB - R(rd) = MEM.Read8(add); - // sign-extend - R(rd) <<= 24; - R(rd) = ((int32_t)R(rd)) >> 24; - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES32Seq(R(15), 1); - break; - case 0x7: // LDRSH - R(rd) = MEM.Read16(add); - // sign-extend - R(rd) <<= 16; - R(rd) = ((int32_t)R(rd)) >> 16; - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES32Seq(R(15), 1); - break; - } - - if (!(code & (0x1 << 24))) // in post, writeback is always enabled - { - if (code & (0x1 << 23)) - R(Rn) = add + off; - else - R(Rn) = add - off; - } - else if (code & (0x1 << 21)) - R(Rn) = add; - } - - // Block Data Transfer (LDM,STM) - ARM(LDMSTM) - { - if (((code >> 25) & 0x7) != 0x4) - met_abort("Bits 25-27 must be 100 for LDM/STM instructions"); - if (code & (0x1 << 22)) - met_abort("not implemented"); - - static const uint8_t NumBits[] = - {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; - - // Works like LDR and STR, look at above comments - uint8_t numregs = - NumBits[(code >> 12) & 0xF] + - NumBits[(code >> 8) & 0xF] + - NumBits[(code >> 4) & 0xF] + - NumBits[ code & 0xF]; - uint16_t regs = code & 0xFFFF; - - uint32_t add, baseadd; - baseadd = add = R(Rn); - if (code & (0x1 << 24)) - if (code & (0x1 << 23)) - add += 4; // increment before - else - add -= numregs * 4; // decrement before - else - if (!(code & (0x1 << 23))) - add -= (numregs-1) * 4; // decrement after - add &= 0xFFFFFFFC; - - if (code & (0x1 << 20)) // LDM - { - CYCLES32NSeq(add, numregs); - ICYCLES(1); - for (register uint8_t n = 0; n < 16; ++n) - if (regs & (0x1 << n)) - { - R(n) = MEM.Read32 (add); - if (n == 15) - R(15) += 4; - add += 4; - } - if (regs & (0x1 << 15)) - CYCLES32NSeq(R(15), 3); - else - CYCLES32Seq(R(15), 1); - } - else // STM - { - CYCLES32NSeq(add, numregs); - CYCLES32NSeq(R(15), 1); - - for (register uint8_t n = 0; n < 16; ++n) - if (regs & (0x1 << n)) - { - if (n == 15) - MEM.Write32 (add, R(15) + 4); - else - MEM.Write32 (add, R(n)); - add += 4; - } - } - - if (code & (0x1 << 21)) - if (code & (0x1 << 23)) - R(Rn) = baseadd + numregs * 4; - else - R(Rn) = baseadd - numregs * 4; - } - - // Single Data Swap (SWP) - ARM(SWP) - { - if (((code >> 23) & 0x1F) != 0x02) - met_abort("Bits 23-27 must be 00010 for SWP instructions"); - if ((code >> 20) & 0x3) - met_abort("Bits 20-21 must be 00 for SWP instructions"); - if (((code >> 4) & 0xFF) != 0x09) - met_abort("Bits 4-11 must be 00001001 for SWP instructions"); - - if (code & (0x1 << 22)) // SWPB - { - R(Rd) = MEM.Read8(R(Rn)); - MEM.Write8(R(Rn), R(Rm)); - } - else // SWP - { - R(Rd) = MEM.Read32(R(Rn)); - MEM.Write32(R(Rn), R(Rm)); - } - CYCLES32NSeq(R(Rn), 1); - CYCLES32NSeq(R(Rn), 1); - ICYCLES(1); - CYCLES32Seq(R(15), 1); - } - - // Software Interrupt (SWI,BKPT) - ARM(SWI) - { - if (((code >> 24) & 0xF) != 0xF) - met_abort("Bits 24-27 must be 1111 for SWI instructions"); - - CPU.SoftwareInterrupt((code >> 16) & 0xFF); - - // FIXME seems wrong ! - CYCLES32NSeq(0, 3); - } - - inline bool Interpreter::a_CheckCondition (uint8_t cond) - { - if (cond == 0xE) - return true; - - switch (cond) - { - case 0x0 : // EQ - if (!FLAG_Z) - return false; - break; - case 0x1 : // NE - if (FLAG_Z) - return false; - break; - case 0x2 : // CS - if (!FLAG_C) - return false; - break; - case 0x3 : // CC - if (FLAG_C) - return false; - break; - case 0x4 : // MI - if (!FLAG_N) - return false; - break; - case 0x5 : // PL - if (FLAG_N) - return false; - break; - case 0x6 : // VS - if (!FLAG_V) - return false; - break; - case 0x7 : // VC - if (FLAG_V) - return false; - break; - case 0x8 : // HI - if (!FLAG_C || FLAG_Z) - return false; - break; - case 0x9 : // LS - if (FLAG_C && !FLAG_Z) - return false; - break; - case 0xA : // GE - if (FLAG_N != FLAG_V) - return false; - break; - case 0xB : // LT - if (FLAG_N == FLAG_V) - return false; - break; - case 0xC : // GT - if (FLAG_Z || FLAG_N != FLAG_V) - return false; - break; - case 0xD : // LE - if (!FLAG_Z && FLAG_N == FLAG_V) - return false; - break; - case 0xE : // AL - break; - case 0xF : // reserved - break; - } - - return true; - } - - NIARM(_Code) - { - if (!a_CheckCondition(code >> 28)) // condition failed - CYCLES32Seq(R(15), 1); - else - switch ((code >> 25) & 0x7) - { - case 0x0: - switch ((code >> 18) & 0x60 | (code >> 16) & 0x10 | - (code >> 4) & 0x0F) - { - case 0x40: - aPSR(); - break; - case 0x00: - case 0x02: - case 0x04: - case 0x06: - case 0x08: - case 0x0A: - case 0x0C: - case 0x0E: - case 0x10: - case 0x12: - case 0x14: - case 0x16: - case 0x18: - case 0x1A: - case 0x1C: - case 0x1E: - case 0x20: - case 0x22: - case 0x24: - case 0x26: - case 0x28: - case 0x2A: - case 0x2C: - case 0x2E: - case 0x30: - case 0x32: - case 0x34: - case 0x36: - case 0x38: - case 0x3A: - case 0x3C: - case 0x3E: - case 0x50: - case 0x52: - case 0x54: - case 0x56: - case 0x58: - case 0x5A: - case 0x5C: - case 0x5E: - case 0x60: - case 0x62: - case 0x64: - case 0x66: - case 0x68: - case 0x6A: - case 0x6C: - case 0x6E: - case 0x70: - case 0x72: - case 0x74: - case 0x76: - case 0x78: - case 0x7A: - case 0x7C: - case 0x7E: - a_DataProcShiftImm(); - break; - case 0x01: - case 0x03: - case 0x05: - case 0x07: - case 0x11: - case 0x13: - case 0x15: - case 0x17: - case 0x21: - case 0x23: - case 0x25: - case 0x27: - case 0x31: - case 0x33: - case 0x35: - case 0x37: - case 0x51: - case 0x53: - case 0x55: - case 0x57: - case 0x61: - case 0x63: - case 0x65: - case 0x67: - case 0x71: - case 0x73: - case 0x75: - case 0x77: - a_DataProcShiftReg(); - break; - case 0x09: - case 0x19: - case 0x29: - case 0x39: - case 0x48: - case 0x4A: - case 0x4C: - case 0x4E: - a_Multiply(); - break; - case 0x0B: - case 0x0D: - case 0x0F: - case 0x1B: - case 0x1D: - case 0x1F: - case 0x2B: - case 0x2D: - case 0x2F: - case 0x3B: - case 0x3D: - case 0x3F: - case 0x4B: - case 0x4D: - case 0x4F: - case 0x5B: - case 0x5D: - case 0x5F: - case 0x6B: - case 0x6D: - case 0x6F: - case 0x7B: - case 0x7D: - case 0x7F: - aSTRLDR_HD(); - break; - case 0x49: - aSWP(); - break; - case 0x41: - case 0x43: - aBXBLX(); - break; - default: - met_abort("unknown"); - break; - } - break; - case 0x1: - // TODO PSR - a_DataProcImm(); - break; - case 0x2: - case 0x3: - aLDRSTR(); - break; - case 0x4: - aLDMSTM(); - break; - case 0x5: - aBBL(); - break; - case 0x7: - if (code & (0x1 << 24)) - aSWI(); - else - met_abort("unknown"); - break; - default: - { std::cerr << IOS_ADD << R(15)-8 << " : " << IOS_ADD << code << " : "; debug_bits(code); met_abort("not implemented"); } - break; - } - } -} - -#undef Rn -#undef Rd -#undef Rs -#undef Rm - -#undef LSOff - -#undef NOT_PC -#undef NOT_PC_ALL -#undef NOT_SAME2 -#undef NOT_SAME3 - -#undef ARM - -#endif diff --git a/libmeteor/source/interpreter_thumb.cpp b/libmeteor/source/interpreter_thumb.cpp deleted file mode 100644 index 0beb374086..0000000000 --- a/libmeteor/source/interpreter_thumb.cpp +++ /dev/null @@ -1,1222 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#ifndef __INTERPRETER_THUMB_H__ -#define __INTERPRETER_THUMB_H__ - -/* - -- From GBATEK - - -THUMB Binary Opcode Format - -Fo|_15|_14|_13|_12|_11|_10|_9_|_8_|_7_|_6_|_5_|_4_|_3_|_2_|_1_|_0_| -_1|_0___0___0_|__Op___|_______Offset______|____Rs_____|____Rd_____|Shifted -_2|_0___0___0___1___1_|_I,_Op_|___Rn/nn___|____Rs_____|____Rd_____|ADD/SUB -_3|_0___0___1_|__Op___|____Rd_____|_____________Offset____________|Immedi. -_4|_0___1___0___0___0___0_|______Op_______|____Rs_____|____Rd_____|AluOp -_5|_0___1___0___0___0___1_|__Op___|Hd_|Hs_|____Rs_____|____Rd_____|HiReg/BX -_6|_0___1___0___0___1_|____Rd_____|_____________Word______________|LDR PC -_7|_0___1___0___1_|__Op___|_0_|___Ro______|____Rb_____|____Rd_____|LDR/STR -_8|_0___1___0___1_|__Op___|_1_|___Ro______|____Rb_____|____Rd_____|""H/SB/SH -_9|_0___1___1_|__Op___|_______Offset______|____Rb_____|____Rd_____|""{B} -10|_1___0___0___0_|Op_|_______Offset______|____Rb_____|____Rd_____|""H -11|_1___0___0___1_|Op_|____Rd_____|_____________Word______________|"" SP -12|_1___0___1___0_|Op_|____Rd_____|_____________Word______________|ADD PC/SP -13|_1___0___1___1___0___0___0___0_|_S_|___________Word____________|ADD SP,nn -14|_1___0___1___1_|Op_|_1___0_|_R_|____________Rlist______________|PUSH/POP -17|_1___0___1___1___1___1___1___0_|___________User_Data___________|BKPT ARM9 -15|_1___1___0___0_|Op_|____Rb_____|____________Rlist______________|STM/LDM -16|_1___1___0___1_|_____Cond______|_________Signed_Offset_________|B{cond} -U_|_1___1___0___1___1___1___1___0_|_____________var_______________|UNDEF ARM9 -17|_1___1___0___1___1___1___1___1_|___________User_Data___________|SWI -18|_1___1___1___0___0_|________________Offset_____________________|B -19|_1___1___1___0___1_|_________________________var___________|_0_|BLXsuf ARM9 -U_|_1___1___1___0___1_|_________________________var___________|_1_|UNDEF ARM9 -19|_1___1___1___1_|_H_|______________Offset_Low/High______________|BL (BLX ARM9) - -*/ - -#include "ameteor/interpreter.hpp" -#include "globals.hpp" -#include "cpu_globals.hpp" -#include "ameteor/memory.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" - -#define Rb ((code >> 8) & 0x7) -#define Ro ((code >> 6) & 0x7) -#define Rs ((code >> 3) & 0x7) -#define Rd ((code ) & 0x7) -#define Imm (code & 0xFF) -#define Off ((code >> 6) & 0x1F) - -//#define HiRs (((code & (0x1 << 6)) >> 3) | Rs) -#define HiRs ((code >> 3) & 0xF) -#define HiRd (((code & (0x1 << 7)) >> 4) | Rd) - -#ifdef METDEBUG -# define NOT_PC(reg) \ - if (reg == 15) \ - met_abort("Register is PC") -#else -# define NOT_PC(reg) {} -#endif - -#define THUMB(name) \ - inline void Interpreter::t##name () -#define NITHUMB(name) \ - void Interpreter::t##name () - -namespace AMeteor -{ - // move shifted register - THUMB(_Shift) - { - if ((code >> 13) & 0x7) - { - met_abort("Bits 13-15 must be 000 for shift instructions"); - } - - uint8_t off = Off; - switch ((code >> 11) & 0x3) - { - case 0x0: // LSL - if (off) - { - SETF(C, R(Rs) & (0x1 << (32-off))); - R(Rd) = R(Rs) << off; - FZ(R(Rd)); - FN(R(Rd)); - } - else - { - R(Rd) = R(Rs); - FZ(R(Rd)); - FN(R(Rd)); - } - break; - case 0x1: // LSR - if (off) - { - SETF(C, R(Rs) & (0x1 << (off-1))); - R(Rd) = R(Rs) >> off; - FZ(R(Rd)); - FN(R(Rd)); - } - else - { - SETF(C, R(Rs) & (0x1 << 31)); - R(Rd) = 0; - FLAG_Z = 1; - FLAG_N = 0; - } - break; - case 0x2: // ASR - if (off) - { - SETF(C, (((int32_t)R(Rs)) >> (off - 1)) & 0x1); - R(Rd) = ((int32_t)R(Rs)) >> off; - FZ(R(Rd)); - FN(R(Rd)); - } - else - { - if (R(Rd) & (0x1 << 31)) - { - R(Rd) = 0xFFFFFFFF; - FLAG_Z = 0; - FLAG_N = 1; - FLAG_C = 1; - } - else - { - R(Rd) = 0; - FLAG_Z = 1; - FLAG_N = 0; - FLAG_C = 0; - } - } - break; - case 0x3: // reserved - met_abort("Bits 11-12 must not be 11 for shift instructions"); - break; - } - - CYCLES16Seq(R(15), 1); - } - - // add/substract - THUMB(ADDSUB) - { - if (((code >> 11) & 0x1F) != 0x3) - { - met_abort("Bits 11-15 should be 00011 for add/substract"); - } - - uint32_t op2; - if ((code >> 10) & 0x1) // imm - op2 = Ro; - else // reg - op2 = R(Ro); - - if ((code >> 9) & 0x1) // SUB - { -#ifdef X86_ASM - asm("subl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setncb %3\n" - "setob %4\n" - :"=r"(R(Rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"0"(R(Rs)), "r"(op2)); -#else - uint32_t op1 = R(Rs), res = R(Rd) = op1 - op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); -#endif - } - else // ADD - { -#ifdef X86_ASM - asm("addl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setcb %3\n" - "setob %4\n" - :"=r"(R(Rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"0"(R(Rs)), "r"(op2)); -#else - uint32_t op1 = R(Rs), res = R(Rd) = op1 + op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = ADDCARRY(op1, op2, res); - FLAG_V = ADDOVERFLOW(op1, op2, res); -#endif - } - - CYCLES16Seq(R(15), 1); - } - - // move/compare/add/substact immediate - THUMB(_Imm) - { - if (((code >> 13) & 0x7) != 0x1) - { - met_abort("Bits 13-15 must be 001 for immediate instructions"); - } - - switch ((code >> 11) & 0x3) - { - case 0x0: // MOV - R(Rb) = Imm; - FLAG_Z = !Imm; - FLAG_N = 0; - break; - case 0x1: // CMP -#ifdef X86_ASM - asm("cmpl %5, %4\n" - "setzb %0\n" - "setsb %1\n" - "setncb %2\n" - "setob %3\n" - :"=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"r"(R(Rb)), "r"(Imm)); -#else - { - uint32_t op1 = R(Rb), op2 = Imm, res = op1 - op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); - } -#endif - break; - case 0x2: // ADD -#ifdef X86_ASM - asm("addl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setcb %3\n" - "setob %4\n" - :"=r"(R(Rb)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"0"(R(Rb)), "r"(Imm)); -#else - { - uint32_t op1 = R(Rb), op2 = Imm, res = R(Rb) = op1 + op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = ADDCARRY(op1, op2, res); - FLAG_V = ADDOVERFLOW(op1, op2, res); - } -#endif - break; - case 0x3: // SUB -#ifdef X86_ASM - asm("subl %6, %5\n" - "setzb %1\n" - "setsb %2\n" - "setncb %3\n" - "setob %4\n" - :"=r"(R(Rb)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"0"(R(Rb)), "r"(Imm)); -#else - { - uint32_t op1 = R(Rb), op2 = Imm, res = R(Rb) = op1 - op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); - } -#endif - break; - } - - CYCLES16Seq(R(15), 1); - } - - // ALU operations - THUMB(_ALU) - { - if (((code >> 10) & 0x3F) != 0x10) - { - met_abort("Bits 10-15 must be 010000 for ALU instructions"); - } - - uint8_t opcode = (code >> 6) & 0xF; - // TODO put a ifndef X86_ASM here around this declaration - uint32_t res = 0; // to avoid a warning - uint8_t shift; - - switch (opcode) - { - case 0x0: // AND -#ifdef X86_ASM - asm("andl %4, %3\n" - "setzb %1\n" - "setsb %2\n" - :"=r"(R(Rd)), "=m"(FLAG_Z), "=m"(FLAG_N) - :"0"(R(Rd)), "r"(R(Rs))); -#else - res = R(Rd) &= R(Rs); - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - break; - case 0x1: // EOR -#ifdef X86_ASM - asm("xorl %4, %3\n" - "setzb %1\n" - "setsb %2\n" - :"=r"(R(Rd)), "=m"(FLAG_Z), "=m"(FLAG_N) - :"0"(R(Rd)), "r"(R(Rs))); -#else - res = R(Rd) ^= R(Rs); - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - break; - case 0x2: // LSL - ICYCLES(1); - shift = R(Rs) & 0xFF; - if (shift) - { - if (shift == 32) - { - SETFB(C, R(Rd) & 0x1); - R(Rd) = 0; - FLAG_Z = FLAG_N = 0; - } - else if (shift < 32) - { - SETFB(C, (R(Rd) >> (32-shift)) & 0x1); - res = R(Rd) <<= shift; - FLAG_Z = !res; - FLAG_N = res >> 31; - } - else - { - R(Rd) = 0; - FLAG_C = FLAG_Z = FLAG_N = 0; - } - } - else - { - res = R(Rd); - FLAG_Z = !res; - FLAG_N = res >> 31; - } - break; - case 0x3: // LSR - ICYCLES(1); - shift = R(Rs) & 0xFF; - if (shift) - { - if (shift == 32) - { - SETFB(C, R(Rd) >> 31); - R(Rd) = 0; - FLAG_Z = FLAG_N = 0; - } - else if (shift < 32) - { - SETFB(C, (R(Rd) >> (shift-1)) & 0x1); - res = R(Rd) >>= shift; - FLAG_Z = !res; - FLAG_N = res >> 31; - } - else - { - R(Rd) = 0; - FLAG_C = FLAG_Z = FLAG_N = 0; - } - } - else - { - res = R(Rd); - FLAG_Z = !res; - FLAG_N = res >> 31; - } - break; - case 0x4: // ASR - ICYCLES(1); - shift = R(Rs) & 0xFF; - if (shift) - { - if (shift >= 32) - { - R(Rd) = ((int32_t)R(Rs)) >> 31; - FLAG_C = FLAG_Z = FLAG_N = R(Rd) & 0x1; - } - else - { - SETFB(C, (((int32_t)R(Rd)) >> (shift-1)) & 0x1); - res = R(Rd) = ((int32_t)R(Rd)) >> shift; - FLAG_Z = !res; - FLAG_N = res >> 31; - } - } - else - { - res = R(Rd); - FLAG_Z = !res; - FLAG_N = res >> 31; - } - break; - case 0x5: // ADC - res = R(Rd) + R(Rs) + FLAG_C; - FLAG_C = ADDCARRY(R(Rd), R(Rs), res); - FLAG_V = ADDOVERFLOW(R(Rd), R(Rs), res); - R(Rd) = res; - break; - case 0x6: // SBC - res = R(Rd) - R(Rs) + FLAG_C - 1; - FLAG_C = SUBCARRY(R(Rd), R(Rs), res); - FLAG_V = SUBOVERFLOW(R(Rd), R(Rs), res); - R(Rd) = res; - break; - case 0x7: // ROR - ICYCLES(1); - shift = R(Rs) & 0xFF; - if (shift) - { - shift %= 32; - res = R(Rd); - SETFB(C, (res >> (shift - 1)) & 0x1); - res = R(Rd) = ROR(res, shift); - FLAG_Z = !res; - FLAG_N = res >> 31; - } - else - { - res = R(Rd); - FLAG_Z = !res; - FLAG_N = res >> 31; - } - break; - case 0x8: // TST -#ifdef X86_ASM - asm("testl %3, %2\n" - "setzb %0\n" - "setsb %1\n" - :"=m"(FLAG_Z), "=m"(FLAG_N) - :"r"(R(Rd)), "r"(R(Rs))); -#else - res = R(Rd) & R(Rs); - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - break; - case 0x9: // NEG -#ifdef X86_ASM - asm("negl %5\n" - "setzb %1\n" - "setsb %2\n" - "setncb %3\n" - "setob %4\n" - :"=r"(R(Rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"0"(R(Rs))); -#else - { - uint32_t op2; - op2 = R(Rs); - res = R(Rd) = -op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - // we overflow only if op2 == INT_MIN - FLAG_V = SUBOVERFLOW(0, op2, res); - // we have a carry only if op2 == 0 - FLAG_C = SUBCARRY(0, op2, res); - } -#endif - break; - case 0xA: // CMP -#ifdef X86_ASM - asm("cmpl %5, %4\n" - "setzb %0\n" - "setsb %1\n" - "setncb %2\n" - "setob %3\n" - :"=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"r"(R(Rd)), "r"(R(Rs))); -#else - { - uint32_t op1, op2; - op1 = R(Rd); - op2 = R(Rs); - res = op1 - op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); - } -#endif - break; - case 0xB: // CMN -#ifdef X86_ASM - asm("addl %5, %4\n" - "setzb %0\n" - "setsb %1\n" - "setcb %2\n" - "setob %3\n" - :"=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"r"(R(Rd)), "r"(R(Rs)) - :"4"); -#else - { - uint32_t op1, op2; - op1 = R(Rd); - op2 = R(Rs); - res = op1 + op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = ADDCARRY(op1, op2, res); - FLAG_V = ADDOVERFLOW(op1, op2, res); - } -#endif - break; - case 0xC: // ORR -#ifdef X86_ASM - asm("orl %4, %3\n" - "setzb %1\n" - "setsb %2\n" - :"=r"(R(Rd)), "=m"(FLAG_Z), "=m"(FLAG_N) - :"0"(R(Rd)), "r"(R(Rs))); -#else - res = R(Rd) |= R(Rs); - FLAG_Z = !res; - FLAG_N = res >> 31; -#endif - break; - case 0xD: // MUL - MULICYCLES(Rs); - res = R(Rd) *= R(Rs); - FLAG_Z = !res; - FLAG_N = res >> 31; - break; - case 0xE: // BIC - res = R(Rd) &= ~R(Rs); - FLAG_Z = !res; - FLAG_N = res >> 31; - break; - case 0xF: // MVN - res = R(Rd) = ~R(Rs); - FLAG_Z = !res; - FLAG_N = res >> 31; - break; - } - - CYCLES16Seq(R(15), 1); - } - - // Hi register operations/branch exchange - THUMB(_HiRegOp) - { - if (((code >> 10) & 0x3F) != 0x11) - { - met_abort("Bits 10-15 must be 010001 for HiReg instructions"); - } - - uint8_t rd = HiRd, rs = HiRs; - switch ((code >> 8) & 0x3) - { - case 0x0: // ADD - R(rd) += R(rs); - if (rd == 15) - { - R(15) &= 0xFFFFFFFE; - CYCLES16NSeq(R(15), 3); - R(15) += 2; - } - else - CYCLES16Seq(R(15), 1); - break; - case 0x1: // CMP -#ifdef X86_ASM - asm("cmpl %5, %4\n" - "setzb %0\n" - "setsb %1\n" - "setncb %2\n" - "setob %3\n" - :"=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V) - :"r"(R(rd)), "r"(R(rs))); -#else - { - uint32_t op1 = R(rd), op2 = R(rs), res = op1 - op2; - FLAG_Z = !res; - FLAG_N = res >> 31; - FLAG_C = SUBCARRY(op1, op2, res); - FLAG_V = SUBOVERFLOW(op1, op2, res); - } -#endif - CYCLES16Seq(R(15), 1); - break; - case 0x2: - if (rd != 8 || rs != 8) // MOV - { - R(rd) = R(rs); - if (rd == 15) - { - R(15) &= 0xFFFFFFFE; - CYCLES16NSeq(R(15), 3); - R(15) += 2; - } - else - CYCLES16Seq(R(15), 1); - } - else // NOP - CYCLES16Seq(R(15), 1); - break; - case 0x3: - if (Rd) - met_abort("Rd must be 0 for BX/BLX instructions"); - if (code & (0x1 << 7)) // BLX - { - NOT_PC(rs); - met_abort("BLX not implemented"); - } - else // BX - { - if (R(rs) & 0x1) - { - R(15) = (R(rs) & 0xFFFFFFFE) + 2; - CYCLES16NSeq(R(15), 3); - } - else - { - // switch to arm - FLAG_T = 0; - R(15) = (R(rs) & 0xFFFFFFFC) + 4; - CYCLES32NSeq(R(15), 3); - } - } - break; - } - } - - // load PC-relative - THUMB(LDRimm) - { - if (((code >> 11) & 0x1F) != 0x9) - { - met_abort("Bits 11-15 must be 01001 for LDR with imm instructions"); - } - - uint32_t add = (R(15) & 0xFFFFFFFC) + (Imm << 2); - R(Rb) = MEM.Read32(add); - - CYCLES32NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - } - - // load/store with register offset - // and load/store sign-extended byte/halfword - THUMB(STRLDRreg) - { - if (((code >> 12) & 0xF) != 0x5) - { - met_abort("Bits 12-15 must be 0101 for LDR/STR with reg instructions"); - } - - uint32_t add = R(Ro) + R(Rs); - switch ((code >> 9) & 0x7) - { - // load/store with register offset - case 0x0: // STR - MEM.Write32(add, R(Rd)); - CYCLES32NSeq(add, 1); - CYCLES16NSeq(R(15), 1); - break; - case 0x2: // STRB - MEM.Write8(add, R(Rd)); - CYCLES16NSeq(add, 1); - CYCLES16NSeq(R(15), 1); - break; - case 0x4: // LDR - R(Rd) = MEM.Read32(add); - CYCLES32NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - break; - case 0x6: // LDRB - R(Rd) = MEM.Read8(add); - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - break; - - // load/store sign-extended byte/halfword - case 0x1: // STRH - MEM.Write16(add, R(Rd)); - CYCLES16NSeq(add, 1); - CYCLES16NSeq(R(15), 1); - break; - case 0x3: // LDSB - R(Rd) = (int8_t)MEM.Read8(add); - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - break; - case 0x5: // LDRH - R(Rd) = MEM.Read16(add); - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - break; - case 0x7: // LDSH - R(Rd) = (int16_t)MEM.Read16(add); - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - break; - } - } - - // load/store with immediate offset - THUMB(STRLDRoff) - { - if (((code >> 13) & 0x7) != 0x3) - { - met_abort("Bits 13-15 must be 011 for LDR/STR with off instructions"); - } - - uint32_t add; - switch ((code >> 11) & 0x3) - { - case 0x0: // STR - add = R(Rs) + (Off << 2); - MEM.Write32(add, R(Rd)); - CYCLES32NSeq(add, 1); - CYCLES16NSeq(R(15), 1); - break; - case 0x1: // LDR - add = R(Rs) + (Off << 2); - R(Rd) = MEM.Read32(add); - CYCLES32NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - break; - case 0x2: // STRB - add = R(Rs) + Off; - MEM.Write8(add, R(Rd)); - CYCLES16NSeq(add, 1); - CYCLES16NSeq(R(15), 1); - break; - case 0x3: // LDRB - add = R(Rs) + Off; - R(Rd) = MEM.Read8(add); - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - break; - } - } - - // load/store halfword - THUMB(LDRHSTRHoff) - { - if (((code >> 12) & 0xF) != 0x8) - { - met_abort("Bits 12-15 must be 1000 for LDRH/STRH with off instructions"); - } - - uint32_t add = R(Rs) + (Off * 2); - if (code & (0x1 << 11)) // LDRH - { - R(Rd) = MEM.Read16(add); - CYCLES16NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - } - else // STRH - { - MEM.Write16(add, R(Rd)); - CYCLES16NSeq(add, 1); - CYCLES16NSeq(R(15), 1); - } - } - - // load/store SP-relative - THUMB(STRLDRsp) - { - if (((code >> 12) & 0xF) != 0x9) - { - met_abort("Bits 12-15 must be 1001 for LDR/STR SP-relative instructions"); - } - - uint32_t add = R(13) + (Imm << 2); - if (code & (0x1 << 11)) // LDR - { - R(Rb) = MEM.Read32(add); - CYCLES32NSeq(add, 1); - ICYCLES(1); - CYCLES16Seq(R(15), 1); - } - else // STR - { - MEM.Write32(add, R(Rb)); - CYCLES32NSeq(add, 1); - CYCLES16NSeq(R(15), 1); - } - } - - // get relative address - THUMB(ADDpcsp) - { - if (((code >> 12) & 0xF) != 0xA) - { - met_abort("Bits 12-15 must be 1010 for ADD relative instructions"); - } - - if (code & (0x1 << 11)) // with SP - { - R(Rb) = R(13) + (Imm << 2); - } - else // with PC - { - R(Rb) = (R(15) & 0xFFFFFFFC) + (Imm << 2); - } - - CYCLES16Seq(R(15), 1); - } - - // add offset to stack pointer - THUMB(ADDsp) - { - if (((code >> 8) & 0xFF) != 0xB0) - { - met_abort("Bits 8-15 must be 10110000 for ADD to SP instructions"); - } - - if (code & (0x1 << 7)) // substract - { - R(13) -= ((code & 0x7F) << 2); - } - else // add - { - R(13) += ((code & 0x7F) << 2); - } - - CYCLES16Seq(R(15), 1); - } - - // push/pop registers - THUMB(PUSHPOP) - { - if (((code >> 12) & 0xF) != 0xB) - { - met_abort("Bits 12-15 must be 1011 for PUSH/POP instructions"); - } - if (((code >> 9) & 0x3) != 0x2) - { - met_abort("Bits 9-10 must be 10 for PUSH/POP instructions"); - } - - static const uint8_t NumBits[] = - {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; - - uint8_t numregs = - NumBits[(code >> 4) & 0xF] + - NumBits[ code & 0xF]; - if (code & (0x1 << 8)) - ++numregs; - - uint32_t add, newsp; - if (code & (0x1 << 11)) // POP - { - newsp = R(13) + 4 * numregs; - add = R(13) & 0xFFFFFFFC; - - CYCLES32NSeq(add, numregs); - ICYCLES(1); - - for (register uint8_t n = 0; n < 8; ++n) - if (code & (0x1 << n)) - { - R(n) = MEM.Read32 (add); - add += 4; - } - if (code & (0x1 << 8)) // POP PC - { - R(15) = (MEM.Read32(add) + 2) & 0xFFFFFFFE; - CYCLES16NSeq(R(15), 3); - } - else - CYCLES16Seq(R(15), 1); - } - else // PUSH - { - newsp = R(13) - 4 * numregs; - add = newsp & 0xFFFFFFFC; - - CYCLES32NSeq(add, numregs); - CYCLES16NSeq(R(15), 1); - - for (register uint8_t n = 0; n < 8; ++n) - if (code & (0x1 << n)) - { - MEM.Write32 (add, R(n)); - add += 4; - } - if (code & (0x1 << 8)) // PUSH LR - { - MEM.Write32 (add, R(14)); - } - } - - R(13) = newsp; - } - - // multiple load/store - THUMB(STMLDM) - { - if (((code >> 12) & 0xF) != 0xC) - { - met_abort("Bits 12-15 must be 1100 for STM/LDM instructions"); - } - - static const uint8_t NumBits[] = - {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; - - uint8_t numregs = - NumBits[(code >> 4) & 0xF] + - NumBits[ code & 0xF]; - - uint32_t add = R(Rb) & 0xFFFFFFFC; - - if (code & (0x1 << 11)) // LDMIA - { - CYCLES32NSeq(add, numregs); - ICYCLES(1); - - for (register uint8_t n = 0; n < 8; ++n) - if (code & (0x1 << n)) - { - R(n) = MEM.Read32 (add); - add += 4; - } - - CYCLES16Seq(R(15), 1); - } - else // STMIA - { - CYCLES32NSeq(add, numregs); - CYCLES16NSeq(R(15), 1); - - for (register uint8_t n = 0; n < 8; ++n) - if (code & (0x1 << n)) - { - MEM.Write32 (add, R(n)); - add += 4; - } - } - - if (!(code & (0x1 << Rb))) - R(Rb) = R(Rb) + 4 * numregs; - } - - // conditional branch - THUMB(_CondBranch) - { - if (((code >> 12) & 0xF) != 0xD) - { - met_abort("Bits 12-15 must be 1101 for branch on condition instructions"); - } - - bool branch = false; - switch ((code >> 8) & 0xF) - { - case 0x0: // BEQ - if (FLAG_Z) - branch = true; - break; - case 0x1: // BNE - if (!FLAG_Z) - branch = true; - break; - case 0x2: // BCS - if (FLAG_C) - branch = true; - break; - case 0x3: // BCC - if (!FLAG_C) - branch = true; - break; - case 0x4: // BMI - if (FLAG_N) - branch = true; - break; - case 0x5: // BPL - if (!FLAG_N) - branch = true; - break; - case 0x6: // BVS - if (FLAG_V) - branch = true; - break; - case 0x7: // BVC - if (!FLAG_V) - branch = true; - break; - case 0x8: // BHI - if (FLAG_C && !FLAG_Z) - branch = true; - break; - case 0x9: // BLS - if (!FLAG_C || FLAG_Z) - branch = true; - break; - case 0xA: // BGE - if (FLAG_N == FLAG_V) - branch = true; - break; - case 0xB: // BLT - if (FLAG_N != FLAG_V) - branch = true; - break; - case 0xC: // BGT - if (!FLAG_Z && FLAG_N == FLAG_V) - branch = true; - break; - case 0xD: // BLE - if (FLAG_Z || FLAG_N != FLAG_V) - branch = true; - break; - case 0xE: // undefined - met_abort("Undefined branch on condition"); - break; - case 0xF: // reserved for SWI instruction - met_abort("Bits 8-11 must not be 1111 for branch instruction"); - break; - } - - if (branch) - { - R(15) += (((int32_t)(int8_t)Imm) << 1) + 2; - - CYCLES16NSeq(R(15), 3); - } - else - CYCLES16Seq(R(15), 1); - } - - // software interrupt and breakpoint - THUMB(SWI) - { - CPU.SoftwareInterrupt(code & 0xFF); - - // FIXME seems wrong ! - CYCLES32NSeq(0, 3); - } - - // unconditional branch - THUMB(B) - { - if (((code >> 11) & 0x1F) != 0x1C) - { - met_abort("Bits 11-15 must be 11100 for branch instructions"); - } - - int32_t off = (code & 0x7FF) << 1; - if (off & 0x800) - off |= 0xFFFFF000; // extends sign bit - R(15) += off + 2; - - CYCLES16NSeq(R(15), 3); - } - - // long branch with link - THUMB(_BL1) - { - if (((code >> 11) & 0x1F) != 0x1E) - { - met_abort("Bits 11-15 must be 11110 for long branch instructions"); - } - - if (code & (0x1 << 10)) // negative offset - R(14) = R(15) + (((int32_t)((code & 0x7FF) << 12)) | 0xFF800000); - else - R(14) = R(15) + ((code & 0x7FF) << 12); - - CYCLES16Seq(R(15), 1); - } - - THUMB(_BL2) - { - // XXX we dont do check here to be sure this instruction is called after - // BL1 - uint32_t add = R(14) + ((code & 0x7FF) << 1); - - if (code & (0x1 << 11)) // BL - { - R(14) = (R(15)-2) | 0x1; - R(15) = (add & 0xFFFFFFFE) + 2; - } - else // BLX - { - met_abort("BLX not implemented"); - if (code & 0x1) - met_abort("BLX with odd address"); - FLAG_T = 0; - } - - CYCLES16NSeq(R(15), 3); - } - - NITHUMB(_Code) - { - switch (code >> 13) - { - case 0: // 000 - if ((code & 0x1800) == 0x1800) // 00011 - tADDSUB(); - else // 000 - t_Shift(); - break; - case 1: // 001 - t_Imm(); - break; - case 2: // 010 - switch ((code >> 10) & 0x7) - { - case 0: // 010000 - t_ALU(); - break; - case 1: // 010001 - t_HiRegOp(); - break; - case 2: - case 3: // 01001x - tLDRimm(); - break; - default: - tSTRLDRreg(); - break; - } - break; - case 3: // 011 - tSTRLDRoff(); - break; - case 4: // 100 - if (code & (0x1 << 12)) // 1001 - tSTRLDRsp(); - else // 100 - tLDRHSTRHoff(); - break; - case 5: // 101 - if (code & (0x1 << 12)) // 1011 - { - switch (code & 0x0600) - { - case 0x0000: // 1011x00 - tADDsp(); - break; - case 0x0400: // 1011x10 - tPUSHPOP(); - break; - default: - met_abort("not implemented or unknown"); - break; - } - } - else // 101 - tADDpcsp(); - break; - case 6: // 110 - if (code & (0x1 << 12)) // 1101 - { - if ((code & 0x0F00) == 0x0F00) // 11011111 - tSWI(); - else // 1101xxxx - t_CondBranch(); - } - else // 1100 - tSTMLDM(); - break; - case 7: // 111 - switch ((code >> 11) & 0x3) - { - case 0: // 11100 - tB(); - break; - case 2: // 11110 - t_BL1(); - break; - case 3: // 11111 - t_BL2(); - break; - default: - met_abort("not implemented or unknown"); - break; - } - break; - } - } -} - -#undef Rb -#undef Ro -#undef Rs -#undef Rd -#undef Imm - -#undef THUMB - -#endif diff --git a/libmeteor/source/io.cpp b/libmeteor/source/io.cpp deleted file mode 100644 index d76f0e8918..0000000000 --- a/libmeteor/source/io.cpp +++ /dev/null @@ -1,508 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/io.hpp" -#include "ameteor/dma.hpp" -#include "globals.hpp" -#include "ameteor.hpp" -#include - -#include "debug.hpp" - -#define W8(add, val) \ - m_iomem[(add) & 0xFFF] = (val) -#define W16(add, val) \ - *(uint16_t*)(m_iomem + ((add) & 0xFFF)) = (val) -#define W32(add, val) \ - *(uint32_t*)(m_iomem + ((add) & 0xFFF)) = (val) - -namespace AMeteor -{ - Io::Io () - { - m_iomem = new uint8_t[IO_SIZE]; - Reset (); - } - - Io::~Io () - { - delete [] m_iomem; - } - - void Io::Reset () - { - std::memset(m_iomem, 0, IO_SIZE); - - // TODO use clears intead - - // TODO DISPCNT should be 0x80 by default - // TODO do it also for clears - // TODO lcd should draw white lines when hblank forced - // TODO when passing disabling hblank forced, lcd should start drawing from - // first line - W16(SOUNDBIAS, 0x0200); // default value - W16(KEYINPUT, 0x03FF); // all keys released - W8(HALTCNT, 0xFF); // normal mode (internal) - W16(DISPSTAT, 0x0004); // vcount match (since default vcount is 0) - W16(BG2PA, 0x0100); - W16(BG2PD, 0x0100); - W16(BG3PA, 0x0100); - W16(BG3PD, 0x0100); - W16(RCNT, 0x8000); // we start in general purpose mode - } - - void Io::ClearSio () - { - // TODO - W16(RCNT, 0x8000); - } - - void Io::ClearSound () - { - // TODO - } - - void Io::ClearOthers () - { - // FIXME !! shouldn't we call Write*() ? - // lcd - for (uint8_t i = 0x0; i < 0x56; i += 2) - Write16(i, 0x0000); - // dma - for (uint8_t i = 0xB0; i < 0xE0; i += 4) - Write32(i, 0x0000); - // FIXME : should timers be set to 0 too ? (vba does not) - W8(HALTCNT, 0xFF); // normal mode (internal) - W16(IE, 0x0000); - W16(IF, 0x0000); - W16(IME, 0x0000); - Write16(WAITCNT, 0x0000); - W16(BG2PA, 0x0100); - W16(BG2PD, 0x0100); - W16(BG3PA, 0x0100); - W16(BG3PD, 0x0100); - } - - // TODO implement unreadable or write-only io - uint8_t Io::Read8 (uint32_t add) - { - if ((add & 0xFFE) == KEYINPUT) - keyupdate_bizhawk(); - //debug ("IO Read8 at " << IOS_ADD << add << " of " << IOS_ADD << (int)*(uint8_t*)(m_iomem + (add & 0xFFF))); - if ((add & 0xFF0) == 0x100) - switch (add & 0xF) - { - case 0x0: - case 0x4: - case 0x8: - case 0xC: - met_abort("Misaligned reading of timers"); - } - return m_iomem[add & 0xFFF]; - } - - uint16_t Io::Read16 (uint32_t add) - { - if ((add & 0xFFE) == KEYINPUT) - keyupdate_bizhawk(); - //debug ("IO Read16 at " << IOS_ADD << add << " of " << IOS_ADD << *(uint16_t*)(m_iomem + (add & 0xFFF))); - // special case, reading timers - if ((add & 0xFF0) == 0x100) - switch (add & 0xF) - { - case 0x0: return TIMER0.GetCount(); - case 0x4: return TIMER1.GetCount(); - case 0x8: return TIMER2.GetCount(); - case 0xC: return TIMER3.GetCount(); - } - return *(uint16_t*)(m_iomem + (add & 0xFFF)); - } - - uint32_t Io::Read32 (uint32_t add) - { - if ((add & 0xFFC) == KEYINPUT) - keyupdate_bizhawk(); - //debug ("IO Read32 at " << IOS_ADD << add << " of " << IOS_ADD << *(uint32_t*)(m_iomem + (add & 0xFFF))); - // special case, reading timers - if ((add & 0xFF0) == 0x100) - switch (add & 0xF) - { - case 0x0: return TIMER0.GetCount(); - case 0x4: return TIMER1.GetCount(); - case 0x8: return TIMER2.GetCount(); - case 0xC: return TIMER3.GetCount(); - } - return *(uint32_t*)(m_iomem + (add & 0xFFF)); - } - - void Io::Write8 (uint32_t add, uint8_t val) - { - //debug ("IO Write8 at " << IOS_ADD << add << " of " << IOS_ADD << (int)val); - switch (add & 0xFFF) - { - case NR10+1: - case NR52+1: - case NR52+2: - case NR52+3: - break; - case NR10: - case NR11: - case NR13: - case NR21: - case NR23: - case NR41: - case NR43: - case NR50: - case NR51: - case SOUNDCNT_H: - W8(add, val); - break; - case NR12: - W8(add, val); - if (!(val & (0xF << 4))) - SOUND.ResetSound1Envelope(); - break; - case NR14: - W8(add, val & 0xC7); - if (val & (0x1 << 7)) - SOUND.ResetSound1(); - break; - case NR22: - W8(add, val); - if (!(val & (0xF << 4))) - SOUND.ResetSound2Envelope(); - break; - case NR24: - W8(add, val & 0xC7); - if (val & (0x1 << 7)) - SOUND.ResetSound2(); - break; - case NR42: - W8(add, val); - if (!(val & (0xF << 4))) - SOUND.ResetSound4Envelope(); - break; - case NR44: - W8(add, val & 0xC7); - if (val & (0x1 << 7)) - SOUND.ResetSound4(); - break; - case SOUNDCNT_H+1: - W8(add, val); - SOUND.UpdateCntH1(val); - break; - case NR52: - // this will also reset the sound on flags - W8(add, val & 0x80); - break; - case POSTFLG: - // FIXME is this right, i have no idea about why i should do that - if (val) - val &= 0xFE; - W8(add, val); - break; - case HALTCNT: - W8(add, val); - break; - default: - //W8(add, val); - // TODO make a function which will apply masks to IO memory and trigger - // the update functions, this function will be called by write8 and - // write16 -#if 1 - add &= 0xFFF; - if (add % 2) - Write16(add & ~0x1, (val << 8) | m_iomem[add & ~0x1]); - else - Write16(add, (m_iomem[add | 0x1] << 8) | val); -#endif - break; - } - } - - void Io::Write16 (uint32_t add, uint16_t val) - { - //debug ("IO Write16 at " << IOS_ADD << add << " of " << IOS_ADD << val); - //*(uint16_t*)(m_iomem + (add & 0xFFF)) = val; - - switch (add & 0xFFF) - { - case KEYINPUT: - case VCOUNT: - break; - case DMA0CNT_L: - case DMA1CNT_L: - case DMA2CNT_L: - case DMA3CNT_L: - //W16(add, val); - DMA.SetReload(((add & 0xFFF) - DMA0CNT_L) / DMA_CHANSIZE, val); - break; - case KEYCNT: - W16(add, val & 0xC3FF); - break; - case IME: - W16(add, val & 0x0001); - CPU.CheckInterrupt(); - break; - case IE: - W16(add, val & 0x3FFF); - CPU.CheckInterrupt(); - break; - case IF: - *((uint16_t*)(m_iomem+IF)) ^= (val & (*((uint16_t*)(m_iomem+IF)))); - CPU.CheckInterrupt(); - break; - case BG0CNT: - W16(add, val & 0xFFCF); - LCD.UpdateBg0Cnt(val & 0xFFCF); - break; - case BG1CNT: - W16(add, val & 0xFFCF); - LCD.UpdateBg1Cnt(val & 0xFFCF); - break; - case BG2CNT: - W16(add, val & 0xFFCF); - LCD.UpdateBg2Cnt(val & 0xFFCF); - break; - case BG3CNT: - W16(add, val & 0xFFCF); - LCD.UpdateBg3Cnt(val & 0xFFCF); - break; - case DISPSTAT: - // the first 3 bits are read only and they are used by the lcd - // NOTE : we are in LITTLE ENDIAN - // FIXME : if vcount setting has changed to current vcount, we should - // update the vcounter flag and eventually trigger an interrupt - W16(add, (val & 0xFFF8) | (m_iomem[add & 0xFFF] & 0x07)); - break; - // The BG*OFS are write-only, we don't need to W16() - // You do if you're ever going to load them from a savestate... - case BG0HOFS: - W16(add, val & 0x1FF); - LCD.UpdateBg0XOff(val & 0x1FF); - break; - case BG0VOFS: - W16(add, val & 0x1FF); - LCD.UpdateBg0YOff(val & 0x1FF); - break; - case BG1HOFS: - W16(add, val & 0x1FF); - LCD.UpdateBg1XOff(val & 0x1FF); - break; - case BG1VOFS: - W16(add, val & 0x1FF); - LCD.UpdateBg1YOff(val & 0x1FF); - break; - case BG2HOFS: - W16(add, val & 0x1FF); - LCD.UpdateBg2XOff(val & 0x1FF); - break; - case BG2VOFS: - W16(add, val & 0x1FF); - LCD.UpdateBg2YOff(val & 0x1FF); - break; - case BG3HOFS: - W16(add, val & 0x1FF); - LCD.UpdateBg3XOff(val & 0x1FF); - break; - case BG3VOFS: - W16(add, val & 0x1FF); - LCD.UpdateBg3YOff(val & 0x1FF); - break; - case BG2X_H: - val &= 0x0FFF; - case BG2X_L: - W16(add, val); - LCD.UpdateBg2RefX(IO.DRead32(Io::BG2X_L)); - break; - case BG2Y_H: - val &= 0x0FFF; - case BG2Y_L: - W16(add, val); - LCD.UpdateBg2RefY(IO.DRead32(Io::BG2Y_L)); - break; - case BG3X_H: - val &= 0x0FFF; - case BG3X_L: - W16(add, val); - LCD.UpdateBg3RefX(IO.DRead32(Io::BG3X_L)); - break; - case BG3Y_H: - val &= 0x0FFF; - case BG3Y_L: - W16(add, val); - LCD.UpdateBg3RefY(IO.DRead32(Io::BG3Y_L)); - break; - case WIN0H: - case WIN1H: - case WIN0V: - case WIN1V: - case WININ: - case WINOUT: - W16(add, val); - break; - case BLDCNT: - W16(add, val); - break; - case MOSAIC: - W16(add, val); - break; - case DISPCNT: - W16(add, val); - LCD.UpdateDispCnt(val); - break; - case DMA0CNT_H: - case DMA1CNT_H: - case DMA2CNT_H: - case DMA3CNT_H: - W16(add, val & 0xFFE0); - DMA.UpdateCnt(((add & 0xFFF) - DMA0CNT_H) / DMA_CHANSIZE); - break; - case WAITCNT: - W16(add, val & 0xDFFF); - MEM.UpdateWaitStates (val & 0xDFFF); - break; - case SOUND1CNT_L: - case SOUND1CNT_H: - case SOUND1CNT_X: - case SOUND2CNT_L: - case SOUND2CNT_H: - case SOUND4CNT_L: - case SOUND4CNT_H: - case SOUNDCNT_L: - case SOUNDCNT_H: - case SOUNDCNT_X: - case POSTFLG: - Write8(add, val & 0xFF); - Write8(add + 1, val >> 8); - break; - case TM0CNT_L: - TIMER0.SetReload(val); - break; - case TM1CNT_L: - TIMER1.SetReload(val); - break; - case TM2CNT_L: - TIMER2.SetReload(val); - break; - case TM3CNT_L: - TIMER3.SetReload(val); - break; - case TM0CNT_H: - W16(add, val & 0x00C7); - TIMER0.Reload(); - break; - case TM1CNT_H: - W16(add, val & 0x00C7); - TIMER1.Reload(); - break; - case TM2CNT_H: - W16(add, val & 0x00C7); - TIMER2.Reload(); - break; - case TM3CNT_H: - W16(add, val & 0x00C7); - TIMER3.Reload(); - break; - default: - //met_abort("Unknown IO at " << IOS_ADD << add); - W16(add, val); - break; - } - } - - void Io::Write32 (uint32_t add, uint32_t val) - { - //debug ("IO Write32 at " << IOS_ADD << add << " of " << IOS_ADD << val); - switch (add & 0xFF) - { - case DMA1DAD: - case DMA0SAD: - case DMA1SAD: - case DMA2SAD: - case DMA3SAD: - case DMA0DAD: - case DMA2DAD: - case DMA3DAD: - W32(add, val); - break; - case BG0HOFS: - case BG1HOFS: - case BG2HOFS: - case BG3HOFS: - Write16(add, val & 0xFFFF); - Write16(add+2, val >> 16); - break; - case BG2X_L: - W32(add, val & 0x0FFFFFFF); - LCD.UpdateBg2RefX(IO.DRead32(Io::BG2X_L)); - break; - case BG2Y_L: - W32(add, val & 0x0FFFFFFF); - LCD.UpdateBg2RefY(IO.DRead32(Io::BG2Y_L)); - break; - case BG3X_L: - W32(add, val & 0x0FFFFFFF); - LCD.UpdateBg3RefX(IO.DRead32(Io::BG3X_L)); - break; - case BG3Y_L: - W32(add, val & 0x0FFFFFFF); - LCD.UpdateBg3RefY(IO.DRead32(Io::BG3Y_L)); - break; - case BG2PA: - case BG2PC: - case BG3PA: - case BG3PC: - case WIN0H: - case WIN0V: - case WININ: - Write16(add, val & 0xFFFF); - Write16(add+2, val >> 16); - break; - case DMA0CNT_L: - case DMA1CNT_L: - case DMA2CNT_L: - case DMA3CNT_L: - Write16(add, val & 0xFFFF); - Write16(add+2, val >> 16); - break; - case FIFO_A: - case FIFO_B: - // TODO - break; - default: - //met_abort("Unknown IO at " << IOS_ADD << add); - //*(uint32_t*)(m_iomem + (add & 0xFFF)) = val; - Write16(add, val & 0xFFFF); - Write16(add+2, val >> 16); - break; - } - } - - bool Io::SaveState (std::ostream& stream) - { - SS_WRITE_DATA(m_iomem, IO_SIZE); - - return true; - } - - bool Io::LoadState (std::istream& stream) - { - SS_READ_DATA(m_iomem, IO_SIZE); - - return true; - } -} diff --git a/libmeteor/source/keypad.cpp b/libmeteor/source/keypad.cpp deleted file mode 100644 index 6e53a4f155..0000000000 --- a/libmeteor/source/keypad.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/keypad.hpp" -#include "globals.hpp" -#include "ameteor.hpp" - -namespace AMeteor -{ - Keypad::Keypad () : - m_keyinput(IO.GetRef16(Io::KEYINPUT)), - m_keycnt(IO.GetRef16(Io::KEYCNT)) - { - } - - void Keypad::KeyPressed(int code) - { - if (m_keys.count(code)) - m_keyinput &= ~m_keys[code]; - } - - void Keypad::KeyReleased(int code) - { - if (m_keys.count(code)) - m_keyinput |= m_keys[code]; - } - - void Keypad::JoyButtonPressed (uint16_t joyid, uint16_t button) - { - uint32_t id = ((int)joyid) << 16 | button; - if (m_joys.count(id)) - m_keyinput &= ~m_joys[id]; - } - - void Keypad::JoyButtonReleased (uint16_t joyid, uint16_t button) - { - uint32_t id = ((int)joyid) << 16 | button; - if (m_joys.count(id)) - m_keyinput |= m_joys[id]; - } - - void Keypad::JoyMoved (uint16_t joyid, uint16_t axis, float pos) - { - uint32_t id = (((int)joyid) << 16) | ((pos < 0) << 15) | (axis & 0x7FFF); - // if pos is 0, we disable the positive and negative targets - if (pos == 0) - { - if (m_axis.count(id)) - m_keyinput |= m_axis[id]; - if (m_axis.count(id | (1 << 15))) - m_keyinput |= m_axis[id | (1 << 15)]; - } - else - { - // we enable the corresponding button - if (m_axis.count(id)) - m_keyinput &= ~((uint16_t)m_axis[id]); - // we disable the opposite button (we may have skipped 0) - if (m_axis.count(id ^ 0x8000)) - m_keyinput |= m_axis[id ^ 0x8000]; - } - } - - void Keypad::VBlank () - { - // if keypad IRQ are enabled - if (m_keycnt & (0x1 << 14)) - // if irq condition is and - if (m_keycnt & (0x1 << 15)) - { - // if condition is satisfied - if ((~m_keyinput & m_keycnt & 0x3FF) == (m_keycnt & 0x3FF)) - CPU.SendInterrupt(0x1000); - } - // if irq condition is or - else - { - // if condition is satisfied - if (~m_keyinput & m_keycnt & 0x3FF) - CPU.SendInterrupt(0x1000); - } - } -} diff --git a/libmeteor/source/lcd.cpp b/libmeteor/source/lcd.cpp deleted file mode 100644 index 74c5b4c7ba..0000000000 --- a/libmeteor/source/lcd.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/lcd.hpp" -#include "ameteor/io.hpp" -#include "globals.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" - -namespace AMeteor -{ - Lcd::Lcd () : - m_screen(MEM, IO) - { - Reset(); - } - - void Lcd::Reset () - { - CLOCK.AddLcd(960); // call me at first H-Blank - } - - void Lcd::TimeEvent () - { - uint16_t& dispstat = IO.GetRef16(Io::DISPSTAT); - uint16_t& vcount = IO.GetRef16(Io::VCOUNT); - - if (dispstat & 0x2) // if we were H-Blanking - { - //debug("hblank end"); - // we are not anymore, we're on next line - dispstat ^= 0x2; - // call me when we are H-Blanking again - CLOCK.AddLcd(960); - - // we have finished drawing a line, do our stuff... - if (vcount == 227) // this was the last line - { - vcount = 0; // we're now at first - // we reload the reference points - m_screen.UpdateBg2RefX(IO.DRead32(Io::BG2X_L)); - m_screen.UpdateBg2RefY(IO.DRead32(Io::BG2Y_L)); - m_screen.UpdateBg3RefX(IO.DRead32(Io::BG3X_L)); - m_screen.UpdateBg3RefY(IO.DRead32(Io::BG3Y_L)); - // and we draw the line 0 - m_screen.DrawLine(0); - // FIXME see below, vblank finished - dispstat ^= 0x1; - } - else - { - ++vcount; // we're on next line - if (vcount < 160) // we draw normally - m_screen.DrawLine(vcount); - else if (vcount == 160) // We enter V-Blank - { - dispstat |= 0x1; - if (dispstat & (0x1 << 3)) // if V-Blank irq is enabled - CPU.SendInterrupt(0x1); - DMA.CheckAll(Dma::VBlank); - - KEYPAD.VBlank(); - - // we send the vblank signal - //sig_vblank.emit(); - } - // NOTE : v-blank finishes on line 227, not 0 - // FIXME on vba, it finishes on 0 - //if (vcount == 227) // V-Blank finished - //dispstat ^= 0x1; - } - - // check for vcount match - if (vcount == ((dispstat >> 8) & 0xFF)) // vcount match - { - dispstat |= 0x4; // enable vcount match bit - if (dispstat & (0x1 << 5)) // if V-Counter irq is enabled - CPU.SendInterrupt(0x4); - } - else // no vcount match - dispstat &= ~(uint16_t)0x4; - // scanline callback for frontend - if (slcallbackline == vcount) - scanlinecallback_bizhawk(); - } - else // if we were not H-Blanking - { - //debug("hblank vcount : " << std::dec << vcount); - // now, we are - dispstat |= 0x2; - // call me when we are not H-Blanking anymore - CLOCK.AddLcd(272); - - // NOTE : H-Blank interrupts are not generated during V-Blank - // FIXME vba generates hblank interrupts even during vblank - // if H-Blank irq is enabled //and we're not in V-Blank - if ((dispstat & 0x10) == 0x10) - CPU.SendInterrupt(0x2); - // NOTE : hblank DMAs are not triggered during vblank - // (seen on vba) - if (!(dispstat & 0x1)) - // if we're not vblanking - DMA.CheckAll(Dma::HBlank); - } - } - - bool Lcd::SaveState (std::ostream& stream) - { - if (!m_screen.SaveState(stream)) - return false; - - return true; - } - - bool Lcd::LoadState (std::istream& stream) - { - if (!m_screen.LoadState(stream)) - return false; - - UpdateDispCnt (IO.DRead16(Io::DISPCNT)); - UpdateBg0Cnt (IO.DRead16(Io::BG0CNT)); - UpdateBg1Cnt (IO.DRead16(Io::BG1CNT)); - UpdateBg2Cnt (IO.DRead16(Io::BG2CNT)); - UpdateBg3Cnt (IO.DRead16(Io::BG3CNT)); - UpdateBg0XOff (IO.DRead16(Io::BG0HOFS)); - UpdateBg0YOff (IO.DRead16(Io::BG0VOFS)); - UpdateBg1XOff (IO.DRead16(Io::BG1HOFS)); - UpdateBg1YOff (IO.DRead16(Io::BG1VOFS)); - UpdateBg2XOff (IO.DRead16(Io::BG2HOFS)); - UpdateBg2YOff (IO.DRead16(Io::BG2VOFS)); - UpdateBg3XOff (IO.DRead16(Io::BG3HOFS)); - UpdateBg3YOff (IO.DRead16(Io::BG3VOFS)); - OamWrite (0x07000000, 0x07000400); - - return true; - } -} diff --git a/libmeteor/source/memory.cpp b/libmeteor/source/memory.cpp deleted file mode 100644 index c97da5601b..0000000000 --- a/libmeteor/source/memory.cpp +++ /dev/null @@ -1,925 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/memory.hpp" -#include "ameteor/io.hpp" -#include "ameteor/eeprom.hpp" -#include "ameteor/flash.hpp" -#include "ameteor/sram.hpp" -#include "globals.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#define RET_ADD(mem, low, high, size) \ - if (add >= low && (add+size) <= high) \ - { \ - return mem + (add - low); \ - } - -#define debugm debug - -namespace AMeteor -{ - Memory::Memory () : - m_brom(NULL), - m_carttype(CTYPE_UNKNOWN), - m_cart(NULL) - { - m_wbram = new uint8_t[0x00040000]; - m_wcram = new uint8_t[0x00008000]; - m_pram = new uint8_t[0x00000400]; - m_vram = new uint8_t[0x00018000]; - m_oram = new uint8_t[0x00000400]; - m_rom = new uint8_t[0x02000000]; - - Reset(); - } - - Memory::~Memory () - { - if (m_brom) - delete [] m_brom; - delete [] m_wbram; - delete [] m_wcram; - delete [] m_pram; - delete [] m_vram; - delete [] m_oram; - delete [] m_rom; - if (m_cart) - delete m_cart; - } - - void Memory::SetCartTypeFromSize (uint32_t size) - { - switch (size) - { - case 0x0200: - SetCartType(CTYPE_EEPROM512); - break; - case 0x2000: - SetCartType(CTYPE_EEPROM8192); - break; - case 0x8000: - SetCartType(CTYPE_SRAM); - break; - case 0x10000: - SetCartType(CTYPE_FLASH64); - break; - case 0x20000: - SetCartType(CTYPE_FLASH128); - break; - default: - met_abort("Unknown cartridge memory size"); - break; - } - } - - void Memory::DeleteCart() - { - if (m_cart) - delete m_cart; - m_cart = NULL; - print_bizhawk("Cart Memory unloaded.\n"); - } - - void Memory::SetCartType (uint8_t type) - { - if (m_cart) - { - delete m_cart; - print_bizhawk("Cart Memory unloaded.\n"); - m_cart = NULL; - } - switch (type) - { - case CTYPE_UNKNOWN: - m_cart = NULL; - print_bizhawk("Cart Memory set to .\n"); - break; - case CTYPE_FLASH64: - m_cart = new Flash(false); - print_bizhawk("Cart Memory set to FLASH64\n"); - break; - case CTYPE_FLASH128: - m_cart = new Flash(true); - print_bizhawk("Cart Memory set to FLASH128\n"); - break; - case CTYPE_EEPROM512: - m_cart = new Eeprom(false); - print_bizhawk("Cart Memory set to EEPROM512\n"); - break; - case CTYPE_EEPROM8192: - m_cart = new Eeprom(true); - print_bizhawk("Cart Memory set to EEPROM8192\n"); - break; - case CTYPE_SRAM: - m_cart = new Sram(); - print_bizhawk("Cart Memory set to SRAM\n"); - break; - default: - met_abort("Unknown cartridge memory type"); - print_bizhawk("Problem setting Cart Memory. This is bad.\n"); - break; - } - m_carttype = type; - } - - void Memory::Reset (uint32_t params) - { - static const uint8_t InitMemoryTime[0xF] = { - 1, // 00 - BIOS - 0, // 01 - Not used - 3, // 02 - Work RAM 256K - 1, // 03 - Work RAM 32K - 1, // 04 - I/O Registers - 1, // 05 - Palette RAM - 1, // 06 - VRAM - 1, // 07 - OAM - 5, // 08 - ROM, Wait0 - 5, // 09 - ROM, Wait0 - 5, // 0A - ROM, Wait1 - 5, // 0B - ROM, Wait1 - 5, // 0C - ROM, Wait2 - 5, // 0D - ROM, Wait2 - 5 // 0E - SRAM - }; - - static const uint8_t InitMemoryTimeSeq[0x3] = { - 3, // 08-09 - ROM, Wait0 - 5, // 0A-0B - ROM, Wait1 - 9 // 0C-0D - ROM, Wait2 - }; - - if (m_brom && (params & UNIT_MEMORY_BIOS)) - { - delete [] m_brom; - m_brom = NULL; - } - std::memcpy(m_memtime, InitMemoryTime, sizeof(m_memtime)); - std::memcpy(m_memtimeseq, InitMemoryTimeSeq, sizeof(m_memtimeseq)); - std::memset(m_wbram, 0, 0x00040000); - std::memset(m_wcram, 0, 0x00008000); - std::memset(m_pram , 0, 0x00000400); - std::memset(m_vram , 0, 0x00018000); - std::memset(m_oram , 0, 0x00000400); - if (params & UNIT_MEMORY_ROM) - std::memset(m_rom , 0, 0x02000000); - SetCartType(CTYPE_UNKNOWN); - //m_cartfile.clear(); - } - - void Memory::ClearWbram () - { - std::memset(m_wbram, 0, 0x00040000); - } - - void Memory::ClearWcram () - { - std::memset(m_wcram, 0, 0x00008000); - } - - void Memory::ClearPalette () - { - std::memset(m_pram , 0, 0x00000400); - } - - void Memory::ClearVram () - { - std::memset(m_vram , 0, 0x00018000); - } - - void Memory::ClearOam () - { - std::memset(m_oram , 0, 0x00000400); - LCD.OamWrite(0x07000000, 0x07000400); - } - - void Memory::SoftReset () - { - std::memset(m_wcram+0x7E00, 0, 0x200); - } - - void Memory::TimeEvent () - { - /* - if (!m_cartfile.empty()) - { - // FIXME, this may fail, we should do something to inform user - std::ofstream f(m_cartfile.c_str()); - m_cart->Save(f); - } - CLOCK.DisableBattery(); - */ - } - - bool Memory::LoadBios (const char* filename) - { - std::ifstream file(filename); - if (!m_brom) - m_brom = new uint8_t[0x00004000]; - memset(m_brom, 0, 0x00004000); - file.read((char*)m_brom, 0x00004000); - if (file.fail()) - return false; - return true; - } - - void Memory::LoadBios (const uint8_t* data, uint32_t size) - { - if (!m_brom) - m_brom = new uint8_t[0x00004000]; - uint32_t until = std::min(size, 0x00004000u); - std::memcpy(m_brom, data, until); - std::memset(m_brom+until, 0, 0x00004000-until); - } - - bool Memory::LoadRom (const char* filename) - { - std::ifstream file(filename); - std::memset(m_rom, 0, 0x02000000); - file.read((char*)m_rom, 0x02000000); - if (file.bad()) - return false; - return true; - } - - void Memory::LoadRom (const uint8_t* data, uint32_t size) - { - uint32_t until = std::min(size, 0x02000000u); - std::memcpy(m_rom, data, until); - std::memset(m_rom+until, 0, 0x02000000-until); - } - - bool Memory::LoadCart(const uint8_t* data, uint32_t size) - { - SetCartTypeFromSize(size); - if (!m_cart) - return false; - std::stringstream ss = std::stringstream(std::string((const char*)data, size), std::ios_base::in | std::ios_base::binary); - return m_cart->Load(ss); - } - - bool Memory::SaveCart(uint8_t** data, uint32_t* size) - { - if (!m_cart) - return false; - if (!data || !size) - return false; - std::stringstream ss = std::stringstream(std::ios_base::out | std::ios_base::binary); - if (!m_cart->Save(ss)) - return false; - std::string s = ss.str(); - uint8_t *ret = (uint8_t *)std::malloc(s.length()); - std::memcpy(ret, s.data(), s.length()); - *data = ret; - *size = s.length(); - return true; - } - - void Memory::SaveCartDestroy(uint8_t* data) - { - std::free(data); - } - - /* - Memory::CartError Memory::LoadCart () - { - struct stat buf; - if (stat(m_cartfile.c_str(), &buf) == -1) - return errno == ENOENT ? CERR_NOT_FOUND : CERR_FAIL; - SetCartTypeFromSize(buf.st_size); - std::ifstream f(m_cartfile.c_str()); - if (!m_cart->Load(f)) - return CERR_FAIL; - return CERR_NO_ERROR; - } - */ - -#ifdef __LIBRETRO__ - bool Memory::LoadCartInferred () - { - uint32_t size = *(uint32_t*)(CartMemData+CartMem::MAX_SIZE); - if (!size) - return false; - SetCartTypeFromSize(size); - std::istringstream ss; - ss.str(std::string((char*)CartMemData, CartMem::MAX_SIZE)); - if (!m_cart->Load(ss)) - return false; - return true; - } -#endif - -#if 0 - uint8_t* Memory::GetRealAddress (uint32_t add, uint8_t size) - { - RET_ADD(m_brom , 0x00000000u, 0x00004000u, size); - RET_ADD(m_wbram, 0x02000000u, 0x02040000u, size); - RET_ADD(m_wbram, 0x02040000u, 0x02080000u, size); // mirror - RET_ADD(m_wcram, 0x03000000u, 0x03008000u, size); - RET_ADD(m_wcram, 0x03008000u, 0x03010000u, size); // mirror - RET_ADD(m_wcram, 0x03010000u, 0x03018000u, size); // mirror - RET_ADD(m_wcram, 0x03FF8000u, 0x04000000u, size); // mirror - RET_ADD(m_pram , 0x05000000u, 0x05000400u, size); - RET_ADD(m_vram , 0x06000000u, 0x06018000u, size); - RET_ADD(m_oram , 0x07000000u, 0x07000400u, size); - RET_ADD(m_oram , 0x07000400u, 0x07000800u, size); - RET_ADD(m_rom , 0x08000000u, 0x0A000000u, size); - RET_ADD(m_rom , 0x0A000000u, 0x0C000000u, size); - RET_ADD(m_rom , 0x0C000000u, 0x0E000000u, size); - RET_ADD(m_sram , 0x0E000000u, 0x0E010000u, size); - - return NULL; - } -#else - uint8_t* Memory::GetRealAddress (uint32_t add, uint8_t MET_UNUSED(size)) - { - uint32_t loadd = add & 0x00FFFFFF; - switch (add >> 24) - { - case 0x0: - if (m_brom) - return m_brom+(loadd & 0x3FFF); - else - return NULL; - case 0x2: - return m_wbram+(loadd & 0x3FFFF); - case 0x3: - return m_wcram+(loadd & 0x7FFF); - case 0x5: - return m_pram+(loadd & 0x3FF); - case 0x6: - // we have 64K+32K+(32K mirror) and this whole thing is mirrored - // TODO : can't we simplify this with an AND ? - if ((loadd % 0x20000) > 0x18000) - loadd -= 0x8000; - return m_vram+(loadd & 0x1FFFF); - case 0x7: - return m_oram+(loadd & 0x3FF); - case 0x8: - return m_rom+loadd; - case 0x9: - return m_rom+0x01000000+loadd; - case 0xA: - return m_rom+loadd; - case 0xB: - return m_rom+0x01000000+loadd; - case 0xC: - return m_rom+loadd; - case 0xD: - return m_rom+0x01000000+loadd; - default: - return NULL; - } - } -#endif - - void Memory::UpdateWaitStates (uint16_t waitcnt) - { - static const uint8_t GamePakTimeFirstAccess[] = { 5, 4, 3, 9 }; - - // SRAM - m_memtime[0xE] = GamePakTimeFirstAccess[waitcnt & 0x3]; - - // Second access - if (waitcnt & (0x1 << 4)) - m_memtimeseq[0] = 2; - else - m_memtimeseq[0] = 3; - if (waitcnt & (0x1 << 7)) - m_memtimeseq[1] = 2; - else - m_memtimeseq[1] = 5; - if (waitcnt & (0x1 << 10)) - m_memtimeseq[2] = 2; - else - m_memtimeseq[2] = 9; - - // First access - m_memtime[0x8] = m_memtime[0x9] = - GamePakTimeFirstAccess[(waitcnt >> 2) & 0x3]; - m_memtime[0xA] = m_memtime[0xB] = - GamePakTimeFirstAccess[(waitcnt >> 5) & 0x3]; - m_memtime[0xC] = m_memtime[0xD] = - GamePakTimeFirstAccess[(waitcnt >> 8) & 0x3]; - } - - uint8_t Memory::GetCycles16NoSeq (uint32_t add, uint32_t count) - { - add >>= 24; - switch (add) - { - case 0x00 : - case 0x03 : - case 0x04 : - case 0x07 : - // 32 bits bus - return m_memtime[add] * count; - case 0x08 : - case 0x09 : - case 0x0A : - case 0x0B : - case 0x0C : - case 0x0D : - // 16 bits bus - // sequencial and non sequencial reads don't take the same time - return m_memtime[add] + m_memtimeseq[(add-0x08) & 0xFE] * (count-1); - default : - // 16 bits bus (and 8 for SRAM, but only 8 bits accesses are - // authorized in this area, so we don't care about 16 and 32 bits - // accesses) - return m_memtime[add] * count; - } - } - - uint8_t Memory::GetCycles16Seq (uint32_t add, uint32_t count) - { - add >>= 24; - switch (add) - { - case 0x00 : - case 0x03 : - case 0x04 : - case 0x07 : - return m_memtime[add] * count; - case 0x08 : - case 0x09 : - case 0x0A : - case 0x0B : - case 0x0C : - case 0x0D : - return m_memtimeseq[(add-0x08) & 0xFE] * count; - default : - return m_memtime[add] * count; - } - } - - uint8_t Memory::GetCycles32NoSeq (uint32_t add, uint32_t count) - { - add >>= 24; - switch (add) - { - case 0x00 : - case 0x03 : - case 0x04 : - case 0x07 : - return m_memtime[add] * count; - case 0x08 : - case 0x09 : - case 0x0A : - case 0x0B : - case 0x0C : - case 0x0D : - return m_memtime[add] + m_memtimeseq[(add-0x08) & 0xFE] * (count*2-1); - default : - return m_memtime[add] * count * 2; - } - } - - uint8_t Memory::GetCycles32Seq (uint32_t add, uint32_t count) - { - add >>= 24; - switch (add) - { - case 0x00 : - case 0x03 : - case 0x04 : - case 0x07 : - return m_memtime[add] * count; - case 0x08 : - case 0x09 : - case 0x0A : - case 0x0B : - case 0x0C : - case 0x0D : - return m_memtimeseq[(add-0x08) & 0xFE] * count * 2; - default : - return m_memtime[add] * count * 2; - } - } - - bool Memory::SaveState (std::ostream& stream) - { - SS_WRITE_ARRAY(m_memtime); - SS_WRITE_ARRAY(m_memtimeseq); - // write if we have a custom bios and write it too - bool b = m_brom; - SS_WRITE_VAR(b); - if (b) - { - SS_WRITE_DATA(m_brom, 0x00004000); - } - SS_WRITE_DATA(m_wbram, 0x00040000); - SS_WRITE_DATA(m_wcram, 0x00008000); - SS_WRITE_DATA(m_pram , 0x00000400); - SS_WRITE_DATA(m_vram , 0x00018000); - SS_WRITE_DATA(m_oram , 0x00000400); - - SS_WRITE_VAR(m_carttype); - - if (m_cart) - if (!m_cart->SaveState(stream)) - return false; - - return true; - } - - bool Memory::LoadState (std::istream& stream) - { - Reset(0); - - SS_READ_ARRAY(m_memtime); - SS_READ_ARRAY(m_memtimeseq); - // read if we have a custom bios and write it too - bool b; - SS_READ_VAR(b); - if (b) - { - SS_READ_DATA(m_brom , 0x00004000); - } - else - { - UnloadBios(); - } - SS_READ_DATA(m_wbram, 0x00040000); - SS_READ_DATA(m_wcram, 0x00008000); - SS_READ_DATA(m_pram , 0x00000400); - SS_READ_DATA(m_vram , 0x00018000); - SS_READ_DATA(m_oram , 0x00000400); - - SS_READ_VAR(m_carttype); - - this->SetCartType(m_carttype); - if (m_cart) - if (!m_cart->LoadState(stream)) - return false; - - return true; - } - -//////////////////////////////////////////////////////////////////////////////// -// Read -//////////////////////////////////////////////////////////////////////////////// - - uint8_t Memory::Peek8 (uint32_t add) - { - switch (add >> 24) - { - case 0x04: - if (add < 0x04001000) - return IO.DRead8(add & 0xfff); - else - return 0; - case 0x0e: - // todo: cart reading - return 0xff; - default: - uint8_t *r = (uint8_t*)GetRealAddress(add, 1); - return r ? *r : 0; - } - } - - uint8_t Memory::Read8 (uint32_t add) - { - switch (add >> 24) - { - case 0x00: - if (R(15) < 0x01000000) - return m_brom[add & 0x3FFF]; - else - return 0x0E; - case 0x04: - return IO.Read8(add); - case 0x0E: - return ReadCart(add); - default: - uint8_t *r = (uint8_t*)GetRealAddress(add, 1); - if (!r) - { - debugm("Unknown address for Read8 : " << IOS_ADD << add); - // FIXME : in arm state, vba returns read8(r15 + (add & 3)) - // and in thumb read8(r15 + (add & 1)) - return Read8(R(15)); - } - return *r; - } - } - - uint16_t Memory::Read16 (uint32_t add) - { - switch (add >> 24) - { - case 0x00: - if (R(15) < 0x01000000) - return *(uint16_t*)(m_brom+(add & 0x3FFE)); - else - return 0xF00E; - case 0x04: - return IO.Read16(add); - case 0x0D: - if (m_carttype == CTYPE_EEPROM512 || m_carttype == CTYPE_EEPROM8192) - return static_cast(m_cart)->Read(); - default: - uint16_t *r = (uint16_t*)GetRealAddress(add, 2); - if (!r) - { - debugm("Unknown address for Read16 : " << IOS_ADD << add); - if (R(15) == add) - met_abort("Illegal PC"); - // FIXME : in arm state, vba returns read16(r15 + (add & 2)) - return Read16(R(15)); - } - return *r; - } - } - - uint32_t Memory::Read32 (uint32_t add) - { - switch (add >> 24) - { - case 0x00: - if (R(15) < 0x01000000) - return *(uint32_t*)(m_brom+(add & 0x3FFC)); - else - // TODO a better bios protection than this one (read8 and read16 too) - // this value corresponds to MOVS r15, r14 - return 0xE1B0F00E; - case 0x04: - return IO.Read32(add); - default: - uint32_t *r = (uint32_t*)GetRealAddress(add, 4); - if (!r) - { - debugm("Unknown address for Read32 : " << IOS_ADD << add); - if (R(15) == add) - met_abort("Illegal PC"); - if (FLAG_T) - { - uint16_t o = Read16(R(15)); - return o | o << 16; - } - else - return Read32(R(15)); - } - return *r; - } - } - - uint8_t Memory::ReadCart (uint16_t add) - { - if (m_cart) - return m_cart->Read(add); - else - return 0; - } - -//////////////////////////////////////////////////////////////////////////////// -// Write -//////////////////////////////////////////////////////////////////////////////// - - void Memory::Write8 (uint32_t add, uint8_t val) - { - uint8_t baseadd = add >> 24; - switch (baseadd) - { - case 0x04: - IO.Write8(add, val); - break; - case 0x00: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - debugm("Writing on read only memory"); - break; - case 0x0E: - WriteCart(add & 0xFFFF, val); - break; - default: - uint8_t *r = (uint8_t*)GetRealAddress(add, 1); - if (!r) - { - debugm("Unknown address for Write8 : " << IOS_ADD << add); - } - else - { - *r = val; - if (baseadd == 5 || baseadd == 6) - r[1] = val; - else if (baseadd == 7) - met_abort("not implemented"); - } - break; - } - } - - void Memory::Write16 (uint32_t add, uint16_t val) - { - add &= 0xFFFFFFFE; - uint8_t baseadd = add >> 24; - switch (baseadd) - { - case 0x04: - IO.Write16(add, val); - break; - case 0x00: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - debugm("Writing on read only memory"); - break; - case 0x0E: - met_abort("Writing 16 bytes in SRAM/Flash"); - break; - default: - uint16_t *r = (uint16_t*)GetRealAddress(add, 2); - if (!r) - { - debugm("Unknown address for Write16 : " << IOS_ADD << add); - } - else - { - *r = val; - if (!DMA.GraphicDma() && baseadd == 7) - LCD.OamWrite16((add & 0x3FF) | 0x07000000); - } - break; - } - } - - void Memory::Write32 (uint32_t add, uint32_t val) - { - add &= 0xFFFFFFFC; - uint8_t baseadd = add >> 24; - switch (baseadd) - { - case 0x04: - IO.Write32(add, val); - break; - case 0x00: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - debugm("Writing on read only memory"); - break; - case 0x0E: - met_abort("Writing 32 bytes in SRAM/Flash"); - break; - default: - uint32_t *r = (uint32_t*)GetRealAddress(add, 4); - if (!r) - { - debugm("Unknown address for Write32 : " << IOS_ADD << add); - } - else - { - *r = val; - if (!DMA.GraphicDma() && baseadd == 7) - LCD.OamWrite32((add & 0x3FF) | 0x07000000); - } - break; - } - } - - void Memory::WriteEepromDma (uint32_t src, uint16_t size) - { - if (m_carttype == CTYPE_UNKNOWN) - { - if (size == 17 || size == 81) - SetCartType(CTYPE_EEPROM8192); - else if (size == 9 || size == 73) - SetCartType(CTYPE_EEPROM512); - else - met_abort("Unknown DMA3 size for EEPROM"); - } - else if (m_carttype != CTYPE_EEPROM512 && m_carttype != CTYPE_EEPROM8192) - met_abort("EEPROM DMA3 on non EEPROM cartridge"); - - Eeprom* eeprom = static_cast(m_cart); - if (size == 17 || size == 81) - { - if (eeprom->GetSize() != 0x2000) - met_abort("DMA3 size not corresponding to EEPROM size"); - } - else if (size == 9 || size == 73) - { - if (eeprom->GetSize() != 0x0200) - met_abort("DMA3 size not corresponding to EEPROM size"); - } - else - met_abort("Unknown size for EEPROM DMA"); - - //if (eeprom->Write((uint16_t*)GetRealAddress(src), size)) - // CLOCK.SetBattery(CART_SAVE_TIME); - eeprom->Write((uint16_t*)GetRealAddress(src), size); - } - -#if 0 - void Memory::ReadEepromDma (uint32_t dest, uint16_t size) - { - if (m_carttype != CTYPE_EEPROM) - met_abort("EEPROM DMA3 on non EEPROM or unknown cartridge"); - if (size != 68) - met_abort("EEPROM DMA3 read with invalid size"); - Eeprom* eeprom = static_cast(m_cart); - eeprom->Read((uint16_t*)GetRealAddress(dest)); - } -#endif - -#ifdef NO_MEMMEM // memmem() is a GNU extension, and does not exist in at least MinGW. -#define memmem memmem_compat - // Implementation from Git. - static void *memmem_compat(const void *haystack, size_t haystack_len, - const void *needle, size_t needle_len) - { - const char *begin = (const char*)haystack; - const char *last_possible = begin + haystack_len - needle_len; - - if (needle_len == 0) - return (void *)begin; - - if (haystack_len < needle_len) - return NULL; - - for (; begin <= last_possible; begin++) - { - if (!memcmp(begin, needle, needle_len)) - return (void *)begin; - } - - return NULL; - } -#endif - - void Memory::WriteCart (uint16_t add, uint8_t val) - { - if (m_carttype == CTYPE_EEPROM512 || m_carttype == CTYPE_EEPROM8192) - met_abort("Writing in SRAM/FLASH while using EEPROM"); - if (!m_cart) - if (add == 0x5555) - { - if (memmem((char*)m_rom, 0x02000000, "FLASH1M_V", 9)) - SetCartType(CTYPE_FLASH128); - else - SetCartType(CTYPE_FLASH64); - } - else - SetCartType(CTYPE_SRAM); - //if (m_cart->Write(add, val)) - // CLOCK.SetBattery(CART_SAVE_TIME); - m_cart->Write(add, val); - } - - uint8_t *Memory::GetMemoryArea(int which) - { - switch (which) - { - case 0: - return m_brom; // BIOS - System ROM - case 1: - return m_wbram; // WRAM - On-board Work RAM - case 2: - return m_wcram; // WRAM - In-chip Work RAM - case 3: - return m_pram; // BG/OBJ Palette RAM - case 4: - return m_vram; // VRAM - Video RAM - case 5: - return m_oram; // OAM - OBJ Attributes - case 6: - return m_rom; // Game Pake ROM/FlashROM (max 32MB) - default: - return 0; - } - } -} diff --git a/libmeteor/source/sound.cpp b/libmeteor/source/sound.cpp deleted file mode 100644 index d5d9e38ebd..0000000000 --- a/libmeteor/source/sound.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/sound.hpp" -#include "globals.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" - -namespace AMeteor -{ - Sound::Sound () : - m_speaker(IO.GetRef16(Io::SOUND1CNT_L), IO.GetRef16(Io::SOUND1CNT_H), - IO.GetRef16(Io::SOUND1CNT_X), - IO.GetRef16(Io::SOUND2CNT_L), IO.GetRef16(Io::SOUND2CNT_H), - IO.GetRef16(Io::SOUND4CNT_L), IO.GetRef16(Io::SOUND4CNT_H), - IO.GetRef16(Io::SOUNDCNT_L), IO.GetRef16(Io::SOUNDCNT_H), - IO.GetRef16(Io::SOUNDCNT_X), IO.GetRef16(Io::SOUNDBIAS)), - m_fATimer(0), - m_fBTimer(0) - { - } - - void Sound::Reset () - { - m_fATimer = m_fBTimer = 0; - m_speaker.Reset(); - } - - void Sound::UpdateCntH1 (uint8_t val) - { - m_fATimer = (val & (0x1 << 10)) ? 1 : 0; - m_fBTimer = (val & (0x1 << 14)) ? 1 : 0; - if (val & (0x1 << 3)) - m_speaker.ResetFifoA(); - if (val & (0x1 << 7)) - m_speaker.ResetFifoB(); - } - - void Sound::TimerOverflow (uint8_t timernum) - { - // both fifo may be triggered by the same timer - if (m_fATimer == timernum) - TimerOverflowA(); - if (m_fBTimer == timernum) - TimerOverflowB(); - } - - inline void Sound::TimerOverflowA () - { - if (m_speaker.GetSizeA() <= 16) - { - DMA.Check(1, Dma::Special); - if (m_speaker.GetSizeA() <= 16) - { - int8_t buf[16] = {0}; - m_speaker.FillFifoA(buf); - } - } - m_speaker.NextSampleA (); - } - - inline void Sound::TimerOverflowB () - { - if (m_speaker.GetSizeB() <= 16) - { - DMA.Check(2, Dma::Special); - if (m_speaker.GetSizeB() <= 16) - { - int8_t buf[16] = {0}; - m_speaker.FillFifoB(buf); - } - } - m_speaker.NextSampleB (); - } - - bool Sound::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_fATimer); - SS_WRITE_VAR(m_fBTimer); - - if (!m_speaker.SaveState(stream)) - return false; - - return true; - } - - bool Sound::LoadState (std::istream& stream) - { - SS_READ_VAR(m_fATimer); - SS_READ_VAR(m_fBTimer); - - if (!m_speaker.LoadState(stream)) - return false; - - return true; - } -} diff --git a/libmeteor/source/sram.cpp b/libmeteor/source/sram.cpp deleted file mode 100644 index d98edfedc4..0000000000 --- a/libmeteor/source/sram.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/sram.hpp" -#include -#include -#include "globals.hpp" - -namespace AMeteor -{ - Sram::Sram () : - CartMem() - { - m_size = SIZE; - - *(uint32_t*)(m_data+MAX_SIZE) = m_size; - } - - void Sram::Reset () - { - std::memset(m_data, 0, SIZE); - } - - bool Sram::Load (std::istream& f) - { - f.read((char*)m_data, SIZE); - return f.good(); - } - - bool Sram::Save (std::ostream& f) - { - f.write((char*)m_data, SIZE); - return f.good(); - } - - bool Sram::SaveState (std::ostream& stream) - { - SS_WRITE_DATA(m_data, SIZE); - - return true; - } - - bool Sram::LoadState (std::istream& stream) - { - SS_READ_DATA(m_data, SIZE); - - return true; - } -} diff --git a/libmeteor/source/timer.cpp b/libmeteor/source/timer.cpp deleted file mode 100644 index 6c2b9472c2..0000000000 --- a/libmeteor/source/timer.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// Meteor - A Nintendo Gameboy Advance emulator -// Copyright (C) 2009-2011 Philippe Daouadi -// -// 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 3 of the License, 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, see . - -#include "ameteor/timer.hpp" -#include "globals.hpp" -#include "ameteor.hpp" - -#include "debug.hpp" - -namespace AMeteor -{ - static const uint16_t Prescalers[] = {1, 64, 256, 1024}; - - void Timer::Reset () - { - m_reload = 0; - m_count = 0; - m_control.w = 0; - } - - void Timer::Reload () - { - // FIXME to test on hardware, vba update the prescaler even if the timer - // didn't restart - // if the timer is at 33, 63 cycles have passed since the last timer - // increment and prescaler is 1/64, setting TM0CNT even to the same value - // it had will reset the prescaler part, so the timer would be at 33 and we - // will have to wait another 64 cycles before having it go to 34 - // - // the current behaviour for the above example is that it will reach 34 in - // 1 cycle instead of 64 - if (!m_control.b.start && - (IO.DRead16(Io::TM0CNT_H + m_num * Io::TIMER_SIZE) - & (0x1 << 7))) - // if start has changed from 0 to 1 - { - m_control.w = IO.DRead16(Io::TM0CNT_H + m_num * Io::TIMER_SIZE); - m_count = 65536 - m_reload; - if (!m_control.b.countup) - { - m_count *= Prescalers[m_control.b.prescaler]; - - // here, the str instruction which have triggered this function - // will be taken in account by this timer - // in other words, if the str instruction takes 3 cycles, the - // timer will be incremented by 3 cycles just after its start - CLOCK.SetTimer(m_num, m_count); - } - } - else - { - uint16_t cnt = IO.DRead16(Io::TM0CNT_H + m_num * Io::TIMER_SIZE); - if (m_control.b.start && (cnt & (0x1 << 7)) - && m_control.b.prescaler != (cnt & 0x3)) - met_abort("Prescaler changed while timer " << (int)m_num << " was up"); - - m_control.w = IO.DRead16(Io::TM0CNT_H + m_num * Io::TIMER_SIZE); - - if (!m_control.b.start) - CLOCK.DisableTimer(m_num); - } - - if (m_num == 0 && m_control.b.countup) - met_abort("Count-up on first timer !"); - } - - uint16_t Timer::GetCount () const - { - if (m_control.b.countup) - return 65536 - m_count; - else - return 65536 - - CLOCK.GetTimer(m_num) / Prescalers[m_control.b.prescaler]; - } - - void Timer::TimeEvent () - { - //debug("Timer" << (int)m_num << " overflow"); - SOUND.TimerOverflow(m_num); - - m_count = 65536 - m_reload; - if (!m_control.b.countup) - { - m_count *= Prescalers[m_control.b.prescaler]; - - // GetTimer should be zero or less since this function was called - if (m_count >= (unsigned short)-CLOCK.GetTimer(m_num)) - { - m_count += CLOCK.GetTimer(m_num); - - CLOCK.SetTimer(m_num, m_count); - } - else - { - CLOCK.AddTimer(m_num, m_count); - } - } - - if (m_control.b.irq) - CPU.SendInterrupt(0x1 << (3 + m_num)); - - if (m_num != 3) - m_next->Countup(); - } - - void Timer::Countup () - { - if (m_control.b.countup) - { - --m_count; - if (m_count == 0) - TimeEvent(); - } - } - - bool Timer::SaveState (std::ostream& stream) - { - SS_WRITE_VAR(m_reload); - SS_WRITE_VAR(m_count); - SS_WRITE_VAR(m_control); - - return true; - } - - bool Timer::LoadState (std::istream& stream) - { - SS_READ_VAR(m_reload); - SS_READ_VAR(m_count); - SS_READ_VAR(m_control); - - return true; - } -} diff --git a/output/dll/libmeteor.dll b/output/dll/libmeteor.dll deleted file mode 100644 index 0122220fa5..0000000000 Binary files a/output/dll/libmeteor.dll and /dev/null differ