From 72808f01bbe48d2f928c20e493f935a1d7353fba Mon Sep 17 00:00:00 2001 From: nattthebear Date: Sun, 23 Apr 2017 13:21:35 -0400 Subject: [PATCH] remove all meteor and garbo stuff completely. These two GBA cores were never up to par, really. --- .../BizHawk.Emulation.Cores.csproj | 20 +- .../Consoles/Nintendo/GBA/LibMeteor.cs | 294 - .../Nintendo/GBA/Meteor.IGBAGPUViewable.cs | 51 - .../Nintendo/GBA/Meteor.IMemoryDomains.cs | 84 - .../Consoles/Nintendo/GBA/Meteor.ISaveRam.cs | 48 - .../Consoles/Nintendo/GBA/Meteor.IStatable.cs | 83 - .../Nintendo/GBA/Meteor.IVideoProvider.cs | 27 - .../Consoles/Nintendo/GBA/Meteor.cs | 336 - attic/GarboDev/Arm7Processor.cs | 501 - attic/GarboDev/ArmCore.cs | 1273 --- attic/GarboDev/FastArmCore.cs | 9916 ----------------- attic/GarboDev/FastDispatchCore.cs | 8469 -------------- attic/GarboDev/GbaManager.cs | 469 - attic/GarboDev/IRenderer.cs | 13 - attic/GarboDev/Memory.cs | 1981 ---- attic/GarboDev/Renderer.cs | 952 -- attic/GarboDev/Renderers.cs | 5939 ---------- attic/GarboDev/SoundManager.cs | 191 - attic/GarboDev/ThumbCore.cs | 981 -- attic/GarboDev/VideoManager.cs | 164 - attic/GarboDev/readme.txt | 7 - libmeteor/Makefile | 110 - libmeteor/cinterface.cpp | 246 - libmeteor/include/ameteor.hpp | 80 - libmeteor/include/ameteor/audio/dsound.hpp | 78 - libmeteor/include/ameteor/audio/sound1.hpp | 75 - libmeteor/include/ameteor/audio/sound2.hpp | 70 - libmeteor/include/ameteor/audio/sound4.hpp | 78 - libmeteor/include/ameteor/audio/speaker.hpp | 173 - libmeteor/include/ameteor/bios.hpp | 59 - libmeteor/include/ameteor/cartmem.hpp | 57 - libmeteor/include/ameteor/clock.hpp | 111 - libmeteor/include/ameteor/cpu.hpp | 148 - .../ameteor/disassembler/argimmediate.hpp | 44 - .../ameteor/disassembler/argmulregisters.hpp | 67 - .../include/ameteor/disassembler/argpsr.hpp | 47 - .../ameteor/disassembler/argregister.hpp | 56 - .../ameteor/disassembler/argrelative.hpp | 50 - .../include/ameteor/disassembler/argshift.hpp | 56 - .../ameteor/disassembler/arguimmediate.hpp | 45 - .../include/ameteor/disassembler/argument.hpp | 39 - .../ameteor/disassembler/arguments.hpp | 48 - .../ameteor/disassembler/instruction.hpp | 76 - libmeteor/include/ameteor/dma.hpp | 113 - libmeteor/include/ameteor/eeprom.hpp | 79 - libmeteor/include/ameteor/flash.hpp | 63 - .../include/ameteor/graphics/bglayer.hpp | 100 - libmeteor/include/ameteor/graphics/object.hpp | 100 - .../include/ameteor/graphics/objects.hpp | 53 - .../include/ameteor/graphics/renderer.hpp | 52 - libmeteor/include/ameteor/graphics/screen.hpp | 148 - libmeteor/include/ameteor/interpreter.hpp | 133 - libmeteor/include/ameteor/io.hpp | 219 - libmeteor/include/ameteor/keypad.hpp | 105 - libmeteor/include/ameteor/lcd.hpp | 129 - libmeteor/include/ameteor/memory.hpp | 162 - libmeteor/include/ameteor/sound.hpp | 117 - libmeteor/include/ameteor/sram.hpp | 56 - libmeteor/include/ameteor/swap.hpp | 36 - libmeteor/include/ameteor/timer.hpp | 86 - libmeteor/include/syg/signal.hpp | 389 - libmeteor/libmeteor.sln | 20 - libmeteor/libmeteor.vcxproj | 173 - libmeteor/libmeteor.vcxproj.filters | 288 - libmeteor/source/ameteor.cpp | 204 - libmeteor/source/audio/dsound.cpp | 82 - libmeteor/source/audio/sound1.cpp | 202 - libmeteor/source/audio/sound2.cpp | 145 - libmeteor/source/audio/sound4.cpp | 185 - libmeteor/source/audio/speaker.cpp | 169 - libmeteor/source/bios.cpp | 919 -- libmeteor/source/cartmem.cpp | 57 - libmeteor/source/clock.cpp | 125 - libmeteor/source/cpu.cpp | 447 - libmeteor/source/cpu_globals.hpp | 41 - libmeteor/source/debug.cpp | 85 - libmeteor/source/debug.hpp | 109 - .../source/disassembler/argimmediate.cpp | 39 - .../source/disassembler/argmulregisters.cpp | 83 - libmeteor/source/disassembler/argpsr.cpp | 53 - libmeteor/source/disassembler/argregister.cpp | 53 - libmeteor/source/disassembler/argrelative.cpp | 71 - libmeteor/source/disassembler/argshift.cpp | 71 - .../source/disassembler/arguimmediate.cpp | 39 - libmeteor/source/disassembler/arguments.cpp | 51 - libmeteor/source/disassembler/instruction.cpp | 691 -- libmeteor/source/dma.cpp | 317 - libmeteor/source/eeprom.cpp | 272 - libmeteor/source/flash.cpp | 178 - libmeteor/source/globals.hpp | 140 - libmeteor/source/graphics/bglayer.cpp | 475 - libmeteor/source/graphics/object.cpp | 698 -- libmeteor/source/graphics/objects.cpp | 168 - libmeteor/source/graphics/renderer.cpp | 35 - libmeteor/source/graphics/screen.cpp | 423 - libmeteor/source/interpreter.cpp | 222 - libmeteor/source/interpreter_arm.cpp | 1477 --- libmeteor/source/interpreter_thumb.cpp | 1222 -- libmeteor/source/io.cpp | 508 - libmeteor/source/keypad.cpp | 96 - libmeteor/source/lcd.cpp | 151 - libmeteor/source/memory.cpp | 925 -- libmeteor/source/sound.cpp | 111 - libmeteor/source/sram.cpp | 62 - libmeteor/source/timer.cpp | 146 - output/dll/libmeteor.dll | Bin 143872 -> 0 bytes 106 files changed, 2 insertions(+), 47778 deletions(-) delete mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/LibMeteor.cs delete mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IGBAGPUViewable.cs delete mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IMemoryDomains.cs delete mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.ISaveRam.cs delete mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IStatable.cs delete mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.IVideoProvider.cs delete mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/GBA/Meteor.cs delete mode 100644 attic/GarboDev/Arm7Processor.cs delete mode 100644 attic/GarboDev/ArmCore.cs delete mode 100644 attic/GarboDev/FastArmCore.cs delete mode 100644 attic/GarboDev/FastDispatchCore.cs delete mode 100644 attic/GarboDev/GbaManager.cs delete mode 100644 attic/GarboDev/IRenderer.cs delete mode 100644 attic/GarboDev/Memory.cs delete mode 100644 attic/GarboDev/Renderer.cs delete mode 100644 attic/GarboDev/Renderers.cs delete mode 100644 attic/GarboDev/SoundManager.cs delete mode 100644 attic/GarboDev/ThumbCore.cs delete mode 100644 attic/GarboDev/VideoManager.cs delete mode 100644 attic/GarboDev/readme.txt delete mode 100644 libmeteor/Makefile delete mode 100644 libmeteor/cinterface.cpp delete mode 100644 libmeteor/include/ameteor.hpp delete mode 100644 libmeteor/include/ameteor/audio/dsound.hpp delete mode 100644 libmeteor/include/ameteor/audio/sound1.hpp delete mode 100644 libmeteor/include/ameteor/audio/sound2.hpp delete mode 100644 libmeteor/include/ameteor/audio/sound4.hpp delete mode 100644 libmeteor/include/ameteor/audio/speaker.hpp delete mode 100644 libmeteor/include/ameteor/bios.hpp delete mode 100644 libmeteor/include/ameteor/cartmem.hpp delete mode 100644 libmeteor/include/ameteor/clock.hpp delete mode 100644 libmeteor/include/ameteor/cpu.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/argimmediate.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/argmulregisters.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/argpsr.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/argregister.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/argrelative.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/argshift.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/arguimmediate.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/argument.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/arguments.hpp delete mode 100644 libmeteor/include/ameteor/disassembler/instruction.hpp delete mode 100644 libmeteor/include/ameteor/dma.hpp delete mode 100644 libmeteor/include/ameteor/eeprom.hpp delete mode 100644 libmeteor/include/ameteor/flash.hpp delete mode 100644 libmeteor/include/ameteor/graphics/bglayer.hpp delete mode 100644 libmeteor/include/ameteor/graphics/object.hpp delete mode 100644 libmeteor/include/ameteor/graphics/objects.hpp delete mode 100644 libmeteor/include/ameteor/graphics/renderer.hpp delete mode 100644 libmeteor/include/ameteor/graphics/screen.hpp delete mode 100644 libmeteor/include/ameteor/interpreter.hpp delete mode 100644 libmeteor/include/ameteor/io.hpp delete mode 100644 libmeteor/include/ameteor/keypad.hpp delete mode 100644 libmeteor/include/ameteor/lcd.hpp delete mode 100644 libmeteor/include/ameteor/memory.hpp delete mode 100644 libmeteor/include/ameteor/sound.hpp delete mode 100644 libmeteor/include/ameteor/sram.hpp delete mode 100644 libmeteor/include/ameteor/swap.hpp delete mode 100644 libmeteor/include/ameteor/timer.hpp delete mode 100644 libmeteor/include/syg/signal.hpp delete mode 100644 libmeteor/libmeteor.sln delete mode 100644 libmeteor/libmeteor.vcxproj delete mode 100644 libmeteor/libmeteor.vcxproj.filters delete mode 100644 libmeteor/source/ameteor.cpp delete mode 100644 libmeteor/source/audio/dsound.cpp delete mode 100644 libmeteor/source/audio/sound1.cpp delete mode 100644 libmeteor/source/audio/sound2.cpp delete mode 100644 libmeteor/source/audio/sound4.cpp delete mode 100644 libmeteor/source/audio/speaker.cpp delete mode 100644 libmeteor/source/bios.cpp delete mode 100644 libmeteor/source/cartmem.cpp delete mode 100644 libmeteor/source/clock.cpp delete mode 100644 libmeteor/source/cpu.cpp delete mode 100644 libmeteor/source/cpu_globals.hpp delete mode 100644 libmeteor/source/debug.cpp delete mode 100644 libmeteor/source/debug.hpp delete mode 100644 libmeteor/source/disassembler/argimmediate.cpp delete mode 100644 libmeteor/source/disassembler/argmulregisters.cpp delete mode 100644 libmeteor/source/disassembler/argpsr.cpp delete mode 100644 libmeteor/source/disassembler/argregister.cpp delete mode 100644 libmeteor/source/disassembler/argrelative.cpp delete mode 100644 libmeteor/source/disassembler/argshift.cpp delete mode 100644 libmeteor/source/disassembler/arguimmediate.cpp delete mode 100644 libmeteor/source/disassembler/arguments.cpp delete mode 100644 libmeteor/source/disassembler/instruction.cpp delete mode 100644 libmeteor/source/dma.cpp delete mode 100644 libmeteor/source/eeprom.cpp delete mode 100644 libmeteor/source/flash.cpp delete mode 100644 libmeteor/source/globals.hpp delete mode 100644 libmeteor/source/graphics/bglayer.cpp delete mode 100644 libmeteor/source/graphics/object.cpp delete mode 100644 libmeteor/source/graphics/objects.cpp delete mode 100644 libmeteor/source/graphics/renderer.cpp delete mode 100644 libmeteor/source/graphics/screen.cpp delete mode 100644 libmeteor/source/interpreter.cpp delete mode 100644 libmeteor/source/interpreter_arm.cpp delete mode 100644 libmeteor/source/interpreter_thumb.cpp delete mode 100644 libmeteor/source/io.cpp delete mode 100644 libmeteor/source/keypad.cpp delete mode 100644 libmeteor/source/lcd.cpp delete mode 100644 libmeteor/source/memory.cpp delete mode 100644 libmeteor/source/sound.cpp delete mode 100644 libmeteor/source/sram.cpp delete mode 100644 libmeteor/source/timer.cpp delete mode 100644 output/dll/libmeteor.dll 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 0122220fa5fac323604e375272e8e8efd6b9423b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143872 zcmeFaeSB2awLg63CCNZ0oBCJ2Rqv-t7Is0|3wbx#2?X~yWyXfo9l0}jvE3R-@lG<>mzXJYy>7M~akD2<)80qCv zf4rj2wCImlEUCS3RrZ4`zy0qkzwto!H^1?%Z++XH{crbXuk?H?`@U~w&%dKA`+;xY zbMJL&X`^%WqSuYzeRclIU#vB*U(fl<+Sz!&>Z93fZ|3*3wKwp)bM0Jyx39eg_v=T` z;_>+_f4=rNJlwW+D!4~1rl9VLz_sCu9MIeax!mrGTE)bb0EoI<${WfHhrhw4aev?#8 z(amP*Wlzc3=*t+Dz3|L6ZZ1%jseJ57%8w7UZ) z$6oxEv;GQpGMLOmGbr@5%Vu(qt_Ww$$BTEDm33Av-)WU7G5+$}^LFPQtZ9AmKh2KT zm+7YsKQ&6)Yy6hcF5Y%gOc(v^72(|?{E&F-p_rre(<{PHh;U83^;66M{hSivgLG>h z!f%HFBk~LQnakGN%ghd6yW74(svQ8>;co9P+j2^)$Dcra%)76>RYQopsr{LEjTlj6 z-;v3Zfh&a|e@RPms@YLi!92D~#WfUk*`yyxlKLzcY4WyY*2TKLy;Ip>!~R}KR7;rt z$=kw#50bpcrv~1)d3%S{tUpoP1$u4rwj-(MQ+Hazfxgj*u!K_wy~n1qfMvI3cR(}a z=l$f=LFO8gw;f15r{sIvt=>*^xX6a8J>RXa>P+f?!t9WivHvyjX;}*JoJn`#chw|T zWUFCgYZONfyWL!)EHop3D<$Bm_wMD1S=thWh}-rq5G&8A=9KE6Ql2-n+abuU)T-6O`yzKR4Y1klmgN z)ib1hb%G=@n{T&!3^TD}YxrPmx@vZWMhBDVPE=w=Lx>(l(Y6()@IlJu=DDh3vuy!8 zP&T?J%GR00tJMi5ns;ws?mtGfFLT*J+_@;j9CX>~rn>A8TU6H&OPlee*-^n}fX6C| zOSHo8o1_*BdWBNu{<+lBxk4(|u12tTS7udwRT2DKGI=2$yW$!0wR^_ZN(GXn9raTt zYb!-kwFpy->9u@Q7Lkzk3H$>gIU|lON6x z=lBZJB?r&GyrU%xrQnt=ZaLyMUEHn_H$qReV%~0)BX0_*^TJmp&Edh#XU0p83%HU{ zs2$gMT$6EKfr}8P`pfMATpPF2B*|Ojm_fvsvE}wkR%g@dSDB=0Bv}^2FnR5>lk!m& zx+dpImPT)Ab{p8iLEO+neLct%N%+%yebyiKULWCPPJV*Ndt$Jm|1~6S$&}2Fyj@CT z4p}_}Mg_s)3(JiPm2^aIY`|TepW`Uro{cB%KcT_tRr|w4JUo%JMUU28P^Ih%UQS6k zV-Z9S8$e_FPJ8b3zLrCkIaZEk8+nG(h$vMT9GXJ4ib)CAWmBN@weW;i%v?`u~ z;QZ@fd=?5wUHo#;HAIoxWY8GTVf?X*7g^dsJBWF!RarFSMYa#LrPrcU_b6$U`p)5f z4DGu-JgpcF5Z~VINGt%M_NE4*E}XX;4Q^Lo=ERO^2}LxeU$n4x2F4AV-B!%@Y0GS& zWwc2}3beVd9nqvV?S~|smgLyvtpk7@L7Bn%R@+A4sm(DX3Tar0wdE*KLFC=a{B)a+ zm`+>hSTyvX8bw13Od|N8GqFHG%Y-a;XL|?7xF>oC(;mL=6)QT1*8h-+x&=ow4v(tqIreHGF?Uq@ggW00o$0{5_Fc{JoW(Vmm zvBfijgoVT^(v7GbBWjk2^41hw2o?$m_f>_bxq+U+2B0seD6iI5>CR^BbJ#@RLH9(q zc#iYHDhDf^#U#s4Ma~Vd#j_L>TW<574|`IptMb})1X*DYSMXP|idk$NOq*`!&Q%%I znY&O^wI7O-qX(-JxS8Gd>MCznSkLU+?Xl(^3E8Qh3J1%~ooqSGIu2;w!R%EjZP~yq zlnRF5tJ`1OAvQMTb~*Q~vL4VpClT{I)t;#o4Qa<=$WaO7*q~BA=sV&bS5{i7H8S+E z@dnPrck=0Z1!m8cY~GBpgmhsZlSVmg{;_N)u`BF3{Gx$4@3NBY3N{mZ zE(sx39c7j5kr`|%>$LPZJ65I0Ta&AoRdt|HtLMvXUJkGK3(n4mlV(3OXZ4iX^X9Cw zDD&np{2!OQ6S&=;%}nxEi856$<0Tr5sNVs92`kBAW*}fQ@|QI&&#b6KPm~+?5vvn| zu;6^{a^oBHUY_nfXZBFF#es;Oz%09XCigo35br5n*cVqw`kx| z7<@~up=9JjUf2asz^<1z*nFqu$NtVMbg+CXI{1|H9r?-Q2wG=z4#Cm2;{U} zxEd+4P5Gx?nP$0hH|2VS_awQIYomF*8-bi`oHCK!J`3b9^*w`RfK6`nQhKxE$^_bL zFNM#wgwMFoj>@|H4X{#H&SdjqP}p$QI;(Tw;VHRwnQY!H4*KmmrrDthf^uwM>K^y# zC}E&UtMhg%GpdxOR%M}0S!h=lIymp8OC&!|VEB^m?YEabRlx=+^jQkmXEK>1Y@g!k7y4{F=?#C;kkBmNN7EhbHpfacyG+*%%HjfQ ztTNW4EldWbgNap{fd3~^_)8KfWA%|289|{wT%6bjoNzWA{uCQfxFsqhhSxBF4AlyF zpfa^T42Hv(c4S253+R8>e@EzFlE|7+@7%&tVZy1mEmd4FV$EBKn(BjXWI_yqkdju0 z8VwW*2Y@WgAbU?)a{Yk%wWY$`6A+a}aez$~v1}9D2hKC@fBOtJl6OP8W7Rlzhhttz zC0sX4xa-Cq8qFpu6M`uOAY0&2U_9KBt}IRuE)XWx0%2mMz)&%aEVMUN<=3Fcyk{LN ztt>fYW}VKSm9t}Bp;e*M-&#G5!W=9)x2FQFu}^b=rIvNDPUD??f6F?&;R~x%Ycn~+ z_L6KZOm_z1s3>$4S5|0yVM+PI?nNBOY*cr-FYNhPS?_@9xN;Or?gZqWR45+kR#{f8 zwR>scYo{zoxNe{w z&Y3;aT@L$U%^c^sRc3aM6{JJYcuwRFs-8nZmquo4r|XcU1uulddF{|Z>_YH1PFm$Q z2m8ct(dHt?Tcik z&r63G8#TKyedToU(-*)`@9X@O#`(!8mUUKxskn0!d}Y}KPfJZh9A}LYoE6PLd}h1} z{3_WX;BW@w5eo>!08PnZREB!@0PQc@zbAy({#g=z12g*Qy>ai#YY@HkA zj9uth2F@PSX$9>&t2@{}%zMN^!oUUxY|A9SZyB3DH{r-v@F$kg9u1ugXrIk#Pj$3V7}aS?74N)eb|VIF@pX#vWnqE0HyQT9oMgFCMT=GDg&}h$VHhDlPKFPv zDfO1A=%RcPI^l1gp&1`Z6F=c;w8QaHyWLlP-B!$^lwUNJ+N%oZ0=*S+a&0I<<1WBc z`}8}I`Q@idgRWELF4qbHP<(4}{Gd-BjOs&ge`X?$qTD+GwIK%F(o*|R$74SK^+d$9@f#@V%cy!UMQ z;qe#}63K{Q?d~MSWe*jpMg2hGXwcO^0)?YM;V4JJyB_T2va1VC07!9Zoe&n<7Pwka zMBDY#B}WH==+R&aqlqSyngJ)LfPI5y#mHE!<)H);#uQ^`a?IG&W$#RploaLRbfwzi zy+FprV5fB|I_q$qXO}Qo*R|Y)s4!X~#rpzQNMI|{7&DOy;})I{fGDpuGiD%$vCf)b(07Q-~RR>2!z6)hZCiSpR(*5dF1aLWjP zM56KttxJ>_(FX+ir|E-=ymof7wjC^4T%&yF54iikL*~9(Xf4)`J<540h#roh&ca3G zYl4M~O{N$WM0})(KpeLj@?&!pzeM&l`lOB-TVNGc4X~j0BC1C~)Ri{8B0icg%RADV1utG3c}^;n zDYNjbOv&cI`S@*}K|j~f&vg39!H>4-R+GeAt*n-Odo{|Gzv1Se(ogjG(pu4MNws+6 zEtllR6B;jRHSQ*p)(PvUA&Kf}hqqT-aGNBdi03hJqrD2>Y2HDaR(yk;l{HGnw~$Pk z@*sX|THW-kq*d{tyZKATJv?SH4=UzCX-h=REj+A%URvklSG#VhNvc{F+X3q5637zt zrQ13aePe~RVr=aIF*w{)jbxsZtM>GKvpw1Ku67*&ZESb{nR`<)w@5Sma0-t|`Friz zk9f-GHD|Snvb3V$;#!&|O_2OMn(tjoE;l}cM$p#WM_J^?`|;9tKfzt|fC%|Ih1^9U zOZ1S16tajyZq-9>q>wojGDC!HitX~~FW&y_h{Zc(;9tp3%D&rS6c7Pamj~kQ>t69APt9Pdre(6>EUC?WtP@ZXvv| zH1b31lq(@p@LC+~tDv#To-F%F1ZZ176j^9Ggk8`c=QNZXe~H&PIu6h5r}UlLO(mS> zb=vw`{@@l=tiPYX)d&i%6mLrf_3jaGUlo+A5N~r(nMo~wzcd1<4U)2HiOFv1sz07A zzp?X7&t>grx_tq8Bj#w}ErfME6;!8AjJN8%KZ2*UG(Cir2>N3gd`b0>W`O5D@l0il zZ6$2K_8bVvZj6ou>(^&U>@V(PNUjuE>6dzPl~P~}F5o7J!NerLVJ7Yllh5nQ9tJY(UD6VK1XfK?NXa@W?G&C@A0x_dl-tTmErDX~vem*O(1&MabPKatFDCjT z^ic`yJIoo9CB4Avw0R~uyFD3N2kacYqdRsgW4Kjjlbmn5@2-CYlsW*{?L1rknheP^ z1=H^){xpX3r~c+XtrXcpQ`tN#j~nk?X!DF=T?mA~iGtjJQ(U%EwR{Lp;eRJKDzZ6? z?4GA%s-yM;yqg{TWh{r4p*{B=)E+G?CpVGFaJJ4C-AD zw#Me{@I1tgb0_EM`SNm*kJrOv+GV^wYmS(NoWJkxU(rFL7{zEC<# zq3YRw&uD{s?$b2qW<$SJiUw!jY4fb(sZ&6XdA88EphQ_e3S!YiIY$m`q4{5AQv9+lz zy=h^(zc?Mm`@fcs_YUfZ{XbrC=J*Jl1D9;$9lJR<}my60KQn3J=U0|y@?7sQnme5QQn}NiUy15&Z z%86DzO0T&WHT$bUk|EtDCQ8nuF&KCZcD{8X(XYrs>lbV^Zm~;yq1f02R%p%L=^do; zU^eG3?sr*iE69D*8CZQqB|G5VA3pFw?m6e#>Q&af-66B(O=lOze_bUSN$q%h3so{q z+u^5vE$C@cfL94M8h~b{R_9l(SlK|#gVyC;yu|7p?MYS4kr3rpTjZHKRm>mt2U_Q$ zjK$AI%TJ^7;c1Rm@KqZInkY6Bi0UHGG3B#`f(yp!^F=J6hq(V9>5oM=jG^LbRcOmi z#-RSTvP$hoAPB5qNT=l7u99MOcs^E7W>r=it@ofIM#q?3~*`9M~-6-XNe6YrH;gU}RI@ZMM@gObSG@>wvTVF6i6pm!V?ZO-f@f@SrrGeOGj9$Pu zRwrLbqkyY68E0(uO0WI0vYw-?R9-fOeL-yH{BhY7Y9+=#o zQ*RvzT^Hyx>o2{bD-QJO&+VZM)qZ<4?&(m{)29fatr;AyH@f5(-fUC+e*c+1%Ync- z3)>mcrdoDBLy1Bl9o+#72h4q+@3i~g**6f)S1)I2Jyg)PQS!Eqr%nfK?lInDDG*z4 zy?-Wb=?Ptdw;d3{61~4dWVQ6vINw=4N^cJKP75_a4YR!>!78n}>dl(eJvEB$YF<3# zX9o-C=1Y!zTrONCxFY;tOYp=o>o5ki)>8AtrQjUc3pTgb5&|RRcJVlBzL9ZTsOQuY zF-FEc!Q+UWBjRKq4Ht@{`hNufNN2ey{*e?3@Q;s+$3H$U z9{>2bc>Lqy65u~9egyt;@d@yUJS~y8l}s>|*iAHjY%gPXVrK23Ea%6oQ*u969?A-h zt$!pNc2ws)n-rXvMLizsP~J99^zJu!xBfWr9(C)}%v7nA*hlo^tKrF;)^um4-i=4q zpO;sqUFZlUHy&{(UD)HlGZWtO+(G3LNBtuba9uwxVy>%ga>!La6tsh#P ze-^zJ7EI{+z=vkMAFMxKU%#_AH1)uTdTcwzj#sU#vDnnvttWWeUy?4rF)v--`icC) zfatIvTK*jEuvN%KGrS#DWZCd17C!8h9DTS3aistR-hV1rNNkWa1g)Nm5%)R=CCzNF z<~qcxF0jX^h;op+z>y&857ZIV1?dT*ekGzZ6GS~p-9ufFH8M)}J*f8%Z!m#ws)lY_ zh6N7s_(b^UqWDBojKn8CDh{9cs5pG$qvG(1iyDbfT(rQaZ3Fmq``z$GsbqOdP2Kg! zP5!ZJx|G-LJ#MZ!paqU6)ueXI+je3B=?2fcZDHites?P5wFT?DhNTZ2PeT@w{uN3& zug1C4^G;N!bNd8Kk_+u+^0unUHI@!}8%AM6u&B6f@0Pa~PQ&_~rUUiIdn@bD^?IP{ z#<0N<)Q{DBOx}S}2V}hb!l1m(HH0p8hV3yePR~060F^@YEY~0ptiVF0bW5RQ8UcZc zPUiu1*8@sLb|^K!D#vZ{SJ{-RY&Hg!2KsDJ9)V-yoO|5YI?t}YnpId|rCwX(o7_~9 zrrQZmCb!8lHB~3yA%kVHj!59-OyA|^z;{IhDJ5{ ziBkT>nerQpGtV5pY`47iV8gKsz`+}6NURI1k&$<(YJZh@pni0*zv28CaamoIA0sJZ z`7u!^B7Q_qN!0b?_%Xgf;z#t#OZ6`lnw_ZomFV41U67L~dS;||P8(@C3T}qI_^;`o zf*x`G#S=%5_^3E~#7D)^BQ7e^KO^)Q7CoFE!=i`NBQDyY2l|_mMz*AqLG}-ZXxr&C zA^1?qtfeKK8CIAAN}7!ff+EK&A~s_(y_TmdY18q*vnUzY@UTqey_F}1PT3ETx~j=;vF0j@)U1PXm;KE*nn*?$`jk}WeEPmUF49j=&H9UFk z9CwbLz>{Mfp#mq0AO+#hQ548>w22Cw9)c7ccS2Dh8zBIv2d6>=pl1m4ShR>H9ptYn zX(3QgOZ63%?gzBoPr_l{z~+e!@;ORHK*pr9p{z5aEOx_B5LW{S#N5sF5cpt}yme=>ye*|BpjovU5Q8{BDZu^ZRH8q0y2%{7*8dB>X= zYRNC`Yx{oA?cWo_6Ek}=&^OicCd(i^PFv`iB=6{aDtG6B!H}Jv zyvHq;oq<8KyltS#Wh<-PVsgWR%AkfoP2ZyilDEARGUpxH;-Hu$;z7hT69>xM&LJjD zD?w7_9UZ(_d0P)gI`kgY-v=${RqGp2nbq)IE(@jT6Vfb$_^^hVw};^=thp*sV{+N5 z9vPF@-X_6s8t6?XN6ae{O$Y^QW|!OQESN=1iitDy3#OOYfR+p9i-!#JzDv!ji( z#LUwa=I(FfP2Y$WT6p`*4#GhSt#XkwIfd%ckXABS|k!6;V`zHXZ?Dc4KC{2$m51%)`j)Z;;R`!edYU zv5ZZj5-YqN1MHJZHkX#cd*2(v#KoAe!SgbADc%9KCh@ns_?u1p_^T9m4}Y_3C-Bxn zFW&YGJ80#l6zQs0CbQXnh5-zrjkkOIK9H)~gcXk!8a+y2L+iq^9Im^Bp(2hQo<1csO zCBntgw$pgq5$b|^rSLPexkLnNyZQW$V_9g^Zsc$IJkG97=Wn829ol66CfYS!v*T_1 z5IBbe8%y>Xptn|p=B)-~RU9<1)JXDv2}xQBtO!*yDTD)NP$ii{L=)&#IaP=d4&Y*k zpwn>*5tK_8A>9ZO&6KHAjuVc9QsuUR69vJhqwNfWRq|P4O!yH*P*yZe3_Mcq;{CDh z95ChV8|^aDP8Li$gw)i#f=RF8iMn7XpGuzEDQ1$jG#7}TMxU?YyD^%Kt0lQV4J>o6 zAt0^C_u3G7wiQwdhfHf;#;dK4N~N;edL&*UZKrujt!lbSYMMfzVllZpgMS`ZOW$|X zSAAt7GuC6fCx|+0C1gh7TD}owMN|fTMpsL+c7;@`O);WuD389ZLnae1&tk+l+)3KT zn@w2ho$VgSG6<6GRC0~dGz*R1cx2flNqv94%0yqjwD8WPVfozLIRLYjzxEDkhtM`W zPKXGw2tFp&-k=tnOZZ^H0a2;iJzL(^G`InxffxeI_Iv|X?zA)AP#MZ&6i!~aM-gR$ z1Ih+k3c|R)Xp&|gY%`&Ei-3*OOz5A~Kjt7TN>5SE$U5}WJeP^=fB!;!d42Oy9znsQ zbx^eZNX61PipPco4=$P?2?|(Si3DCF>Uu=!QiSuR(Sf7Dfhk*v7*Czy{gn3-C4&g@ zRNl_qot*#UQuFyfp5;gqWyCz4ul%Q+GO=}0vjcM4~3{uK3 zbo1w|QPJnESO{T+{|f6PjOT{z=yS=9(dV47{Y+>d&Wm#=_bq zBac3ROws=PdhmSE8ZH|0{8&dpv?=NnAm9ro&!FNuB{v=f7Wjt6Gl-Q50`hPHavOjR z3eYCWTbl~->(K_Una=D6ou@u*&MP=C4VGX695+fCeDO!=v;&0qEnv7 zb?|iZ{Q}?%lD@%>f>U2Hh$wHv>bz5&jye$s<;DpFJNcW4k{4nqIaS{3x0eznRS7qS z<(L&h#C-2c06mL<{&E!PKjw3wr=V}1g7<$U2wa`rYzhlbpTIZ0RU$ZfVoisuMq%Fs!2rF zY5>;;c9K9-P?pI0m=0ve9g@R`>$|ulv)OFIg@p9i{PkkVk&P=C*YLP>wDEp~_a=z@ zE#g+;YQQxtpP}9({YCE{kzRuyau{_BKKtPiSBV6 z${^$+ay=L&*FSFL?TMu~diPku(hgxX-tZpvk%oN$A*BI}iKGqs+pOAk;Lgz48fMX!Y=IDDWoGTyco02I_AP-}i!eo$9l#6V z2KB+=idl}V0g!L%>p8pZ?7 zW`N&-_$P4K%5ayjOb;Z|WWJ?)GRu;t}oY z9jLKidjfB8K49C8c6o>0Rg2{i-u8lN@K-?9rSo^_IW_?OEWhw^U=S)gZ~^7C%iB&< z6Yp^KL!MInPWgqCJZhil^GM6(lDw@Ok~BC@DH>49`$^hgi5Bm@le6<7+`y|Px(N7i z3fjG1Z}&%|?fwPWeUSS1)!@@q?A<|PYB`%iEjyA0)bAkw*??vNkl+FDhmvYX)9-O# z>HW~`9*ZB(6*X-BPODb@b1*ma`}2J)W+Tpe;J9?=U<$UDjh@*lj z7(BT<*&g&_@7XaAPn5SR#T+wrK4G>`8$&8^xJT^+jF_sesP)p zb%LGC^!jIXvG+C}1P(<50J>j(p^LeC2#0_`2{>SP3Ur289C{2K?iV=REpYg1b^;vk z#b_N(0vvk&6*&9=01F&mYteBSk07sW$cnGYB&?c+yR2#%EsMlDhLj5E?Q+TSIIdxG zxjBHiYjMrPH9YRoO3Cp)!p|p&yJ0CdjY0hHaShLR7IBZ_YQ!}>?sbTbui#pUYgioD z5qvz7#q|TWcHwGan3gz&1&E|5>MW!vVDqs3!rThnKr$ZQ)*fvu9wB$3DwOgQ+7`V1 z^D@4lI0K)heg+wDQ;IZHXvp|ERb0l;zzrYD88Uu!X5wCZ>vcx2Er-1MSIPMMp9ZJs zl5*g`BE8m!NAR}=LxDsxekq51(;|Z06_Gc^6B9%3zt({KUny^XN6_k!-x!5_&(AIi zxm!S9%OTecN%;ee7ZT~!eb+=F*Zy^qau6UIkgua>A>+qh8uDfVc_WAXgaP@{jKq+q zM%S7|3`2Gy-`g9$|Ty%7?slryyM($8J2jbO|lP00!58;2PGSo1eQ&a*V|_ z4cG9v>gAGS55nI~5H|@V@FD&wT*LCw_yXT6kf(xdM$G#P+t3AN4H*qXj>d{)ieqHK z*L!zzccOL*0vKNK!cNx(DKuI)E@97}c7^MC3c2ww7OK;9b2+r1boCSl0HO6{$2cFEp{Xe^@x zunJ|dx79d~FNjUY)bC-W1?i=g z;qJcIkb~{V-apvi6XOf{@n0h#ob%H|fPl@VeZJ&Cf4d=+UxjMO_PpapIA2J|SO)DbrapoFl_V3Etfu=-_2-k^N%iNGJvRS5tOy4v3ko6hl{$CA2g#$`ypl7@2x~=}$+)KDqURfN&Bs-XYc;O* z3GSQ05N2ExaD5BcuySMc^@#rXdytuT#(v%z$$WC*Ygw$cl%$zQLZgh;%xDtPKbJs< z6rzJd(ef^8jQ?W#XQf&6&#RG?cG7YUXqV&B>l!f2TlG%551kY}RNnd)@0u9m=b|}J zQC~$jRo&(=b<~6Se2*YeTqkOr-Lm&M_55dZD9C_k7vw9Z5SsSXywzLZVJoZ|vUfz%Uaiiuf5iFENEVPXB1mNS)I~?ZmsKeQ6kTipL zxPx*dhW64l-rshH{sU>z*OGW&tKw^xEJ@_A50!9dpCyU+wE3(%uBRnkOC1e)(a(~2 zKf6*-u6MH}>Ryp<)(C>4o57ZP1rO1&rR@6^Q9_I_=W-VV@81o(5uCyTsvq~Wa52D} zjitw!{8sIyG{StqtC`(*;m32oylwv5)*38)tjX)%5k86Hu{giR_qMxK-ug%ihbl?3 z&A^VANv}xRi1v*oAS8LyPGz1$P2Xgtmlxhf>SWwhYqx@RiDVAEZPvc{LtQn!t-Xek zqt|r`8#C&>6)x(R8z&LLT^a;~2ElMbery^S448(G6Ab?anb5aZ2!^-dZN=tf)ZoVp z(c)mlno;GV%>#gi)t&Obe?f?E?z5#){35gs(+GyP*2s87DP8uSN z?>y*Wc&x%N--ETy-;^A8;u@xBn;%3N#XpYwM*X=3_ut^^#`QnA{x`w>k6{1VxQcKM zD>EuDvbj(&ga$@c@Wez^`C2qYQx}9s{V^GWU9C#O{3#a_{-S><%X_t};eAGjSKW(~ z**<)DbUQL|0i$8>4c39L??JkH_K7ATp|@^8YU&}8qLZQ16_(`2`@kT=e~fK9w!Y;( z{uMYnRCk5h=Q`!K6`t-WaE}gI8;?9o^V zqJQ{{!o)9Uv*pLS5XU_I#&9v}uy*MGHZpxzbkb<5jr0Q*Zt;kQ15a;2ptyhkxtFDE{c5Gz5R$HZS# z&w&R{;XAjw6NYQ96NG_N6x~g!JE1oKQ6Azl%5cpe{JZ4150?j5BHkbd;r3m+!5R^! zxR)vr_8q)!e3puM1OETzP@Y1Cj0I@7VbZFpr~a=S@V%@OqGo{D?y&fmhqaI4Qw_TY z{jO7l3RX(*LYHoinL1d74&AkaH&7dHP35Opr|8hzZ0OK+D9x|~ZrU!av6Bg{v3z34 z5oSOsgpzIp;De@gY{PRfbPX8*UyS+ZmiXFJ9V=W=zbH!TpeB5KHTadjISn)bD|h8n)+ERo&ooSIGn#g zIGduZ#lkME>1#yOGn5$q3q7F!h7?n6{zeO(w^1@%*Nt==PV9faOtZ$tG!^F-9nE-pq+jc~!% zKm7pb(v7&qIFElz%~nrb3KGXSkNe=71ykJ@Rq+1`=kfUFsM`7AlM%IZ4IW7!L;S_4 zWbiG9Kk#J2%ZMer?cUSbH_Td}|)ULp5KC?f=H0?NE5DDz@GWqz0p$}|ef z$d5ltWQ|Oy?t%Mv1a;|7VmskI=JF%46`TQzu3*59jW4phDkEFiUhz zJ^y~pxBQ3X*oAAD+-&|gVEQKF|AK2+9Or4sQ~r4}JBg1z={tL@hbdQyplngTIt=_zF~~^a~UFLF1WHvLcG zFb_;xhqCqX^;!$SApPfc1*V$`0aYPs#rL!{#Hwvb^ z5!^L9jZmOqx*NerO^{MB-Hl*u%uOv)H>QTA(F2x+Q;jieO$bQ(e$-q`t()lUAL9d3 zb1h|!OA-A#p_ceyWSsbZjA|YkN8gV*Y6gFj#s(;Bq>m>A^iSPN*plwe1kVd?+NNdI})y&4Sm^!@Oyc; zrz5BW$1m5@73A#<9Ggnx{0*sHN*a-882j&inxLt{Vrd)k!ZJ4FSK&+Jlnh!s z8mblPe}ZQ{eW<+U5T#A)q4>Eh<2Bq{+VP`g(3(2FNG>#krFG$jW$dMh*b*nS^io9H z2_8X}@YROeeWbKA2-#|dZ{h8qLP%D1D662GaQzRi4{(`*Ru-folv4j!zId6GMhm@*Ma!%IK~+x2JG<4fo$g_LC`Qy=#>sh*lhgm2 zM*^+k*LxZdO|CG=IaMd;#1Z5a9~H0+qGt<{6WBz^!aq0|K~a|0#?z${WIPEbuPHlG zn57-XZ|J5NI%6>g1?8{|B5?~*n5A`7&{&p1#BCwkvNR393NJJU1OeYWL_=Wn629LchcK@?vb9t29nPdn=I^T~77RUI*5#66!p$2cg}3dgpp zgK@I(#pXr~$GVlU#>YkYO`M4Mt+kyeB03~aM3iY2yhoHtkO*HcQ5qtZ!bt^~n?C~n z79eyLu7$WB!1X;`FXKu?7ek(5J-=3q>5TfhBq*eoS}OV;{4Apd%x3=BG9B+2vSC#) zJ#{AWq@775d~o1|SoTUE`l7R!y)<6SM0qTYN)kMp*PhR_tdL+;#phP%J9v`ia%fx4eYzQL$pDR>Kj5=tbO7S`YvU5+Vt^D z^5bPm+}&v10C(?C5UDPIiORzn0fK7%hG7+D7Ra@o>iBX&T<;$V`#KT@WRyuR8Y1Y`Fzv8qnbgiYA= zSjxorM$7EmOqm3bwYE-Z^a`2<~SmmnAf02Z@|2ZRo>o_Xi8gG}fcllQp8yVF76f0ha| zd5@)f1B>C@#VXO_VHCSt6zAQQ)AwWe2Mr`QBbX>=keSz|mro^Ms>m%yk=cCP;EVi>&!5LSR-BWrk~zl<$$3 z-PcaueZ9Gt8YNJ@j4!v;iCJ7yYJhkT67kLWviiu8UHb&y4bF}s%QYw>TH(`1g_(VK z#8mj2Q6Z&9Ra9@3`zVvneUmAZPNQxFa~egVjAahW#o^2BJAwXM+l%+UWv~ru2k@k$ zN)5=l@lusOhwMhBQrBm#^xITvCX)A&H>h?7o#;R zb_rfWSJl>15u&+^Ls_-!=v60GD6O`cUIoi?_OL}I!)8RG@%dRqIBKlA3ND5*s!C!P z--qzy$Gm*1Rq~X3&u7Sw(-u>h5_%CbTI<;h{lWK+`|IU!qG1h>cJCjJpl&@V?(2&Q zaCwUyzcq5K!UuUG=x0WdW4{r^^dQdY`1*m^KH+M6QNmqD2^aPmCERWVIU|MMXasGE z1YKnW{l44C=rDo~zGVdc0}d*V<+~WjiyA*Lg8GjbL2nyDXWun~b{Rpd|7ryN)(HCk z`$o{ujG(9cj38zNrS%&@YxE%al;3?=a-76<9#`5L$uSkz)wrCv9>nz=u0y!2k4TO= zxSqlFcU)my&b63}#kC#Rhq$hK6!R;%zKLryu6?+AaJ`G`BreN3)PZX%uIq6*aTVdJ z#&sXAM{%jReu(Q$T!(Qb*C7wCEL>h(Kfv`%T%W9$99_86bp+RkxTYX%2Cmz1Rp7c0 z7o}T=>q-6j8Qg!5s|(i=Tp!{xOb*x^_%f6&Ovi*hI0{pMm?cmarW;$}22D?c)uW>v zq{sfo=HEv4Uv228&qfk#!OG6+t0mN;XM=nxb?hNLII+OD6v7faQ=w-_Z$R!!#i~jx zt}!zw4&=eoCB{QA&8Vt8bz=slcow@>iBk;tBu9{!v;=`c7v@4}-gh(XCY4vZ;;Lfp zho}M-sfFt9vHgG1emy^rv|obbx;)12 zvf+$opo|ZLZEQ?9Ve%=vwL0R6f)b(N$j}%Nl+-ePXW9LNd z$T!bA`>q*wkAuyhF~`|~bK}r*KcS{g#%Y6=KhOTU9acKl=jfbA8?TP0CjDv-yEWUn zXG7|`B=4Zx!S zDJ1N^4&T4uYHeCHqri{F?d2Lyi<@-^3k;a+xBE`2;?@eE0nYN)077}RKHXK5XZZyP_g2^Pp+{qO@8MZTxJ>dhn z)#>^~!XZVC1h2Z@RA2XrymY4u{IYKkR*&q$7>LPicF!KP-=?rCNG?LJrHLHg~!x zs`fRqr?hvW1*o*!Y=sK|sqapRn!GT(4abn0JWgE~VBgUvlH4SO8k5%G<~?ijSe-!> z#Vg}Qm1-MBQMK(TICP75(Ck_Gx$-a3^Y21_0b{XNAi{*kSW#D^edRpIzW&inY{jSJ zT2-n|7r`X23=NU-J-{2$WiDuley$;W#lRpK)oQPja)2BY{Gs@0|FWohgA__W?b>X@ zSHo&8QNR@4c(M{q#dTyjV;4!gP4^=K4oC2I&G zNgPwtRGI0o$Q&j+B9efM1HJz2nEDfSMbaMpK)`k-St+D#IoYGuT&MBk{)#s|Yy;5! z+B45{>jcnXZLCeT=Zn!O)CZ2rt_oT0IM-Bjp^ zcK0Ob{&g7}lAJDW^_X0jcG-S*mh~ugM?)!jN0jA9*?G2PX1?O-#+h2981_6tDe!W^ z7$H&p2v(x-7i`Qh2~->o${?K|t}F$=KM$4# zYB(wEZE<{vUN_geIF@V?wAP{-Ifh0XLrXJnr^%Fr3XIitbNgnP4x0!}*`oY>tWo9G z#YJ?Ow={M)_I(BEsIc;*;m~WO zvT3K+L@N6aOsMR>tB^zR6Ltm0+0=IDKKFPQMtfPC#`+!e3b0{}bD!s{1Nt7 zPRHiuXQK+Of4v4t6}BU6me*vD&JUG%f^(NRb`utFQ^I}k#|5+&3{1Z^Dxfm4Ie-?_5F~a$rEn-?V910vw##_Yp&q8tk zKLJI}a46_-v6!KaShgV);E3^8dQj>IZ#ONr`WIT8Dw6!gNwKG}aQn5ZQhmrI))O?1 zoyX-lJ}R}bvsxYOgz8xPG$>IoHAYK@zWrUaKQ{C~i*Ar$6nFA-48Qe}H*%mCMvud# zm#Ee9`A6XO>r==u665e?#hU!Fu$R^+V={EH)jf%&t4~?_sQAx4Y zUx8z(i?&S zrAO@-ON_mh0HBkw@N_`*aphur>=EwzP>ncSADqQ$q2Uz^OEXph93d@if+9FyLh6ND#wBr^4108K$wvvvC?^`pV~fvN3=>p zVh9SL#fTi2LY)&p)OUZ(`9LFmCG6~q^vEvoSVpUxb}$VlpufOH9a9Vcgfy>xc!{!r^Vah}v{? zhEnbEQ^Q0E_HAEXzkaN=BNOqSq#aqfvBh@!hRUXvA1V!ZuUHP5NVQg$pr<5h^FP*(Uv1=Z$>K8y457DY{&SRu1=GjZbOvs-JA}IyYP$#Nuh!&h^KSmZI;wV1W5lQc8#)OW@W#VMWtFZ7gIu<0R5&Ze1*zrx) zCC4|gj+bJeZ7W*>PZMl+eZ1p4xGoDrhTZN7N>Ptee$=^VwLNzaJBvr9P796Jzwlvo z8u`H#PY<|T_d~)HsB=8Gye~GGi41i3Uesq4tW%nk7HeKE$vmuMJ69&uwB zBm1`F4MQ038k~@4hCg%+`9l}Yr14CdF`nrV!OY=~F=(&hT+z)a_`;PO@=sM=^|9fRuNH_FT&6_?^xA z0Ooq6HTY#|lwT64lNfn^KXn-_ug8FuhTSPN0Nzi}G*pHL>nz01XCpM1EwcPb=g;ZU z`brX1DD)TAWiZlWVnrKjcC5gP5S%U(`^wdsa58?X9uxiJQ}Ipy%#{oE5hK6j?GI7k zr~7Agg@F|%asHW^WF`bTG?)j8q5K_04ABfWwtz_A#5HCd@niOJH57_~$M>6vJ=4&C z0!)8NeFCS&%c^=0_(gHO81$v%A*xc!%2YKIA%;rf8-}YYB~t2M)>R6QWZy&~T%}NI zs1$mSsuX=9iQ>3Q`RNioDSTpyhOku*GA=30ie)9*0?a*p;j38qp$ncAW-&5-a3U5Ju4a z#9?Lm3IFm#v+MQ_JGxiE$jgWF(pujWFnV4j?Ld%g&2^walnzADpzCF>Ac~%kp@<+T zSf4A1wa5j{!#MU3T`e?Kr8h@o1{HiM4PlbvHH2vY|BuZdR{k$d>x=or6}C^GK>Q-j zO(&Q@d=Zo@)<&T;80^GAhI{z*qX_zZLzBNE3%KI{I)ON1{EG8K*Kxb#QuBwKqvMe> zz3avpfy<5gL+ut)eHN(Z*a;S5I4O7=*>Je=nVJ~!72{hbnNh*=oU3S;%`veO*V}1D zsOJN6#pXFry02h?+(0F^Vpiw)sMyMq=ppEq3(BL|(N-Tq3;sJ6dmi}osPKuiWlxer zt6M*U7S1fivzPm`m=k6d`LdjkTHU4I^)M#KtT4CH6b81qc@!~Bj*$WIJmO?)-MrB5 zM?Pvc-DZsKC^?>Er^3b7%ZP)jORXIQFZ@@OC9QQgAbo^P)!zevy1{w#UJ}<#rfG4*-aZ9l~v# zDv0v{>D+Cc>Q1Lni$l2eN9?>^;V3JybeC#Jlla1SeiSy&c#odMttZuw6y$G)ZlOEq z17vBR(I5Q^js}bvQ_RRUR9I(-56+ zV$a8Oxn~1mv$N3V!TEpMq+GNXpC+9K+ckZ=;_wz)t$g5UBsq;q8cEg^uwZ+&MPoqaB8iJ4v#u=4Cn2h){{KD$`EcPxajt^b64VcKo$=9r7 zT6Z`s&vk^qY?6Hn64TDT_8lb1+Fsm)3C7Xf>S%iz&)O^N!{Meq__#UfIz&zwe^F0O z(1pcuovtHTIC4Ve6DL%q_HD3LAe05!Kw6Y#{nU|+^^kki5>u0D9_;wDxo=XpW*yoz zS`eS;-0Y5kHi^E`A54;c7>wb=w}6(V;DpIR*>ktL<`jod`vPEM9cMc5l_E|oOGDk^ zP!blShNVDgqW7<6%W}-%XtZubUE;N2-3o_OGlW*~BDGV2k_nWcVSHPgpae$ElO;gu#g{FQ2jv92!K3^l>)R4}L^x=?*ol2%Fel}8qvST}LHbV2Gh$IH7h zAY4MS?4cRs$rYN4woR0Pe+pu6IE&h>vhPpHM7U}A5M%)7p6{Smn@cb5S?sOA2lo2o zvQl@*U!JHPi3hY_5Ey)vLhZ<@VwM{>V=kAPBT1aACO@8zYVdXV{lCX&od|d2pxC2+ z>?IR)9V7PmtHk!;V;fL`bR#}`3HsKcJZct2U5BTpw-SItE2)-%k&4yVDK*%OtWK>J zzE&zO17G6ETMv}d^Te3vO#K;0#KT!qivmhn7jmX(N{FyI!QX7!9`pg#NAcv8NYPSZ zu)@uXcXEs*^YbP8W)P|%m4m}~G>VYFy!T8;Jtl4r_@+ZfqGN5j+37UzqSZ|cI}rRMDa`0La@74 zAH@@Xb}bhx233_RB>YmfuYrzz#b^+KJqBP0`KeI^bI|8Ts%(Tcbx>2j?02;RYz+51 zU9S?@YA;bq<=!c^=w%e=(Ch>@D3yVapyaLS-gurE^PH(atK~;ag~5qoHgb;DKBm=; zdb5nv=)44V6D?>f<*{xwn(Ctp2@Qv~5%u&v1@5GFchFV~b+OG-6ls=M0Y3pj%`zU( z-s5PNr6`v-%ci^VB+z@!?`j8n0Ya|>ANdLQ7|^4{YSC+`Hbc91;Par@O!VRCP0+^2 zpf^z~KTGIQJfSy1+k`d~J}yEpL;F4I>3apj0#IiH>Y(p#9ps>o#x>ap(|gPF{_+~cz0wg4;S*GBbdW)-`w~4D!?%=BVs*mCct!yosqeZn5T2r+z z5L)=+mYU;AKpS-J;yuLGMcP2{kA`gt0PWuh+K=d@siNi*wQd*0K8ncEK7m~M>>Xnr zRn0-2rX9ve*8uek+GPalCW3AsRUDOsCIq0%okuFPRWa4}qAxMi$=@fO2RM9R}HeH(+1J~7>7ss8b<;?`t zbgh$9mxf8;lyF0xowSW-bXz;rX5SV_$BMRHcqC1Ny}^>&x=5V{pgJj}Kys&62o3uo zJj4|+5B`i}+7qcc9L+BKQXvH@+V;kl*G=U;gz{kc>l%7Jw`o7$bhnH#Xea~5>v+tV z#+cSHpY&OGxv`a~z1Z;z8CkO{Vy53sx6?E$Le|3qUgv!?oZIa^_gUusjmh@!uKl#y z-B%~BdA?q=u}Hv*X=XtP+UflAM*!~Ch>T!I+3TXm4k?8Z*(P0~L_koreHl_1j+ z62vwyw)R^fc);5lPTh~A@4SnT9v}hgKYwQd-nAU4)&w&y1PE-G# z00kCw`DrPa;(0>xG%KEsisvW(@~4p&BMJ0=yTo@pWBcCf^>w(pD_M2}VgBo3u#@FRa#6574ab_LX1U>PJxpD>@yiHnJR&P=A;V91I8Y%T zNH|Qyaq>BqIcC{MmM(Rw8CV#+1JAr72ot>`->(r?(RM=bj|J4f`>8)3dslSkQ7|*8 zL}7@MWf3nrA?t*#d_4-%a)G<958_3cNHdet5Pbq6d~3_gS{{{mCXpzQ5*;VYB+(E9 zjhZGtxW-0Dy?3YL6YwNv-Si?nnibkLI?zins33tTfadl_JU9`kXHjJyR3>DZ-1s8| z5a(D~2ek<4Iyn_nI9!F0=-mU(xdGvZAv3ICWEIxb&SD(H#bq=$ZY!z(E2Q;X!=&RRO(KYNReQ6xEDF?Y z?Pu7NF%eLFuu^ZTz$gVw>DvG;OVo6L<5ua<* zb#!Z5sRI4yFaMj-o1Ms_y$y9vcEpslKT(<@LqT)AG@75+?!O2e zY>##YNrD6@3)4aNyHe+j@{Dae1c2c`z|&DYg|Hr@omqVk^4|29BjNCAS1Pt4q`61E zNgKU*Hav8nPeFfc)u(ENi>S!5kt&i5jR#9HpNZZJ2MN@v6QjMmPic;&3 zjnR3t{;Z7yZSpJ#gzO`QqHxj>E6kw$Z(=~0s9DwJ?mLO2@txV@&qo zfREa_IN+mV@~8m>^?n$&$cp|TX)Iby-zHMKXt0P!q!9t|h-`jcLYIIt-GUs3z)@bO zft;T&bgv2e?!yZZ_5BCkQMd(31%td!!*Ks5a(*BkY#^QvrfHZy`tqHiQH#n8Q&ma| zp=;F|NwRWqxiU!7{z@ZEl@imC#;TP;AGGlmNAvB+KKh>tbPI<(LEk*0+%7Dno;j(F8Be*tEN*X$(Xs-hB zIJjJU6(5z*cN2i(+UoUnc=fyL(YOu78(xDqxDyF5p%Y8opMYm1#TN#YgOKg}81@Zs zibg_9m;FlJ6aJ!R6!%>!?)yZ3h(Tk3{hGf#)-hmGec33jSgm_Pcm-0miSbC;wbgw5 zNXdkgbN9r}j^+eyj046b+XCbQ~b3UE`5BW5Os(#+@iXHF64YN^@nevG7{us^o zZd~)r+6fHf)lHO=$UH_{G6JIK6~5r8k5<$K`G*;Nh|9m=$VTk|g2p%khtH7Op5aauJ8f>II?W3~NA5Koq);**fRuK@_&Ok6h@GVqY!72~4>K;+QT zjl-Y#i=IXcwonVUk{e``9iYHja7Zos32IB%9{NihO)|7@j8at}C8N=Ex>hg(oS!JJ zLw)4^HCm|&6>=%Ty_a*4mA8^wfG5B+f#4BN%w7KSF2J*!;Mv37GK0Vy9hEY{v_Op$ zwZD+r678j#+FSxjrIf@t6Se;a%<&Z3rSKDN`mP34;hv+depj&!t*&r+kG^SD3@!~37k!ojM!$1wi)oo z6XjXOwXts^V2NuduuTg0!jc=2x07!no&e5N0*B@>l)6TLksqK!%5}OJcQVyeMe6I6 zNiAwbjoI3b@gQBHZNeP4>Z6pxVU#oiq(;R@CGQ5^BrI=Q6@Zv`WoS zZIv83ZP+t^JI?ZWHSYUtOz6Ns6jLBH^BVzz#F$AiVPEvW6tOS7{r4oC{5pBb zxvv4u3jxTM+iO?{j@Gc(cn4EuANI^f@5bB-lp5wvAf06&wgIJKGyiPdWjAKUte^{K z#gIa3v*B5L_M31JvV4hO+EGuuOWj;mC`0Ny? zdWbnrn^H&9kJr!~C(S-y#ooz195^4D3OO2MY}#^mOtNE{|NnQJ4> zZ<4Fwf1qlp(qHwD12L===Y8dmF$gt1IDuCNoKf zWWqCGKrA3pN5#gjXi)jofDED%O$Z5E4cOME)U{oO8Btd>aT3kU<5;?@t?qXJ#p>?X zZr|0ml*ErhCb0=076Q16;wqqPCk|_)vLt+%yuWkr^UO>_LR-7I|%xl)4Ab9vHVl=3@fS(vpAbban)OM$D76iJU|deS%N8_jLb)FQBx? zXxzb_rd}z)f@jP$n5Vc=Ab;y?GUK4Yt~;RMF56GO2Sh@=FYQ*;3s5g`$H+apr}ZOO z-9eSIDkEh)nN4C*B*O1sfgzHrL=CQa+4tm(1>RvY^~nmoZjzrk+y%O1*zQftB+t&k zlTufnN1J8OHf}Wup0HO8?_(4#{>OiZbBC5mg8Wy02Sn|y33qh6pJ91!UL1Q-Jv-L}5k3(j zdc@5y8O;vH3TCd)z}1?xB|d*8ch zSl`jGzN%r(P*?QShiEg2eSq&U|6qU zczv628B)UrAX87X>p4*h_%a1pi9o5f`ijJ&y#=q<4YH}G1#m>i0@QdSM=hplp&4kk z<;?~qZ+UjXS*mep~jQlueP9%^aQ0S>3znGm))c zqfyR5sBS5QQB!htl5~*=wt^|8%BL!=7nGf}>6dBKnz*7BB`!siDLGGpjnQL)gv#QU2@ zpc}%r@q2Vl)pTo6@B{L1@#{_k@kJ-0#&o#J*wYb38-2 z^aZ#yanTk)Z}+D%&0PPt>o`?1eV9x&4~<&eQ#`OKIX$Zw<>9!N=y_>e#y6nM;G!TH*~G$(BS;)mJ21{ zE67)8>f+dm4CJf))D+)8j+o!ENk-$t6ltwpe%hhht;`-#3Yuc@azI8H6gW=6f=lOd zwp$8RH78g)Le?M*pcoOy7T@TOl%+mWlZ5#rd_-F;FdF|Ecw~LXK}TNAc}849b6TcL zU6%kK6J2&S6%kZ5FA}tE*gHJh^t$YLzEzVaTDNFbB5mFqybO4ZO?zUC%Y__j;w%lW znr*yggnYHs_Pq20g`>md)z02#H2%H9rfP4`{x&5AQ4$N#i)|`jEZ}C7tyL5HrHjJv zKj_-$+SiL^y(O#FI?;P?4qquNxlXKbpjM1t7$G^R#TxAfkrDPXwpJh2GWM}o)nE#O z>!sEaXSU0okt$F4SpVJmD<>$2Px~>S#-wxhw$%mYOR5v!zXfQkJS;%(W&yf-=mPX^ zz3uyK8RxL-xhl2T>zS|2CaYyP4vVehW#E0vCahMh+M!-_duz9=MS5LPd;=SrGKCsV zSS?a1F%t>UiCA5{GMCXxZPfa+Rr5W3TSR8H z95-3}jYUiBV;~_cFdSl^ZU@3Z-l^*%t5%6#{IIb$=GyJT?St+ItLW)Z%p?*nkqTN& zG^BH!Wx-twx6wJy#_dyY;yH4QRXw>xApdWv&@jRm$n%WG_2h5qv4`9K1Yp(L(zRr7 z0cA-e8#o}A)uJR5`wWYm((lOvk7E49X{wIxu2vT{`?=~S0xvNAN1`i9l=$rR;UTrA z^_K$Qa20tmjt{pshwnFpZ=+<0aqDT?d7`PI4E#j2nfpMB$J;mEf<43b* z$L~I8nYnA%N1F#oQ+#ap(G{!N-j&R9ZDU-TWp1fRh_Y^*si!P<8PAI#KPq1h&UvAy zIEON4$5&rpxh%1ik7e)4UJRMHP@Ze6YimV$<-oY5I7wpj)&uV1J`9F2>m6*3PXmg1 zUyix|ensR=c2PyHcMrB0ru^_BUr8(0_X{-?YsSUgF-nuMZz-9pqd`I!U`Nbgtq1f< z+`zb7h+4V+Z7fQwdX{tsdKS=x6NP($(st#f>L~RKc*2Vc-P%tDUK{Uv3?=lXa(-iX z`CM(YcdS0YvTp7wo{LsbntLbLRoN{P9X+FILVvbI%qyL}W7WQ!zufi{`8X4aNCOL2Yul~>^p9+j!m!Q!g0+)o!Iw95j2{23c$s9j3s3U1(J0JA6srv@;C>~o-`W0btJp7yPSrPZI1-QE7t`G-s z(ZaQfZ*F~DB!(5s`Dtc>6lc0UyxPDA4f}NZT%F#qUK`EsU%xT302;xLy|ql^mo3;`nI_*ez+7t9>(%mDgMSfkZj&h( zM`W>oYP1S^v_%&9i(>A&*qnN(81xsKH~7rBniF-sOmauZ0{^5eekNqiZV%8{1XV1YGI~&x4+S<0k->S2El?xH_EdV%rul5PdlW#tdlTcEk)CWN^feyAe~!2f z!l@g3bxx~bqZ}(=4SqQ;hMh4fUyRBF+*UlmjmGhfYlm5m2e@*N=~#j@Ro=~WBfMfu z{flq+E$LV=t+Ys&%O0wgOLdvle(K6wxi6O^AhfH-?`@PlaNhF7!`uiw9tDqN2RxN- z9L%}c>Mgi05_mGUcBSAMueREb1kWuNJkw5w=W6%L8wH$|>vmx84NS_vB#zSbF0jvj zZNc^tH>ZZJ^ozl^^!7Z3t2Au%4p)0tE1dT(Z?$ z9T6WTM`+8Tub9g`>I8`agqOon5SmoWW>|BLJGR1|_{DETykG5gwK`qSt3Ao-@?dU} zR+P;&1^Xg{{z>LCR0yusv8z4hRAGAjqdY#wh^{pCqb|3i`Kgl>PJ3Go)??fcWyt4qIIY7CTn;9wj&>9sn}$mohqvpL)Kbn zft=HVtBZWeUNZd>naD1m0^kT49ohfQjWd~Jb$U1WqBR~f zjy>F*TSJ%8tJj8Gjasv()^()T)lute<-gI4Wsfg%H7C8gLV2o7<{`a|mj zzRkkZ8Yk*X=cl{Cph52;aGYLi=GI28_F9h~uF^wZDu?r`!D-|MAE%+#y0+H3tZrSG z{F0~^wXQZGcuCIjtv##IV?L@o!NG$Hc9jk6{SSxlAfcbY8B>^jWjUPc&m4I14bG1z z%p?qrTgAH@33448C*S>;AlJchDb?22|LDB$crLYGHLU+YXY8(9>Dt7t%z}&8tKRK; znbM<{%vYDvY}KQ*R^41h$}E=QV&+)H+CN!Q-LN~DkH@s|IVZyBok-@3bB1&J!$tk* z@;P(Yvn41r%gmSVeFBpNYbNT`Js*03E_O@e=Kn!zxzuSOZ9WH{Q??`)4SF^A*%30B zr!%;HP->OIvO%v@vDvG<;lA88xhTgSrRC0LfV@nWIb_IhY^w4Zn*xQADwcE#BW2#q z^LF#~f!T%Vhpc_&B>t_1n=+p>->fQhjvpxVhTcKvU(qqY+@U-L_#CMArDR8zH~|Xy zBK($}Nak4Q3+8VU!ID_8k!(UfwyEXdM4a8HZ5)6R9z z733;UX(otWcdO^O9ByOQW0f zljeID1#eyy%uzPh?Um85`l^kMpP3!!G8I^NZ}y__mcCMT1WfT3m1NI;qxss=@sC}u zPf&HD-q8(lSOzY8qBVA%b9vLXzMByvbw^7>6FTO59qs+|eRcQw+#yfLe4m3iStYF* zRREq0ZyTyU6^xNfT8}KuaxM#&vva%tK7|^VYh&KuF)Qw9*czOSZK?8aS!-T_>Egl#(xL74~iaLiurAnk*5!Sq(bD%#@>Yv;3;^ zyNaS`VmX{Qfx>TSnh^R!sqpuEH`8Feju)J&%nWo3y%^tBz_jLCkNFAnCGOaAPvyxc z?gjHNX-zqflWCRMLT~DzzVyL-p|^<3iY**HT-XeC zCu=BA0biYPl{n{CC;E*D-{53};TsY+7(NyGC%~84-a65lXlr$AJr330o~6B68+3z{ zq)kZ!yWUfaYv6YM^|t{8h6dH+RkXtmVGG-{EV~r_3`K+&CWHzHY7e zXGWu!JF3dB@V4xYfAMF`_}9*4QoQjGyd_zc(fD87kqp^lC$rD2C)pO>8XM`(TI<4n zcN&jKL+02q&jF<;9;RqMWsGNk%9D)ztnzq5M%YjK2wX}Jg#^IR-w-WovX%HH4P2Ec zR4sso%88c7Y(=w?V~#I4an7{R<#b`s$!4n1SCAvFg>DWAp=ReM@_ArIEWTmWC zl_&Pm*pZ9m$D^H}(ab*Rg>F|oTIMbCSaGyR!BgXV4&ToSdkAv>W$JkiVWps&;2?}9 zOd|Zu3J&++Kj+{_ch->Szx2^%F`@87hNxJ`aMf89vep|FT;n z`44WV!4dKw(qKo*KYU0$dLizPT%A{nxBIKzrYAaYadb;-x7%-U+H2r*+^uHI3C5ob zGa4H|d8)VnNH@EBlJ1Vc=XiIXkW#Ml&C?T8|CNriCz-_tq8lcqV!XtRCI+Xn;-CJI zFhg|3SO!seE64st{yo)uRIM4!V-$1EY5HA<901;Y%-C4vb+t)?ov8VuV8h#Wk-!J{ zW?viL);GVY%6JKZ;i#S6W<2x|dDk5;4c%5d``D@(M)TfS*nuALRQOtkS28sDEC?{>N3G55kq zpf7pT@X3mjm*@xq!Eg52h5kVbb+v^%i^z>~Db)Rd^D?va9coBoqd8YjY|LZhM^jnm#q!xcCb zo8Co&Ii9tvqkE%epVPrJvg9!9jY2WpPO}Kjz@@yu7CWn{(Hz+2OVH7*C}K0ji;g;| zlJA|52Y}j0Uebg1TGCn@!C^gMxUNq+7jo2JIN;0bZ{JLsKvLj$PR89BK4_!=Qb@z@f!uj$aO2gmjD@{((yfCxsgH`9x zb$A_)2hXqXYy}bZfj+r#oO6%y(65=_xB76eW3B^1`oLTDe<%f;^<=^&`6lWqV??M> zbJ%D$gcfo0X#5Xeq1=5%<}QZ!jO}GhS5-g5IU&Sp_3vwpUl-oqcNJvVo-_u%if)hA z7>W`gnSsD*F?U=|`)=CfYAtRHx8^4EEZoQ3T~8IanLWGuU7XbksN^8c6?qi6&wpCQS#7Xw~NwjFu)uJoZ$tc!*2U zaS?R%B#WSOA)W>xSBoa0dl^)NegU5x`6~xB4x(D{b^-9w6*M%QK!*c;S&D2ukd0%` z(li6u{qsU4;Ii&MXjaftN|i1M^j!d|C%>rL@XWFgR-LQqc5aK%%Ngi%a_+sN+ILT; z+P)T{mX*g_L-m8}Eb(-RPP<@@*E}up@K2-}olxgwP`JaqE>ljOmZ(+neG=a%@ztGy z!#!M=tz&FyGQMX?#uM+yYur6-r25;!SmEcAZ1%SMFMQEa1iLq0muEC=<(0&mJL3oP zX($nV>g>KZ+qH`ua~nA{9=QkES2<1=?p(WPe|rB{TJ+af@wKVGUOf(U$3NureujtY z^EbFLKc#fDLj;-;E23E_Yz%Ng(ulpQu24=G}x zxwk2IvTD3Dwo(Q=%b1-!+9E0hlVgsY#Mq}%bOIhhqxmL_>Bl@^p#GR>LTe_~AN{dh z3%|Wp;$7Qb(i~T~s5Ua**j(my9p%@D4)1zv01ajnt+uAk%Rq_#7iFE|jx5Y8rO03@ zS_S>rHH)KhtmCxzK zHkM75Gx;!$U5_w`15-{$M>akY;5DvAgh3E4EFQ6>IaNTXQ6T-;M!v=D94s5V1r3a_ z&Cej6CcdY>U%t8jQjl#?em<0!If0fn{PliZ{6_p(uGz*RyRNoxw<_H9+?!M1A$Kqz z3yJF`gNx9~Uec^no)@fcd5XW@?)b4B>(f|a9Y^T8w()6PK7flYOz(jFP9gspkRM%l zQIXx)u|`H-XS8=sdS8}nFLy=GK;hK`WmApDJleY@MEwq-2facXca;|M_L^~_5_2JF z8cc;0tQlpFP4xeN$XEuPU{Pws`dcPzD3&-QeDuLJg)wg=et-%L;R~PQi$aSpyrH<_ z3tz?nx_0J`dBN32^L7!{qp@&WbHRZBi614=oJ+?R75RM0Gq@=&Dk@5IVe5S2Hj zb#-E|=4vV*C7))654!5x91}3VIXF5}K8a0~(LHR6X#FS``A;QVi8+wpRPK!|not|L zF|XYmm_;d95f&4w2qKrj5Bip%!e}0?=K+nz7wCDGNw<<0{=JKRVBrDW&HMu|>%_Bm z!#eJmA_PI3*Yi_5d*=f=_1z*UD~-)Zjg6cI(HE&n%sy^>?>3U+FBdImCy$TG9%!Ta zir!99(Szqi+c5L=vvaXO_Eo2?)AgJ9A>4SJKHx}FxWAt-sr-zB+Enri8f7tBl_ew* zk19v$)Qycxa*XHO;`?)wC}4T6oqj7sOQ}!H<$28oUpf)V zO)fRd`l6%ET;ji?Pa<_WW>)pA%2n&Hp-YX8aiv*-IQRVgz~KT%9g--Q{q*W6Q4*K+ ztTxQ9lB&b9kl}KabVW{ApikDFfz=U&`*TA%s7f=FMFZew;xLf`B3%Q4zG&dI{#IjS zPgCGDh5SW1S~17JUAWyn`xE2QiHLxk)e0^$*(TxjBa=|$3leUTMm;hK^|aPbNSK`Q zClD`tIO0j&W78i~8xM?)i*hJ2799P)#YSuxb?uJ7pY6KQBV91QI2HYN8;^YnZiIfV z(2s-36b7dYj(MG-a806v$()E|Rv?re{&;e7*7eEDMGd<|h^W7@wXjLNKlz)E$;lk8 zn`N-e-w3EdJX3ZfKHJRf!7rRbGjO2BSSuPlcSuR%0@&QH&^YUSb zZNe(aFP(}}U@fRE4Bp@B+6}>7yX8RYcDHLc)CLa>t{&|{4y359mmy$wFgzaXmk^vv(oPK2lnrd3{#p%OZ1X&)IG? zZ{-LQ1SF5aQ5<7Pp}dG*pBt^|Zz?;HwJ&R{9hzzekZ`oOU~bkv95%|2#) z4=IE|{3PbR0t36pK9v=?zz0eiUJwoV8RMpOg!5&bYpDt6OaCo{%_HCWTx8<;wEjbpf-^&hS9!ox9n)5NqXiCgYAv-5ciK!MPic*mol*m^vd!U3(hNECkkwK^utvMf~ znT4%}D;($-Bk7%{Tn7!7wDzEMeM=(2DGofip z-CDyDbl`hg53| zW*=WQN>tov*@Py;s?YV*hsmbXMV;Bw6gXWe0i~AWHhatce`i6TF@Zq;Mk-7utBvMq z<_-pgh-mgoDn^+AoucJA4S0$z;C7kWuXjCKJ=;-wwm;~eZPAdPt#4@0))y_!jc%h) zYqbNT*4_@QSKG=1HXfUMjg4!)vwMy2{YaR1V{2^EwAt?&k3GiIu0(NPalf%Sgr4vg z9m^yc+djWjcUZLXT?`Qp?@Aiaf99emo1aVXwK?P`+IYT~PHI;lCu}pUGd8d7GoEjU zxJ=g-_ZZDrxz$XSNVTiHu44#fqnZBQ`<$Z)5E`U$OyUr=CShVr@LTfkZ6o$QUP{mNNGdWV@7CU}SUufY_@%S(Q@#UNYf7(P zDhzx>hVTmbBLTnJuHTqdeoJ~y%Iqjq*Ks)Wjf**^IbG5Us-`xb4n8J;EU+St+TmmZ z`k1Tdf-1y{n0#0|kl(I9X>|SR|ETI=tNv8}xEA)R@~z~Q>h=24_5UgFrT*(v@u~V7 zF_{Yz954~d=_W-yWmJ`!pT2ZW`$np1duBy#InCr;{rf^fC8wFN?7u1{r|Z}H1-A_M z){YkR>gE)f+LU_|V*DC0%$&0yYE&j}Xg{);T5HZUKfPpkZAstD4s<`pezlFqgW127 zQDCikZ&q!|TF=W4ietthGiEK5Q1@mbPTjR7{Vxx&9a3Vme#zwV0BP@X2X8T&5k$>> z@#N_EA4bRKyliaz@vE|`e-p26ihr=^X#-qJ^C$@(7yOE*c zRySf)G+!<;cSqzdUu0gPHLsDeB42Bcsje;Q+9b75u)YyoWHjFeh`7;W)qQkq`VWka zKM)91QBp!vMNaew0*SHlt{jR}Wpy-FAoq7unpxpvBA(L3z_`|&mqh_>n`A)?snTn{PHg;B15`Kc@=I|A%)w>Ja=v58^PHCipen|En6XKfA&j)w%W!q zFToI45&*3)R`>+EwZnM+4XG9vc*?3oMhR+sFu|S%bml1Ao6a0DG)_2Tswr?NO5iX) zqa%2~Vbl=uaL{#R5e}vk73J&z{MgC95$w>Jh;`<$z+c2A5klCg0lrMCEgMTJtR)4i<4lJ<;;A*6y5Y%=y&1NnaE0vDbKvh6l)_5;a23du&nix-ln6 z*Sjz)o*2d6!lVm_@3qFJEf`y~@d5XUsPSyIt6UPTI#Hdt0N+x{=^SxtGUp02HMcH# z(r8{f@609gJ6`>cHkudA%i)lfCF0YpvZ6ZCjt{qR#{>WfnKvuT9c5>s@byRFeKG^y zTBbW+6iU^e6Msp13sjU<-}wTy_y%s3{`^{ej^8(33#0KaY4_=xXeJn3pX<{2uRC}p z!?>oZK1G7>TUAVtigBYoZss=;s;PLXfQ`Q|12R*JsBR*dED z$Z}6=g9Yc9FOt*E%RI3bNx)pIS06|FfF}_F7h<3E0Ec#;yl0496PJ^sWM5@v;_-iB z(zMF6gx%SZ8nRDs(g=KjebxtRlg8hWDAgj(9Oim6PjAQ}FANZ*DJvr4wAyFS!xZNkv_oSk7WI2<-NiM&|pV93fK(Gz3Wz@_q=Sox2F2$1!R zm&a#(5;M6_errx_7CX1tRbra!$Tr`MOrD@(C#l~e_3Kx^Q~6BU`TWY%bEIIAye(L)-rmA5jE>Ns`*ro=HhvwBqN3W)?3LU~`a8Hr3hq?V_wXxK z?98s?jxy!ThgDP)zt)$Jaw}i1;~FV=Tt)wgU;X8?+#x$0o!LL<&idp9Zsn5=Tq6Z7 z{3b3thNBe^cPDXVCa(ySVbzKK;V8y;^F89aVQ4(`UVjD|g%6d_%AUZ@>a#Hp`mxb? z|0t!=mOk}j9suiKPA3T5NCf0nzze;Li$ zUsCUWA00Q5o4SKjaK&HQRQ4fSitK@Wl>O znprSae=H4FeXJ1mvcl7s_?Q{uZgJmKckr+Vz-TxK;fL1Gu9{W2s_sjwb^*N6bpM=B zQaJ=~h!zMp*m*E%i`Kw;ILJDWKE2#u!QI(%XW@;`#8dvX)Gzj!RIXx)Ch<+=tuYt; zmcm-HGF{3Q8Ff{N(xuvnvhYOV-@f<5rupNn#AAlK6o-xc#HqXCSy$|odvb>Tn62hnq>KU(Gqb^7I+o; z<%pDR!3R11U>JDPT-P%-jl*|Oz=0JGuVFyQ`lBDi{mA(ES-#MRstt_lUE|X!vj5=qhiMD)Z#fReoI}HkS2WV>ER0@|s}nHTalT zFX6f7fft3Ri!mjz>ZTx%P0unr6+-Na^tpMA_q*#q6tMDpNU!Uv)6dDGs`bB@SNZ+j zx2o)G$bP5Vro!76iDFsfd6_RURQ?JfWa;X$aoi$#rxGb5$V!f2&()^jW2#+>=%KZ> z2oj6qR*ovMt1tZfDU`pTn3HI~UA_EsXurXR>wlB>FKF7Usz%nn0y9XBV6<4(3qt!1 z5Ijx$S1j5KTW}VFiIp2>?)0Xtx@-vtUeA&_=~@m@66-Z>obL?my&&)^R=>vwEP>`R zHdmbORNbN}_vbmsNl&TnFL92O9?x_bn-^W?RGpwOmU(F(rrtNBWmO$sGVliKuNmkn zA9w>%RUwZoK6rk-VtMF7HcN{VmC~uqf%B;+@TsYue;af^z{>B zZl`Z_HrpKu8wvIR0{yK*EMYuz-Z#SaP;J(hyYpsst#Z%WwaPnd%j&ykb*<)p^|zI~ z48-rO?Q4oyhjew!+P-=zGQI9-&+5fZzW#XWtnI5l)umq2YQDjO#dz#L=CFD#XF=sf z%Le*e=g(?i_224i`E1-Td%nDjUWLAh0b3%B#)n;T=4k)5*DA$gf2DN7sf`w5hx@CX zhFh|{LH8xCH@B-43di3o_m!GoJ9kKjW ziebth95=Z9L2()7Lmws>n(BWGX~bk*=v5iJagw>i-dMA39r{v-wOz*=&z7b)TZa#o zrq9n~ESBE1V;+r#TFg%KZ4rt5CDx0o*2781%TjxRCSw;41L8-bgD%mT_zlnIT-m0x zNkrMqP-4|6br9y8aIM(==p!%#A2bDCpBZ|M$f}kl0}^@Co*s2<-a|5Fq&6B^47swE zY;Sk0ypY{|iMxKt$)hqIyVDq4-ObhM z?986ZwTD@{j_gC+k>F#wL<$abiHz&xw?&c+9?^hb*^R`WfX!8`r71{_($bHmsA)ia~GPy*D^QIZfZUNvUdVeXKsLwZ55nq)u;d9IHO@ zs%=1;1=>qmts4tpz{~y?rZ7gol-iwfU0!wCONKBO8a$cyI9+D-?@xUTN#fYDe_#Ei)y zB8-Mg6uj7?e!VB{g$JdZY<;GOs2P)GFTK%lmLz!8znD&oJ-mk?oZ3y_;6K4_dP99B zX*{Hwn}g<(7OGaN&bjx!mrn02(QX|70$E=E+sQVgHUCVoXY}Jj#A|0d6WJmHp^%l5B#V z%o~1nlHL|iYKN7YeVtMhy+yu~?axBnSc6;QZ+9>0C@q~P4a95qDE!|(E8NFdI zd^vPy`nPexN}FWI|0G-+h?A0Bwh6H-e~Ve|Wk&)dJ#+NHE_0mV-Nc&$nXmi+TyXrk z-rIiq8X9_oLL`S+n~%Ds7(f!t)*pC~fme8IsT8rO5VTAKCp3FO*@fIT{m4Iw3s1sV zT;}MD@EqI2g&^5RvnpIwh(mQB_4|37aQqt^K_B;Up>}muf+85ngl^#=@`oUn6(lsxeevpuoL>wd2r& zN4TJi2&=l1n(Ds71$b@&9#>*JD}`x>19w74iW7#bKd>3x$qskk)o-oi75)dnqQy~~ zJB6LDIhmsbpfA8tR!x-`18O1AD3%)cEIhnP#HjGx43#;O7#!LRd5!pNIGJ5X^A-Y- zm+-sIGKaq-lc{`xjq4p`djE5YPih7RB=0_w-R}95@-C21ht2Y)mc^LyqNQ&f@kBjFnC(H5ASVb zNSgTQ5~e9>H;QrS%$(Z%SO(rNsSC?%t3u z+qsJ^I-&O~-*z9JZl)lAN@5@NKMQ2|a9E(E_yYgZOcB1oe=GHrW+PL8;l+M`R(Wi( zf3X(c77FM*9Oh#G0#r8QZs}Z5xFADrFYw=D32j*9=3kcr;@VEQQ$wP#80WYm4 zMi!~|wb*-$Ev^%iUWx0a{yUXO&ydxNy*Da1CX4;Irls^E7%{fMeIuMboQOVQiDt?#Uhy(yKe=C#V5;Tw@^)EM7k`5R1ffiAF&nVBD26; z3b|M;Z|MFYEt32ApdxWcR0*utrM8c%Osw?2#4p(OE;9LX|4L$kkQkB4W3&_zY-Ng& zldu?D>R$@!ai9G*wu8_KDF}v7*;}98}%(d221YI|(Y%PH} z5}Ir=3&YwncHPP$GWM5=*o|5&KKZ9)nJHZ}vYkn`0#=V|11Ydp4w9=j^)iKOMjrq3 zEiF-L!}x+(kofK9lq?-<%TngR! zvIY|Wwv1`&xuX3#RNH#yHpv%9V_E9X94BK8bAI9Nju+*wBU>fy$QHjPtf#b0BKK!R z@h;hyoK&i7(OM0c(tq<+<{jkg8Ixs@V>DiSn4?A1 zz4@qLsrecHL>^TtTghvQ{5qL%pI$#>DCe>_O}Lrk>h=5) zGa?;$q_7@#$QKs&sIxg)ye=-OaCO3&thS($&i*8Hk(INXoU=^z37Ia#CEA{srN+sx zEHgXOPgB&(nKu>UrgYTI<*Ac1`5>|BVc;w~LB5geeG-R@$D2Fc9-NQZAa%%N8eV%o z?nt&MSw+FTv@m&E-h}rXrngbl`IuW>j>I|bFbr5)qBuc%Li=9Dl;~& zn{yU}VE+@-xJ2t@l{mTui$qKYchxdWiLhypmG{*jR353K;*l!4D{D9Zwq-R*>Wp+5 zpR=KvIp0(c*yq}17pSuFKSkN~H>$E57fad7!<8yKj=grO>G z=I0nrrZc#u$mv^6_(#HEKSuaX;@uwzr&IpmI2+rnZx;x5nE~A|Hhp4TizO$@wyAI# z92KiL5g8{UJ+{EbuZ`@9o ziQhqWdvdEP3Qe-TJvaQmt7NyF7CNOm zeB8BW_JIGN?m5TlV}rzbV3Qpc%gi}X2z#+%kCQ!KECLC|JIu~Ki4}flbW5^8c2E?? zBn30MtgL^^oiL^5My#Ov6Eab-TunrhE%vHi=5&=M`=ZP@_Iz}W*|8^~GJ}9yOs~o; z-aVycH>;q@pAYxVG5MxXee-AfF*b*QUz~%gCKxSHc*bz}QmMSTSD#MD zN?iCu1N8k`kW)LLh#uWbt>ie*zHq-0a?3sg=GehkRO1WUG_)EGvd2T^opI*c8s1@( zu>~rI+s)|;sZ7_tVbhSATa9(LxG5?{ z)1O(dN_JneH6iCxTDj?B&m~r}OwlP_^400ItFg~SnC!7gJ&4YBi84Qyne{3=Yt2uJ zoRT@zNXYQnN;@>;G&9&4Z_Z3yHlR19tDVsM=PBr6i#;i}kRoi>NHk=AYNxUD{Z=}% zz)vF~yhoTJB+*P@HMVvZRZTfHik5ZIs16opvA=2?g{GM>>Eh918TiDUuGpkHL0h4* zv@8DdS{tm7S#x%8$CKmWo~D|7HVUx0$!JKDoP5H^4C9e)+#}JSEOz?NVOg~+Vzsiz z+nUDxtuW>r-A|CDq&Im`TE&jyoe{5Yhp7~7fSn?44$2Pq?rIu$KOf;z%zU$Vx5AJ4 zZag_9Z@XD@g6rAaBkcBhmk;D&Po6ZqCWQnP4U8;lYUUfgSh7wzdzWk%lS`R=D7V{H zR%dU|+a;SL#@$On-E!Quz_qh@$Nw|9y1$`Xeiz%stTOP;HnjG-;=Q}5x~c?KFyE7! z@1Y7i5|zjB<)VOA5Hf; zhS4|=0hxH{T1Kf@VRWski5luUA!~4^kP8Y64A0bd6msRikxZY zNq(6``F3&1Nxg3hfc=pi`9VY2to#*sjOSqo!A>q37oxW{^B~zWgHo_$rIDHEU)r4OVULUEuJ!pOUx=(4#eYqUnp|5Pe?aQ@jD&vn$r% zybJ$Gqb+{71+6$Z#v+$bbmWb-9&fO5-4+U;OVPXx$gUk2Pd~ zLybqo^8%>4L!;`}6s;jyYOK}kA6gSlbj>!pwpQizD;d#3|F7h?g>scGfw*X4iB_25 zC!#TeEYreOVv67S6Gi-PPrAJ;;;a2{e@gwfrJO&jnTX8#ou`z)bxo>%Pu$PtWSZN3 zfISSbhFiOEsPd5~4QlxJMz8-jB8_yFt$_+Uc1-KoCHwNXM?xpe%Ss0F`|-bAcH*=* zBV+y;mWshrcI+zW7sJt?ME{}qv3y}G2FT8mZgAbR8bMDA1MGqhgKFM;p&sSoa%xHj zKmY&31%Dv}$nIYe!@7POxY)z#q4X81LgEV*iG>xltQwKNr@hJG<>(a1{QsKBUjzkd z8m~E*`oE*=-^In2g+tgr-P;U_FbB^4E2r=Bi=4iRd@W(jG^cOu#e_?ozE24s68|~j zOwtVQkIaEn#eG`h^nF5JqsVjUcmMlwx))U9m*MYT`X~qPMP3#i1XqaJ@nkNJN5bz< z2_JPCkBGuc-%&b)_OJzJXxxW2w8ik-aTot~w#UFK-zTHG-hC7IC1I*yV;{cjvt(BBXUljhMeCB;5pHFaFH2BnhuY|r zXunAsN|!Y|_66i&v7-^bR!4>FXdcpK4LOYi{1HFH!P~pe9{JW+Lf7Utt8#w z0*I3(vE9jbFCse4kg3-f^O_kDV8iQ}Qbo!+LwW00r4|`LKB^0DNENInSJR!ivY<}v zS}HZRxxM>!kYVAaQSh=u8zSrjFT==il?8=Asxr}NtFwu-xL3?bF;9NT%ap!&QWz`f#zeXYL`5gw06bpO6ZF9RZ7L|LKH<; zP&0=!RKf+07;kmPuFqguYox~9kfqlZex39#)@3?yU;qUY)So#}%lp42`~zWVTYryt5(a;x+iS*rsL2j#&dXrpi~SfzH5+vR ztyElk^~67R*MA7Q9r>R`LVZcECA(#O@JSkQtMMpQq#MV(G>&(di3}*HKTt;=CWhv> z<}C6nu+f$!;ZqOx}ex~Zq0!=@$MzMY0?oj4Fx1IUS-mym?p(_i96L>n-{ug zkTq^}tchZ?J@EnnvhRI#W)*UYmMmjexfAQ80=l5Y1}c!|AUz;)-CxaQu9xs0VG`UmdzRDp zFkuJ593(rrJlw=yPDAZ)ff6-+m-H{P{CBIWF0UKS4EcFn8|RuRMkX zPBaF3g6G;oc_FgTY9@8ZjZm&OU~}UqiW>B{*B$q*dZm}+K_tM{0@nLA zm=m~UuJUE{1b;{EhQPfSUt#;Q+U<416!S_ymYGXdYeqiTDlDZ|N2O0JRfWfl-OwYrpnG)|4;0EPLv3_w} zV)dxgnn$Ug=Fi*@GZ8T&lxzeh}??>Qpgl_A6 zl#{tKw}Nr)LEc@`+FmzTmXLVfJ@~ny&3=}77vg_8__^UH_Oq;?5&w6CpBo;spH=?B zQC7jh@1zS2e$9Frx{;UbrJz~al3j2S&(Q+)qCj4RE>~YE&_ko6YH@IuTDc2O&WIV4 zk%!T61=Ch9I7R>54!#yp`F&iIgyV#Ko+lED39||1gl`f;gog?12{u-xf0gq%r!ywJ zR3@s;j%D%0q{QQ_WHq#g{(8uq;{Jdd|Gdt{mfyD4@R!diGKM(=hXHE#wHF*i*B%P8 z)C(Enj6T<`#&#FbDfejM&{oZ})`#YF=x8J|elfGZd#&P@og#S$4AHepV&(kw6=0|>{2$ARG5875kSvEY)@X<|`mpCPGCa#niKwZief z3hUfPvu~*V^-Lhb@~S*B%>qrIDruc^IS8~le=cYWCMCrc93vebx$!DxE^8rh)>WX2 zu!=BPmY4(2@b01ovmaq85^bHwrh=s zI(2FMK1?@jyZAwleaiq%X7O_n!D^D&(TT^Wt zp`;JV(i+|?Z1Ol$k7lgerk7`!ZL#O)lM9D{C%I&-`3#c_)e~%)K5G?P$#zSi!m85w zqO3M`EmAV|RW1lHy+o!h1#NAZK3Oc;Y{NCa(W#Wxa{Ic+`0}3!8wi8>U9C^*N*?lH zX#AYR&4?gRCJb`IALg=r2YGTJPio#wq^RluZKkpGB&uf~EoQx04f|Maf4o&KWr#mc zwZyI}Cnhb7ws5%FCEriMd!g8OVA;Zoq!@SX0io*U*|U%aaZ7(p?h!QljMcq=qwWUw@WFRm$D)0sY64SJfxi616as8NrMM_kRB{ea(q#zL( zZIWx-DNXW0kO;|lXp19F^CeZKSbf?22&CK&!;OfU3=K}W@kYoG7c5p>kST5cTy8W6 zj=+cKUFY=ulu)|Z={rFfO}7GsUkt!mP|}DpQ;W6unB}*ZY^s8U%+s zA*MtMX_Hp!gWWBLZ?x1 zR2OU!H~C#7yn)y>MB*h~cbvNW*})RXj+A`cQ)D{27hqB_a$&NfB86R?&eO`!=4WXt z;*g76td7{x{Z;Z@{gw15X)t2f4-5ujDj>w^07%@K>f+N`=|0`j?IB0WPbZOvCFiI3 zu_u(?Of6P-e?T@vY7)~Zj^^<#M#A?}l~tFRW3e_J(oI?!hxhA+Z`FlcsOau?Q#mKyi&1m4PRv24Xu!MQP;1|pD)~b5QW}soJ2HkQDKmG} zQp*t6C$3MeB31Wf_V>Q2`XcGPte(p@P<)G)m&eg2AVlRo#`KUEV&g5~>D?op$lJOD zds~E^>d~-RlxBYRuDrLg4r-b#omgaA_dfxm-OOC9ba&dE1<8|w7@01ep4eA)4OV@$uE(KRLJE36nVwGd zHeCvyl!9R+S`kT%c`f}ysUfPnNj@OUsY5`}{6Kg2M>;#zq5Qd>opijwA*J`Jo=zUp zon4ACy1NlS@GMy2@V^vdM(LSFi;2xq-Tz0DSrXM!=&dmT)Aqk|;sg`BChOQjb}sGt z!|XS)YicL5?zm;ww8vghg|#&GVXfz#R%Z`<$Rwp{uEryW(Y30Xc=0Wh`t7#X^Kl{M)ZJg*Q6n^6 z+mePq?6=HGwdE-L*+n0+XXY^}&9EqK*9%q!mq`+PhFz}%k$Fn9+-7PkF`>V$dfV2JCEdO|p93bN;_ z%@Sn{LaoX5Q(@@er)O4wSPUgq5_?ijW2j-@J- zSfW0(v9CY0cE8$E^uUSK&auRvL7?d5%qLE&Vz!5HX|>b$&jef9S93w(11G9u)9dY3 zsMeV@ab?}AR^oEwA5XAw5biHn^A%&`!+mfO%yfuL^kEsZCa1)%w|8gN%a}GxzxL>8 zS$^rV6xP(bu4;NRP%gYtH9ZfP!A)<3QPhwjRQtC9<1RuIVQ_mf2by`;LHN&;;%rS- zUo(`|1G$yfin{8;MYxPY=D744r)aB3F(VbXeQMlw>sP@n!pZ8@+Y@KaO0Sm(*#0@Z zF~i?pGK2x!$%GRL)lh7SxjnIMMmn48Nt|r9*3%P3#MrA9xfW&Yb>P=Y**z23?4{>+ z)iSjqhloX8fSvq*E>?^?WZC#i4O^O71-9CB4L4_i_A7GeK7%H&UO@k*WT#l$*t`Xz4q1)= zaGIcF=xY2l4YReV&d`hXknh5*H{9g({fg@mquNrKInRJT` ze3+}@P}`50>CO#*c)u&H@mPG+k$CHJn*nwtJ_j(Hk8CU{8YW6Cko6|X70cV<*MwV- zc*6Vdx6F0frEJ;#ypP};o_Tg8emHFPFII1DNhu|C0sKb*k4-x)t93rn8a|xj(z=zH zFXe%1&1O3ik6n~0A2Y2kf-1(Yk_CQ_4gM4he6=2E_9TwboW$@#<|&3U^Nz$+UCIz< zUNy9Ybw7qa#|XFF%>Dv`NPrZ*TqtPFn`uoV{t*+gQ`lEsq0bV&zuIP`Ng`&OQ;@`y z6ReiCJbb)h4JKvgf*K{&=5UGrqsT~0{;~ZmB?3kHcmN4_t4_O=i#>6q4GYq3;$~@s zoEMQ2GqZ${Y@D00LUIu!wtI9gcS?zMy2O;w)q9lflL-IR^*akoN9dSQB>sKT%{M``iu5W$C-iXUc zv{(+>WrmH-s!CjA!FD11px{!}0I;TMIv+om6kvmQh@T9Yy@%NX(I(d-omHu1WfRsS z7p-yNF!VSm|pU1#;zOtgt>})gxuuB49nK!FrU-7Xl02YboD;gK!^VC|ou^l|57; zGr6Xk50w$48w&)>Bx)zqXIb@P55<9g^dmve1Q$6du=562YMhSCdrU^c`%j3wWHr{C zAT|Y5qJHshg4@PYE-4eHp>{L7`?nqW=+p*GCHs^kG|n8ML`%41HQcB=R8F+psqHN4 zkhqZ?3<cGM<=~Vdb=;oYoYa5SdYTJeN&v9qP0k@hg^_cxy7m4xDhC>?P4m zUUpbE^v@f>X}Fx3eGgis#oyl@Tt1s5*Y)T+eZb{uaU=l<|2hs<8bS{NXj&Se4d*I= z&NK_;n+TH-L&2I4SVJ>02hR8!>%)XA34`0LIpFxZ)3;OJa~&G@ZQjiz$aQGkuX(qb zuy2^SQQu&{0AXnV`9t2-5LQZDR#ujiApFGNy1xPy|H=EKC&%gii$mmzOl;9@SwaPc z&2~1B7B8S3R@Ph^Vk-5pEnRj~pm3}hMBec&B~5PSlH%AeWDr@hZ?k4YB~P?v8&$JhdK#m99MZ^c zgU{+3J(*dfKV3c!-v(b%c|Ng0@*JiO%E?W-@`qBw^px#yugWj>8W+|6el~WP_V?Sf zM{a*Ned(n3*JHK6LlL~!tM&(;WimyyE!&>46B!!HmlN5XdMQ8z=eNGen49oD!cacX zuf<-8_i`N?H5!Fs{Eh4Pv~zl+koADrv1;T4V@wfFQmh}?b|8y zvF?p)1jk<+A`+Sv3{zGXu2M=A@ocAC7qZmzlsbtUhrn=8}l zj^x*^o6sxC8Y|1-FKi>RpC+%d-<4YLk{8>NW~S*^<9!If;# zso2taS&?x=Tog?M;#W1qEnG(EEYn?}W#t#ewZquVt}!*`GIac5eUR?x+Slc+#Kx2` zo^Upyj8IMZ8sTOK2thBcYkF1OR6en2Xb*G z+p5*j>;eaNTQ-WEC!^?UP*iujB5II}ts$J+%Md=EPUXKT10CkT+2lHta5G^j?3TXF zGFC9Rz`;o&$!rCEe81PFyp$?0cWE|M79@p#t)TUA`J%dK7qGlXI5G@OnHaS!@s*1v zGp<03x#wdUk8lc3(O3<~`@>tEdUi6R`ctK~C3CIm$PDOV$91nO=%3iaWkhyNxxTWf zAwIP-Ea%$Sy};Lx5#%})rj_29dfsz_V)3W(4>@~m zk$OFf#NMWY1?s`E{HM9W2~d%PSbtK+tCH4drgM2_4nOTJ5Y2J&Ybk#}Fm+^qz^}8` z^gR6zHz^<-Dr+C5zo<&z7C*p=UneAqNddLkqBo7}qs~puaGn`acWNy=GYa`d5XVTF~Qc_Jb zyR>KhNcm-Ufpw@6uX-s{yeAK>H&q|@ue#*Ove*N~_(6P8vQE4PM68qC5c=;;F96VH zFFz%%==6I=Nrd}`&?li3`t#z)TF*NDv5AeFrz~;1pE+$X8*Jn$X z#A_p2403uTr3}nN3*<~5mfXB*QSpO2l>qPJ^5Px%2wdLnzW@ktQMYHv?P7I1T5jj4 zTNk$)Vh&~{+gj5-etG-4?~}!k2>(j>CE+&&huiIT60!)cAy^mqPkaIRm!{yqmhN)H zT?+p7Ton9?Z%#!wYHnTLuIiAePCZIJ5?7}lr7npX_G4y!RCUaO3bMSF@Hd192rT|B(g3~0BrANhp!Fc39;25JJ&TqK;*6`8ujYoFMn~jkd0QAmUn-E=uIboRVA0UcvAA`RPu3%;B;~s>33v{ zU>cJA-UpU<=h-<&w=M6Eoeh;o*Bz`=@No<;3$^_gwDm`Y<&B0b5y;ETD@-OXcC##4 z6h6?;){~jF@q?b){B1__)(W~}nQ5=1SZ2=Yn|1sFJ6OrhJ5{8dc{$>jO{a>K13E|iQclEFk!MwT&C#6KLRV1eQ3BX3 zotk(?ZvzD56Gch z5*2I03zEfW2gJLRD>3_~6az?|B#Uw1MT)7<>yJt|U_7!*c(>t)+}C%@Zl&;1uknaX zTcK-~-zz*EkT0KEZht6DEm;*@pMGOyeue#pB=GYAF#r_UTBM^$EJi@s{5&LHdXL0~ zBgZRI>>W8?$>u|6rSh*oD&6LqyMs5?cV9xKg0t(pcK}RqYPdVgXnYENlWLil^>)>s z^{{ldFHU9Tn}|M{LYQg>16ML1@i(e6!u;(P^Jk)e;5}W%#JkL0ShcG^>LJVEG)t^E zep!mE@kaNkNsep|SXGW8V^=#7W=A;SGmVw-0jD`$P^JMo`onbOKwn5s0%N{>4fAct zz2k(5JkKWlE#XPRuL-*ee;{~Ce*s}3p_cFs!XtzR!cPhROxQ~3ApD;28}j`nc^Y@? zXUD{e6P**YCb}lNCuUE~nV37#GjY_!yovb}y%P&2jwV+B854aI$4ne+KTbStV&TMb z6UR?HebB#&JPrPvFj4+ZOa(hO{Z7Z*@Bh^6|7Gu8z@nvc8(uYh`6+N#$E8=B22}%&e%Wd~GJE zu#1_Q{61@+GjKpm-+ur9^M9WI@5jTMb@twCuf6u#YhTaaXJ0nr@*dK^cwY02n9pS* zen-T2iMT_=4~cjP^ds#ba15=>^9jDdTHVxTrO!`C-1P$ezEZXRX6gb~-3lZO>x6HA z)MT4Jm|G(&`lp2Rp1@gQPx`tk`9B6<=Gpot?! zf0394G~+>&l_88@!(fTKevoHXHwTJ7r!Zd=z8#T`tn5Q;&;gL+Sp!%Gco}XA<8V%B zAPAuILz1u{Jj*0*iu3=*A01p`hnGa=A;1Kb-g%$JLPr0O@3%kvY|r=G+0nzZzkn~4 zoi=_KhJ3Zus0LG$qwZcDjcd7SU|knZzngxcM=OVhhF#=m-WO3rw-;@~zE^o2w~?WE znTSI@QRMMbK<$l@%&Rs#s_wSai=*qTaw&(6u((ZO@Bs&gz(K&Fo^X1oogL|kVh=Y) z)y`uK6uk^w_DwNDWQGt~z@ZG+W=Gk@9f%2jm-OcHv6$BXzfR^|_M#2(F1c zlC&EOoNXBVH>7pWXh>_RyRB17G_xgrUvdj0+CfCgUPnV(6K->s5~VfG*q7YIi0%WC zwElU*Nu%tx)Oa+vWx{2qBjACR9~Lru^PV-p5-f+&};Z$Jc@ zn%!Zz;(-Qx-p~xx+d~6V1PBzzaIwQi?|>A60>vJpI6WXmkU;S`T@Ha2ZK<{}f2Ub$ zMpi?aY*s^MNW_ki*O5Q2ra7W!7TIfaL0!noUOCXCg+^N*jwXF>+O`VD9b%)261 z)!>09rR~oXnn=| zJnrc#sMZB^SmIyZ0J4I*L6E9q2v#f8z4sxoV~qRCg6g3GCqhD9VT%KV{&U5e?(UZY zybI9*d*8+S5;9%jX~l9xXo2xkcjBwGa4-ZD-jFQ{mxbv^Y6La4%mT*v@7%lGZveyg z29p5|!QT9-;gGmsZdi+CshtQ3a0h!IL^i+~WlNKjF7L7icKTUHejY6qF=cWS4HFAI z^FxKH#8-=&2lx>?vW8>SNW=Mv9g`yq zHqqD};TWTY(?}iR(Fmt;Il?b5*hGVHgvV^$j|ULZxEn-xS-A&K9_=CgHoVGVZ3NM1 z+>OiHaSep|eHSY3@-`MOW_)HNWrvPtN>p0hHxFe+{)Lz2C8~ z3dg~TEk2)utp=1#Ls&X3f_kxe;QbuTGO^Am$B$c4;7K|xoA3JxZzc*nnTG@C`q|S&;~M;IGT_I1H(p{Da#d)@W5{_sbHXw=DactSga&Y% zV#%4?6FQ!p>CB1Gqiu>K=Oj3*_e58}*S(1+w+}U(ZD62`ZKQOeE4on@_K7Q5=swwv zlqlUO8&1jLQdv(FC4|dnH&O~Lgm|+MVu}z?I0=q~=C3+{8?OUA^2Gt&2c^2Bf)e`A zu%~+Z&ly=~-yXv_fy+ccmyPX0^%;iCTw<_0q`Q^*;HdY$U`iFm!F2>PKlUl);E20k zLB+ys<#Y|kC_OYdcu?~!0>DNCHoo=rjNA68n?|GX`P>KY>*MSbcTlU$DAVkgAMWg$%@sn&lp;#?AT*Ry68_ zRBMP8eIDmCOI4%uEFDCZU$O1+8_RS6n?x%kTf{sk=5zNT)Ouycx|LgRY0W&G2qu@u;SWRO#LZcvbJQAUhD<6}6FSALQZ!iA5O;49ie`=Di>Giq>%>Mb4Vl zlgKpU$eLZ&7)#q;y46O~?q;Fg4N0fA*QQO%(H zIf1<2JdBIMl42vVc8HKp@{(iFf-B>^cn-upj}(!vom$zku^`AVV?9*#sFy? z0;!k=#X=fQK)6&pH8v6#71kdCp$pfP$#Gp_BwbgCE6L&zkCLL==>5;V?3yyaA2l`I zQ9EI$Aan_Ll;Lic)q>*s+|WhJ#SL9Wk;pYhcRl5i_kyH6XwA2`JV->b)n&K)w!-YmLZ=m|OA?wE~(rzdpokck%HLc73BOwh*z4Q8B0l{aO-w81xD8VYn+0*Tc2q z3oiz+p<8E(h_vRtd3tv@E)?&ptNCzKwxKEe#e$}AeIXeF6`^%?u{=8 za*BMg z-VoPUu~fptK~)=0ZEtpVNsqM zcJ@7g@%t20Bc9(49f6cW;J}{a3{dL;ga>*rFMhUkBwivlf&?Rutw4RZW{F!$nx8<( zg8;$<@gkEDh)CR@S6f+EO?Uk@;6s%UG|lk5hbxh~qiWEyc;vX&vu18UnEPdX9h1XH z>7s}lLkKP&mGo?OceCLwg~Jxn{)=ov(Na@#5vwrW>E1}aHPN6(4Mal=>#YAK8kqDz zG^2@zI&{V-U_ct&Pua~n>A&FfDQMU|hio8pw!E*=TC#u8EJp+Bh|cOhNEb$JKnP|@ zz4Lxn9(YOZ{pJJ~`TWK5es@&QHHJd5xNpqz7l$;E6^A_w#gN?X@SGJgmI{Ckxm=?$ zuYvl{CUV87nuOze7?xow;UA9GX{pru7R^}+?CD!9XN7O>TO?{P43a2pV?6iJbtqB4{FIP3O&;!vHFYNqh2-? zlmB|UGphP_4d)u_nXVzrki#52VR{B6bw|`^@l~e+T;{4%fi9i7Y55S(Vee4C;P10|5d3`_))7b=qBC)PXAJ@=J?uOCTwrZzkR#vG~7 zL7JoF@4?bF(lmMAuldYb1pp}T7{)UF;GnZ)k2|`msx^X0H9)h(jVfcXAq-igv`_YKE1xH% zeyl*)=>CPc(S1HG?+u#cyBj;kJl$zvlK^l4&=2(4w@T&HcaJ;v*jI(!FQ^2_^WJ>V zzB#@1e>PY!ck zg5Mb~IerJbLhw5U^9Wqs@KT^R4}0Bky{2HzG?^fy!Pab{6lOve&&N5wKk?q)^Rc=q z$M-Xyz#rv3%kw+kw;s4G82A{)`~WvL_ysPDs-GHYnil8^zaC7N zy*PgkO9IX3KBPqXL;BTL5|?uu8)weMM61BueCAFD zjmj`}3VA6A*$(y=LydF9fi;X1W9!KDtnOAaLt-zk*WC9^&tw7z@q6ZSZ%JRTe^o=I}tpE_dSWD7#Lx@qyqPiThch_?bWD7;D?;EG_D z5C4y<37?+Xigj|1JFzR&75Vs0cz(Q$e#+^`fuEWKD$^iAKJ zjPy^ZFsaK>e^zCs*z)BwBC0*o(by8t5i!B6cO52`B6xQ&2aOq^)J%wIfO1Ihat%F|%>fr-LvD+&~0p znpmzZit>F^@q++X5^<7>~Ip}RI85blNU%dcmUbS{2<2^hb(`|yLlBX%T*j_tl3U!ED163$h1 zcgN#q^?F$-t8?cJpBaWNRNDe*zlq zCP5}HK{>pMLun}~Oxm3iKTm=z%i|7ZV^(oo%d#~T<70J`F-a9RAKxw#TZn<_*|7XC z=y8X#pS@)8&6L{9nq^bq--o`hj{DK0zhUn?UaXo`;|O)nt&c8^7u1!7Qu>$BvAy~DS{21Y z1AO}&-{pu&g9xD%Jqe*(WUj%DEd2x-4nGIs!dOi*OZSxke4T@0KJ?p}SBYZ&g#87c zUD5)Zkx@TtmSH3rJl+G%$6}aaBpEjxS7HT_UZ1d-6ZU&1ht^G#ZIQWi>PI1!h#fK^ zk>{}w{T-~;;v+Ydl;_lMUm_FcedR-gcEcMVA|UUMSWt;1D^F2Q+=Kl=gM(Ue{U1?z ztsmh{*5uH5*W`#dhF0$i5)Q`iF8HurctMCgl?8*@PFBHPuxce+@w>F<-u|ysqv-us zl`RPG5~hWDF~j0==FDzBkq|0#4eg#Ha}S2yd;g?Sv{WCnuxfvDabUysfqf@rJryp-v9JvNj5 zX0zY9>~{hC&1b)b?6;Wxmf;u8M|V^$9;h#**Djv@-NTy~%Nn1066^8NXdlt_rr}-u zt)QuPp5{6(#h@7%0c?_oqRjq{(#-Nsfr4jmBoB;`+pE(~ce5y!h~lL$s$newb#b1r z0(9o^XbvV8_;a%_072bj^RZ&qJvN*Drm){6{IVEmhXOG|a*fR@EQ2@=%TIUf7KhF9 z#-STxZPcJF@4Jv-wrB7Bj!5r%j8z2hS>9KeH%2-bjC7BscQlJ53mZRyKm~~0t#x3C zgW3)WyARhTAI0VI?yzomXm^wxq_aEn7l(SaAe>EE7N{9rw>A|K>9M^bxgA58qYlLK zXgS8n;r#Lxk~kCK=%BLnXaXBm^j+$y|fM!EfCOg;uBNFLonodr+9j%50fHT9+K=VB{Uc%+0P#3+dwF?x;{O zSxnzEJPhmjwqww~Y_@S;m^&27M9Gk#abya7T``4(ykC=okx+QI8*^AH zX7cW4S!W;h`b%-yD3gg>eG7C11IV8(%C9;6y$@@aRdL(~iG1RcnM-C^8fdEpVN4_PQA z&+nd}Jo7>kh`K}p$TW(}l;SQ}!JL=nkyqUXjUC5b0_r#4yk*;}{ zD|A*?MmN4Ld$jttqa2Reg9bj{d$6?to}`j0(JKxmL3C#V+_5kR#Vkh#Yh}kWURFHcT@v|cwk%F!i5^@RYgLtez{f-fydu}A#kF*g z<&bShezz8xqL%<+6Y^ujFte!}@9_#_`?t_6oEG0zHYEQdydi0p&M;647@y7%5?t9i z9;L8p{9vd&JeGc=6!beXhJLlt^lOd8Z^7!Qc!t6?42_gC6dcCT*ieS9l>x24C)fbw zN#-`iF)Z7}12-gxZnBVjRXe))eZiHe?(`Y&jTE>k4lXDIzk_95)4t$X7An5~satgf zQ8vbqU94)uV|SE-+MzNKEe`MwCtWW_eUE`>A#RM9!yfTiZ6yK@gTess56I>0LgJ0q z3}INolLH-SM&rzV3S&F~g|a3$OkJ8lY5ADq>Y6dH}1Kf-fcm?tI7{CoLePj+a~C+0uO zFG{R#8gD*a?!{sTR=lLcH$k4oXA0v{)`IRgqR=>pWZ6NPd=d)p(JnL(of8q(^EtWq z8Wg3l&XMU!4!xHA972eLg@i(7CQp1UzMS`4D?Z{X7MLfkw~U14Y1Rs<53V$#xocuM zr$$I5#~H4(B6N?9VV0v{zp?ChJbsyuSbH?Q+Dff0=N`;DuvpX^wAa)i2{fJ9ga8Am zcAjK4C}Y-}(~iZzj!hih7?8WdS2eo^|JJ&RYHx=#t0DO$>Yf2S@TCd08=a4a_+gyK zi#U#9XbN=Wi7xpUb#j-w%lw;r&>PdixkJ9{XR1fx!>-3ivfJfDy3kO8`)`Nqw3N#H zoH+-Y(N@N>yzuN-!+s6y*TQ}a*>5p^TR>aJTrTEnX`w;nSQRJp9^z|UTcIsCWrdgeTJnRKlw?JuO{+FScEURA9+g;T|4OViBA3*=tlbK zP)fegPbB<)0iA{DEJXJ!7Nn)gx1cKcjvSHDQ~F^{)mhs{dQlLG=3Z6Po?;c6hEkc{7zr?N{O_jpBSP(O4J`=#k`Mx8j?GG(f#Q= z@s^`e{yFHM=uZ#*SNl@B$EHY4fYNBBI2MX?lQfQp8EX=(2QA)z`|P(F;-5|YYl;7` ze*CMOLVYu5V;$E|P8NAJk#8sRud!y@n`OWJJEih>A;QU@5TTtSydaH$g%jVpED3Y6 zpBADG`vSD9q_mU@*;^r21Yq~oO)}r-|B)00MZK4z##7X(EGpTvfzfvn{j*Yf%62Z% zyNLdBfnJ))BnoVyz(28`%`(|X$Kc(D34D)YD4%kQ!+nW32PjTY*b#*Nfx)7?9t= zF7PWRejb5egS*vtq!{f*!+7*YzIWqbDh;vJF;Ok)v9deJ%TuqwFLJpWT&kPUc9KQh zPAs<(O9NPvz14!B$KB;qWJ>Igj5?D@j}mFPkUH6$P#=3z@;AxjiB|p}LAKKgBm4DBS|mo!?4{)N8uXg_QE*-#777830$DXqW!n?fDlL;pb2Mapi9c6j#* zj!xg*#3|Y9yHmvfkaA|_Pn@?C=LrJm2KOOf64Qfrg!D`Kg?#h^vD(@CXG2<5k8lQwaHtoM zS`d!Mqc3lfAk-s80=^%3Am!Zxe+ak#Y~iTFK{$Jla9R@1@ePFg0oC4Lo@hUML)a{bwlEfcb0V|9h2peQ98Hhpe)$o5=E$`lJb%zr2||70!Y6`3US_V0{t`2#`Yp zRFMGD5WusFHLg8f%oF51(~wr%Q>sGBtUYX?_SP>2YoD*Z3M@$TeH-LIzM}?NCN#)D zz|pve68sn12%#8yeg`s%BT#j-UvF$Y{0y<^A{P1mSTwlT_{M(-lTU8*HGNKayRVVq zoxW{^)7JUMzeoP-eH)nnI)_*P6%wG3p<>9LETql%4-qe8c)PE}A0yZwqwQURSEfjr zD&i!DJAD?05BW3inS`k-?xKhMrA}$p10ug76 z*dgK+5yy+zAYxv`<3+3xaWum_eR778mw$aJ=H(1#HVw%;eJ2>+?)!mZP^|J(w22{y zMBKvgR^J}r9+O!OGq3c*WTL-?$tcl`_1GI$v)TNK@EVG{su(8iTg4u!EAZXS9$oZU z${vqmQOx00Vsu-AGAw(jLIJ{rOnpsLlMv+aC zCbCF7edCxH&*;AUnu)iDad_4rNyaD^P^8~6y>3X}>N`$&)h~?hWg$`w<3RP3rSv|d ztn%$+xW)G-i?Nx-s1{<-imt;u*&pLkM!CoL0K;Bi1H)?^-b{h~Rz`lQK<@RGh~x!+ zvOi&|NZRYmBp-LJZ!2pLy}l$y;q_TWtPyb>!+U(OqC19RB>0lRsl|7Z7!v3YdB~qe z*TNXf_EFuZR%gZVH9*X`U+L_+yEuK|PP$3(lU>`kK{RBDBG&EGAxxTL~ zB$j8@p3{BgAt&VN!fS>edA2Zz(8cdWxL=+%@b^t6dE8CDLRM`$MPyIIhLVJ#{5$>NmPJ*Mc zom6=m?GowF_j>giY5B5GZ+YbuX^(6ZogDQRZSU?bEPEYm@1sx>v->R9ws>zrV_R57 zq1@S_EiK*=`w+f{!rQ^LUu=ZmGV@IL-e3+1v2Sd7JFu-=a^kpi`-4HSJNi_SKp zHq_R__GUD!sR2rFsJ%mQRWVn}tuq=NmFW#B#SMvnQ(_Y*E`}hAR4cvGtfV&y62CxqB3gB(P z7l2cM=syCuI6w+uA)p*k3wR8$7~%A{uq%LD4>$}6J08Gg10Dpl1IGOnz!d|w0=fXI zpTPt09AH1-YruG1y0i`ODS-PmfEx{10N4Qdn%ua&^Jc)qfOdcacgmyyUIcUkMj_p{ z9|O220T#f)ACNv^KEMVT1qcO{fq(1wg3PB+Le}2{xJv*gKoTGwa3dfeP!6~Qa5rE* z;Ay~4z(K$A5QpC9(tFMHE@x@EVyUyDB6pEfQQ<0g<}Ou~mO0CFT}7oOxy2K~1HMHiixjTXQbloT$s(?( zWLa);Q9exNJaKD|7&UYwvG5ept$-heC!`6v&&XZo%y8wpoZ#ut+tS>!>nfZsOQuax1$m0RHp|2XOJU(M~oVd{Y5sfVBV)+xN!=y(~)(`Djr7 z;NutF8Wucsb;Ph?YlmMPc~4a6rME@@c-g!Wdt)Yy@?7z)!aDlyF`vd>F)rt-hsM8q z^{H#Fj7zxo#)(U=TgISqQ85*5-xb8o?=k+%kt}%XUyu+k0zhX|byk)UjpR-2V zZnC{)8)~0sud%;i|IprP|HID3{{j3V+%@nYYJUqfk+$coHtSoKM9V8?h4~KCr^aiH zHyNJS|3^1mr_*L=7O7pT70PA&lIw1qm~ictai^|%_v(kn=UjEgxKCs69%CK-t-^D~ zgi(8A=8gFAvfH9VFTE$~;>fkbhYedD5j^zPu;Uly5B_LSa>&cFF+umi7)#E4e)@(# zUjKc<$@M29ey#cWkK?YcAAczR{`-!bzB}oy{&v{0O-D`NeDsyO{jx8cKQC_^_t{sU zY&^2)WA)*XkG}ly&4W*V@IY(*`**#!`rU_Go_*)-w|_V=;=qjk_v|~ocii58yw$#E z>Yg{6&CR=ar|<6EbQk!XA%E{#=oIGRJ6vbFxRavMoDac|nN()@+PFN(K z)18ZoDqxi9xl8?CTuN>+1#ua!QZh4cN{Op{R&EjV%StTHEm_j*lT@^fF&)brDhsb; zza0D$%9o01-Bj+PrwZWlEcj|Jp*$}$w?qifb>)`8UsGA=_gAq1@>dA~abhqxsmz_> zWZb~7JkL6Z@tYT?$ggnqI+o{^xU6F<3*!_8MU~Ec>)5 z79Y~Z^-fn}QEA1bLTBER3inbjaZy4+K~ag*&+y!GF|kMlZu-K-eIlJNPMo5&prAsK zKe5O)v&4~`w**=`cf6vKf>OUm&|ciA*Uv1ORJycmR(Y;iF6W9%^7YbZ_0Xrd3kn1t zLb;`<_T}hz`(q>(6%-g2lCYDDieX>=l>7Tj>6JQ31SFGD>MqGoEXt*=o$NWOyl9!T zd`bySQQ}T3&3E>3=N6Sn-B}qcO7bXQEY76D+>#P!@uXsBZaMtYit>wYaIR2IE_dG4 zLo=%o4LDNb#W;SqvY%Vk&#ms~)_}je*j1ERT1sZSbYYplP~sFzA+=DXsBh)@{>nGW zUEwNSN;Oc>GkQlWtGj;r1s$+FO)n@oE1%O##Js~$r@EJxrJ{CIzGhClVcPUr(>OX~ zy_VXH)xG^ois)`#iN39hlgBAIt{BQGgVx#*)>MN&t`=dd(3Utd*qC6Fh{t~<@N(S4 z$$9W}OoIJ@A_JYOOAIT!my zJzGKa>C@90PRI~&Y7b6@f7oH9{}9FkfU1W%c{aHrhx{?P*K_h~uEGB79LSWEo`__) zj7$MfOTL~1XAWFBa0H}s)3QK^twq;o0t2qcb7}_1rC<+o7V?#aX9qgpG`J_hJqhk< zph=zqzpQCo;*?2T+Vm`LdU`rHDQz0S!DS*aGb58r&zQtzBu?TIk_eLEPUJFXCUVIn z!?YxlFCzu=5hg)_$w~4i5r& Q^TnW>d45T2Hrz#fPe&pm$3Ju{WY3Nwj@VZlwd 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