From 6ef78525c5ac989d29e123c0297cfd820fee7e82 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 30 Apr 2014 05:05:04 +0200 Subject: [PATCH] Update Mednafen GBA core to 0.9.33.3 --- Makefile | 3 +- libretro.cpp | 4 +- mednafen/{gba => gba-0926}/GBA.cpp | 0 mednafen/{gba => gba-0926}/GBA.h | 0 mednafen/{gba => gba-0926}/GBAinline.cpp | 0 mednafen/{gba => gba-0926}/GBAinline.h | 0 mednafen/{gba => gba-0926}/Gfx.cpp | 0 mednafen/{gba => gba-0926}/Gfx.h | 0 mednafen/{gba => gba-0926}/Globals.cpp | 0 mednafen/{gba => gba-0926}/Globals.h | 0 mednafen/{gba => gba-0926}/Makefile.am | 0 mednafen/{gba => gba-0926}/Makefile.in | 0 mednafen/{gba => gba-0926}/Mode0.cpp | 0 mednafen/{gba => gba-0926}/Mode1.cpp | 0 mednafen/{gba => gba-0926}/Mode2.cpp | 0 mednafen/{gba => gba-0926}/Mode3.cpp | 0 mednafen/{gba => gba-0926}/Mode4.cpp | 0 mednafen/{gba => gba-0926}/Mode5.cpp | 0 mednafen/{gba => gba-0926}/Port.h | 0 mednafen/{gba => gba-0926}/RTC.cpp | 0 mednafen/{gba => gba-0926}/RTC.h | 0 mednafen/{gba => gba-0926}/Sound.cpp | 0 mednafen/{gba => gba-0926}/Sound.h | 0 mednafen/{gba => gba-0926}/arm.cpp | 0 mednafen/{gba => gba-0926}/arm.h | 0 mednafen/{gba => gba-0926}/bios.cpp | 0 mednafen/{gba => gba-0926}/bios.h | 0 mednafen/{gba => gba-0926}/eeprom.cpp | 0 mednafen/{gba => gba-0926}/eeprom.h | 0 mednafen/{gba => gba-0926}/flash.cpp | 0 mednafen/{gba => gba-0926}/flash.h | 0 mednafen/{gba => gba-0926}/gfx-draw.h | 0 mednafen/{gba => gba-0926}/myrom.h | 0 mednafen/{gba => gba-0926}/sram.cpp | 0 mednafen/{gba => gba-0926}/sram.h | 0 mednafen/{gba => gba-0926}/thumb.cpp | 0 mednafen/{gba => gba-0926}/thumb.h | 0 mednafen/gba-09333/GBA.cpp | 3435 ++++++++++ mednafen/gba-09333/GBA.h | 155 + mednafen/gba-09333/GBAinline.cpp | 285 + mednafen/gba-09333/GBAinline.h | 315 + mednafen/gba-09333/Gfx.cpp | 1409 ++++ mednafen/gba-09333/Gfx.h | 85 + mednafen/gba-09333/Globals.cpp | 110 + mednafen/gba-09333/Globals.h | 132 + mednafen/gba-09333/Makefile | 644 ++ mednafen/gba-09333/Makefile.am | 6 + mednafen/gba-09333/Makefile.in | 644 ++ mednafen/gba-09333/Mode0.cpp | 558 ++ mednafen/gba-09333/Mode1.cpp | 519 ++ mednafen/gba-09333/Mode2.cpp | 484 ++ mednafen/gba-09333/Mode3.cpp | 411 ++ mednafen/gba-09333/Mode4.cpp | 407 ++ mednafen/gba-09333/Mode5.cpp | 411 ++ mednafen/gba-09333/Port.h | 31 + mednafen/gba-09333/RTC.cpp | 229 + mednafen/gba-09333/RTC.h | 62 + mednafen/gba-09333/Sound.cpp | 451 ++ mednafen/gba-09333/Sound.h | 69 + mednafen/gba-09333/arm.cpp | 7952 ++++++++++++++++++++++ mednafen/gba-09333/arm.h | 6 + mednafen/gba-09333/bios.cpp | 1165 ++++ mednafen/gba-09333/bios.h | 52 + mednafen/gba-09333/eeprom.cpp | 223 + mednafen/gba-09333/eeprom.h | 46 + mednafen/gba-09333/flash.cpp | 229 + mednafen/gba-09333/flash.h | 43 + mednafen/gba-09333/gfx-draw.h | 233 + mednafen/gba-09333/myrom.h | 174 + mednafen/gba-09333/sram.cpp | 37 + mednafen/gba-09333/sram.h | 31 + mednafen/gba-09333/thumb.cpp | 2115 ++++++ mednafen/gba-09333/thumb.h | 6 + mednafen/mednafen.h | 4 + mednafen/psx-09333/psx.h | 10 +- 75 files changed, 23175 insertions(+), 10 deletions(-) rename mednafen/{gba => gba-0926}/GBA.cpp (100%) rename mednafen/{gba => gba-0926}/GBA.h (100%) rename mednafen/{gba => gba-0926}/GBAinline.cpp (100%) rename mednafen/{gba => gba-0926}/GBAinline.h (100%) rename mednafen/{gba => gba-0926}/Gfx.cpp (100%) rename mednafen/{gba => gba-0926}/Gfx.h (100%) rename mednafen/{gba => gba-0926}/Globals.cpp (100%) rename mednafen/{gba => gba-0926}/Globals.h (100%) rename mednafen/{gba => gba-0926}/Makefile.am (100%) rename mednafen/{gba => gba-0926}/Makefile.in (100%) rename mednafen/{gba => gba-0926}/Mode0.cpp (100%) rename mednafen/{gba => gba-0926}/Mode1.cpp (100%) rename mednafen/{gba => gba-0926}/Mode2.cpp (100%) rename mednafen/{gba => gba-0926}/Mode3.cpp (100%) rename mednafen/{gba => gba-0926}/Mode4.cpp (100%) rename mednafen/{gba => gba-0926}/Mode5.cpp (100%) rename mednafen/{gba => gba-0926}/Port.h (100%) rename mednafen/{gba => gba-0926}/RTC.cpp (100%) rename mednafen/{gba => gba-0926}/RTC.h (100%) rename mednafen/{gba => gba-0926}/Sound.cpp (100%) rename mednafen/{gba => gba-0926}/Sound.h (100%) rename mednafen/{gba => gba-0926}/arm.cpp (100%) rename mednafen/{gba => gba-0926}/arm.h (100%) rename mednafen/{gba => gba-0926}/bios.cpp (100%) rename mednafen/{gba => gba-0926}/bios.h (100%) rename mednafen/{gba => gba-0926}/eeprom.cpp (100%) rename mednafen/{gba => gba-0926}/eeprom.h (100%) rename mednafen/{gba => gba-0926}/flash.cpp (100%) rename mednafen/{gba => gba-0926}/flash.h (100%) rename mednafen/{gba => gba-0926}/gfx-draw.h (100%) rename mednafen/{gba => gba-0926}/myrom.h (100%) rename mednafen/{gba => gba-0926}/sram.cpp (100%) rename mednafen/{gba => gba-0926}/sram.h (100%) rename mednafen/{gba => gba-0926}/thumb.cpp (100%) rename mednafen/{gba => gba-0926}/thumb.h (100%) create mode 100644 mednafen/gba-09333/GBA.cpp create mode 100644 mednafen/gba-09333/GBA.h create mode 100644 mednafen/gba-09333/GBAinline.cpp create mode 100644 mednafen/gba-09333/GBAinline.h create mode 100644 mednafen/gba-09333/Gfx.cpp create mode 100644 mednafen/gba-09333/Gfx.h create mode 100644 mednafen/gba-09333/Globals.cpp create mode 100644 mednafen/gba-09333/Globals.h create mode 100644 mednafen/gba-09333/Makefile create mode 100644 mednafen/gba-09333/Makefile.am create mode 100644 mednafen/gba-09333/Makefile.in create mode 100644 mednafen/gba-09333/Mode0.cpp create mode 100644 mednafen/gba-09333/Mode1.cpp create mode 100644 mednafen/gba-09333/Mode2.cpp create mode 100644 mednafen/gba-09333/Mode3.cpp create mode 100644 mednafen/gba-09333/Mode4.cpp create mode 100644 mednafen/gba-09333/Mode5.cpp create mode 100644 mednafen/gba-09333/Port.h create mode 100644 mednafen/gba-09333/RTC.cpp create mode 100644 mednafen/gba-09333/RTC.h create mode 100644 mednafen/gba-09333/Sound.cpp create mode 100644 mednafen/gba-09333/Sound.h create mode 100644 mednafen/gba-09333/arm.cpp create mode 100644 mednafen/gba-09333/arm.h create mode 100644 mednafen/gba-09333/bios.cpp create mode 100644 mednafen/gba-09333/bios.h create mode 100644 mednafen/gba-09333/eeprom.cpp create mode 100644 mednafen/gba-09333/eeprom.h create mode 100644 mednafen/gba-09333/flash.cpp create mode 100644 mednafen/gba-09333/flash.h create mode 100644 mednafen/gba-09333/gfx-draw.h create mode 100644 mednafen/gba-09333/myrom.h create mode 100644 mednafen/gba-09333/sram.cpp create mode 100644 mednafen/gba-09333/sram.h create mode 100644 mednafen/gba-09333/thumb.cpp create mode 100644 mednafen/gba-09333/thumb.h diff --git a/Makefile b/Makefile index 1060f68..431d1dc 100644 --- a/Makefile +++ b/Makefile @@ -192,8 +192,9 @@ else ifeq ($(core), gba) NEED_BLIP = 1 NEED_STEREO_SOUND = 1 NEED_CRC32 = 1 + WANT_NEW_API = 1 CORE_DEFINE := -DWANT_GBA_EMU - CORE_DIR := $(MEDNAFEN_DIR)/gba + CORE_DIR := $(MEDNAFEN_DIR)/gba-09333 CORE_SOURCES := $(CORE_DIR)/arm.cpp \ $(CORE_DIR)/bios.cpp \ diff --git a/libretro.cpp b/libretro.cpp index 5333481..fc124f6 100755 --- a/libretro.cpp +++ b/libretro.cpp @@ -137,8 +137,8 @@ static bool is_pal = false; #elif defined(WANT_GBA_EMU) #define MEDNAFEN_CORE_NAME_MODULE "gba" #define MEDNAFEN_CORE_NAME "Mednafen VBA-M" -#define MEDNAFEN_CORE_VERSION "v0.9.26" -#define MEDNAFEN_CORE_EXTENSIONS "gba" +#define MEDNAFEN_CORE_VERSION "v0.9.33.3" +#define MEDNAFEN_CORE_EXTENSIONS "gba|agb|bin" #define MEDNAFEN_CORE_TIMING_FPS 59.73 #define MEDNAFEN_CORE_GEOMETRY_BASE_W (game->nominal_width) #define MEDNAFEN_CORE_GEOMETRY_BASE_H (game->nominal_height) diff --git a/mednafen/gba/GBA.cpp b/mednafen/gba-0926/GBA.cpp similarity index 100% rename from mednafen/gba/GBA.cpp rename to mednafen/gba-0926/GBA.cpp diff --git a/mednafen/gba/GBA.h b/mednafen/gba-0926/GBA.h similarity index 100% rename from mednafen/gba/GBA.h rename to mednafen/gba-0926/GBA.h diff --git a/mednafen/gba/GBAinline.cpp b/mednafen/gba-0926/GBAinline.cpp similarity index 100% rename from mednafen/gba/GBAinline.cpp rename to mednafen/gba-0926/GBAinline.cpp diff --git a/mednafen/gba/GBAinline.h b/mednafen/gba-0926/GBAinline.h similarity index 100% rename from mednafen/gba/GBAinline.h rename to mednafen/gba-0926/GBAinline.h diff --git a/mednafen/gba/Gfx.cpp b/mednafen/gba-0926/Gfx.cpp similarity index 100% rename from mednafen/gba/Gfx.cpp rename to mednafen/gba-0926/Gfx.cpp diff --git a/mednafen/gba/Gfx.h b/mednafen/gba-0926/Gfx.h similarity index 100% rename from mednafen/gba/Gfx.h rename to mednafen/gba-0926/Gfx.h diff --git a/mednafen/gba/Globals.cpp b/mednafen/gba-0926/Globals.cpp similarity index 100% rename from mednafen/gba/Globals.cpp rename to mednafen/gba-0926/Globals.cpp diff --git a/mednafen/gba/Globals.h b/mednafen/gba-0926/Globals.h similarity index 100% rename from mednafen/gba/Globals.h rename to mednafen/gba-0926/Globals.h diff --git a/mednafen/gba/Makefile.am b/mednafen/gba-0926/Makefile.am similarity index 100% rename from mednafen/gba/Makefile.am rename to mednafen/gba-0926/Makefile.am diff --git a/mednafen/gba/Makefile.in b/mednafen/gba-0926/Makefile.in similarity index 100% rename from mednafen/gba/Makefile.in rename to mednafen/gba-0926/Makefile.in diff --git a/mednafen/gba/Mode0.cpp b/mednafen/gba-0926/Mode0.cpp similarity index 100% rename from mednafen/gba/Mode0.cpp rename to mednafen/gba-0926/Mode0.cpp diff --git a/mednafen/gba/Mode1.cpp b/mednafen/gba-0926/Mode1.cpp similarity index 100% rename from mednafen/gba/Mode1.cpp rename to mednafen/gba-0926/Mode1.cpp diff --git a/mednafen/gba/Mode2.cpp b/mednafen/gba-0926/Mode2.cpp similarity index 100% rename from mednafen/gba/Mode2.cpp rename to mednafen/gba-0926/Mode2.cpp diff --git a/mednafen/gba/Mode3.cpp b/mednafen/gba-0926/Mode3.cpp similarity index 100% rename from mednafen/gba/Mode3.cpp rename to mednafen/gba-0926/Mode3.cpp diff --git a/mednafen/gba/Mode4.cpp b/mednafen/gba-0926/Mode4.cpp similarity index 100% rename from mednafen/gba/Mode4.cpp rename to mednafen/gba-0926/Mode4.cpp diff --git a/mednafen/gba/Mode5.cpp b/mednafen/gba-0926/Mode5.cpp similarity index 100% rename from mednafen/gba/Mode5.cpp rename to mednafen/gba-0926/Mode5.cpp diff --git a/mednafen/gba/Port.h b/mednafen/gba-0926/Port.h similarity index 100% rename from mednafen/gba/Port.h rename to mednafen/gba-0926/Port.h diff --git a/mednafen/gba/RTC.cpp b/mednafen/gba-0926/RTC.cpp similarity index 100% rename from mednafen/gba/RTC.cpp rename to mednafen/gba-0926/RTC.cpp diff --git a/mednafen/gba/RTC.h b/mednafen/gba-0926/RTC.h similarity index 100% rename from mednafen/gba/RTC.h rename to mednafen/gba-0926/RTC.h diff --git a/mednafen/gba/Sound.cpp b/mednafen/gba-0926/Sound.cpp similarity index 100% rename from mednafen/gba/Sound.cpp rename to mednafen/gba-0926/Sound.cpp diff --git a/mednafen/gba/Sound.h b/mednafen/gba-0926/Sound.h similarity index 100% rename from mednafen/gba/Sound.h rename to mednafen/gba-0926/Sound.h diff --git a/mednafen/gba/arm.cpp b/mednafen/gba-0926/arm.cpp similarity index 100% rename from mednafen/gba/arm.cpp rename to mednafen/gba-0926/arm.cpp diff --git a/mednafen/gba/arm.h b/mednafen/gba-0926/arm.h similarity index 100% rename from mednafen/gba/arm.h rename to mednafen/gba-0926/arm.h diff --git a/mednafen/gba/bios.cpp b/mednafen/gba-0926/bios.cpp similarity index 100% rename from mednafen/gba/bios.cpp rename to mednafen/gba-0926/bios.cpp diff --git a/mednafen/gba/bios.h b/mednafen/gba-0926/bios.h similarity index 100% rename from mednafen/gba/bios.h rename to mednafen/gba-0926/bios.h diff --git a/mednafen/gba/eeprom.cpp b/mednafen/gba-0926/eeprom.cpp similarity index 100% rename from mednafen/gba/eeprom.cpp rename to mednafen/gba-0926/eeprom.cpp diff --git a/mednafen/gba/eeprom.h b/mednafen/gba-0926/eeprom.h similarity index 100% rename from mednafen/gba/eeprom.h rename to mednafen/gba-0926/eeprom.h diff --git a/mednafen/gba/flash.cpp b/mednafen/gba-0926/flash.cpp similarity index 100% rename from mednafen/gba/flash.cpp rename to mednafen/gba-0926/flash.cpp diff --git a/mednafen/gba/flash.h b/mednafen/gba-0926/flash.h similarity index 100% rename from mednafen/gba/flash.h rename to mednafen/gba-0926/flash.h diff --git a/mednafen/gba/gfx-draw.h b/mednafen/gba-0926/gfx-draw.h similarity index 100% rename from mednafen/gba/gfx-draw.h rename to mednafen/gba-0926/gfx-draw.h diff --git a/mednafen/gba/myrom.h b/mednafen/gba-0926/myrom.h similarity index 100% rename from mednafen/gba/myrom.h rename to mednafen/gba-0926/myrom.h diff --git a/mednafen/gba/sram.cpp b/mednafen/gba-0926/sram.cpp similarity index 100% rename from mednafen/gba/sram.cpp rename to mednafen/gba-0926/sram.cpp diff --git a/mednafen/gba/sram.h b/mednafen/gba-0926/sram.h similarity index 100% rename from mednafen/gba/sram.h rename to mednafen/gba-0926/sram.h diff --git a/mednafen/gba/thumb.cpp b/mednafen/gba-0926/thumb.cpp similarity index 100% rename from mednafen/gba/thumb.cpp rename to mednafen/gba-0926/thumb.cpp diff --git a/mednafen/gba/thumb.h b/mednafen/gba-0926/thumb.h similarity index 100% rename from mednafen/gba/thumb.h rename to mednafen/gba-0926/thumb.h diff --git a/mednafen/gba-09333/GBA.cpp b/mednafen/gba-09333/GBA.cpp new file mode 100644 index 0000000..cc055f9 --- /dev/null +++ b/mednafen/gba-09333/GBA.cpp @@ -0,0 +1,3435 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "../general.h" +#include "../player.h" +#include "../file.h" +#include "../state.h" +#include "../movie.h" +#include "../mempatcher.h" +#include "../md5.h" +#include "GBAinline.h" +#include "Globals.h" +#include "Gfx.h" +#include "eeprom.h" +#include "flash.h" +#include "Sound.h" +#include "sram.h" +#include "bios.h" +#include "Port.h" + +#include "arm.h" +#include "thumb.h" + +#include +#include +#include +#include +#include + +#include "../FileStream.h" + +#include "../../scrc32.h" + +namespace MDFN_IEN_GBA +{ + +static bool CPUInit(const std::string bios_fn) MDFN_COLD; +static void CPUReset(void) MDFN_COLD; +static void CPUUpdateRender(void); + +#define UPDATE_REG(address, value)\ + {\ + WRITE16LE(((uint16 *)&ioMem[address]),value);\ + }\ + +#ifdef __GNUC__ +#define _stricmp strcasecmp +#endif + +RTC *GBA_RTC = NULL; + +int SWITicks = 0; +int IRQTicks = 0; + +int layerEnableDelay = 0; +bool busPrefetch = false; +bool busPrefetchEnable = false; +uint32 busPrefetchCount = 0; +int cpuDmaTicksToUpdate = 0; +int cpuDmaCount = 0; +bool cpuDmaHack = false; +uint32 cpuDmaLast = 0; +int dummyAddress = 0; + +bool cpuBreakLoop = false; +int cpuNextEvent = 0; + +static bool intState = false; +static bool stopState = false; +static bool holdState = false; +static int holdType = 0; + +static bool FlashSizeSet; // Set to TRUE if explicitly set by the user +bool cpuSramEnabled; +bool cpuFlashEnabled; +bool cpuEEPROMEnabled; +bool cpuEEPROMSensorEnabled; + +uint32 cpuPrefetch[2]; + +int cpuTotalTicks = 0; +static int lcdTicks; +uint8 timerOnOffDelay = 0; + +GBATimer timers[4]; + +uint32 dmaSource[4] = {0}; +uint32 dmaDest[4] = {0}; +void (*renderLine)() = mode0RenderLine; +bool fxOn = false; +bool windowOn = false; + +static const int TIMER_TICKS[4] = +{ + 0, + 6, + 8, + 10 +}; + +const uint32 objTilesAddress [3] = {0x010000, 0x014000, 0x014000}; +const uint8 gamepakRamWaitState[4] = { 4, 3, 2, 8 }; +const uint8 gamepakWaitState[4] = { 4, 3, 2, 8 }; +const uint8 gamepakWaitState0[2] = { 2, 1 }; +const uint8 gamepakWaitState1[2] = { 4, 1 }; +const uint8 gamepakWaitState2[2] = { 8, 1 }; +const bool isInRom [16]= + { false, false, false, false, false, false, false, false, + true, true, true, true, true, true, false, false }; + +uint8 memoryWait[16] = + { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 0 }; +uint8 memoryWait32[16] = + { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 4, 0 }; +uint8 memoryWaitSeq[16] = + { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4, 0 }; +uint8 memoryWaitSeq32[16] = + { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 4, 0 }; + +// The videoMemoryWait constants are used to add some waitstates +// if the opcode access video memory data outside of vblank/hblank +// It seems to happen on only one ticks for each pixel. +// Not used for now (too problematic with current code). +//const uint8 videoMemoryWait[16] = +// {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + +uint8 biosProtected[4]; + +static const uint32 myROM[] = +{ + #include "myrom.h" +}; + +union SysCM +{ + uint32 v32[65536]; + uint16 v16[65536]; +}; +static SysCM* systemColorMap = NULL; +static uint8 *CustomColorMap = NULL; // 32768 * 3 +static int romSize = 0x2000000; + +static INLINE int CPUUpdateTicks() +{ + int cpuLoopTicks = lcdTicks; + + if(timers[0].On && (timers[0].Ticks < cpuLoopTicks)) { + cpuLoopTicks = timers[0].Ticks; + } + if(timers[1].On && !(timers[1].CNT & 4) && (timers[1].Ticks < cpuLoopTicks)) { + cpuLoopTicks = timers[1].Ticks; + } + if(timers[2].On && !(timers[2].CNT & 4) && (timers[2].Ticks < cpuLoopTicks)) { + cpuLoopTicks = timers[2].Ticks; + } + if(timers[3].On && !(timers[3].CNT & 4) && (timers[3].Ticks < cpuLoopTicks)) { + cpuLoopTicks = timers[3].Ticks; + } + + if (SWITicks) { + if (SWITicks < cpuLoopTicks) + cpuLoopTicks = SWITicks; + } + + if (IRQTicks) { + if (IRQTicks < cpuLoopTicks) + cpuLoopTicks = IRQTicks; + } + return cpuLoopTicks; +} + +void CPUUpdateWindow0() +{ + int x00 = WIN0H>>8; + int x01 = WIN0H & 255; + + if(x00 <= x01) { + for(int i = 0; i < 240; i++) { + gfxInWin0[i] = (i >= x00 && i < x01); + } + } else { + for(int i = 0; i < 240; i++) { + gfxInWin0[i] = (i >= x00 || i < x01); + } + } +} + +void CPUUpdateWindow1() +{ + int x00 = WIN1H>>8; + int x01 = WIN1H & 255; + + if(x00 <= x01) { + for(int i = 0; i < 240; i++) { + gfxInWin1[i] = (i >= x00 && i < x01); + } + } else { + for(int i = 0; i < 240; i++) { + gfxInWin1[i] = (i >= x00 || i < x01); + } + } +} + +#define CLEAR_ARRAY(a) \ + {\ + uint32 *array = (a);\ + for(int i = 0; i < 240; i++) {\ + *array++ = 0x80000000;\ + }\ + }\ + +void CPUUpdateRenderBuffers(bool force) +{ + if(!(layerEnable & 0x0100) || force) { + CLEAR_ARRAY(line0); + } + if(!(layerEnable & 0x0200) || force) { + CLEAR_ARRAY(line1); + } + if(!(layerEnable & 0x0400) || force) { + CLEAR_ARRAY(line2); + } + if(!(layerEnable & 0x0800) || force) { + CLEAR_ARRAY(line3); + } +} + +extern SFORMAT eepromSaveData[]; + +static uint16 padbufblah; +static SFORMAT Joy_StateRegs[] = +{ + SFVAR( padbufblah), + SFEND +}; + +static int StateAction(StateMem *sm, int load, int data_only) MDFN_COLD; +static int StateAction(StateMem *sm, int load, int data_only) +{ + int ret = 1; + + SFORMAT StateRegs[] = + { + // Type-cast to uint32* so the macro will work(they really are 32-bit elements, just wrapped up in a union) + SFARRAY32N((uint32 *)reg, sizeof(reg) / sizeof(reg_pair), "reg"), + + SFVAR(busPrefetch), + SFVAR(busPrefetchEnable), + SFVAR(busPrefetchCount), + SFVAR(cpuDmaHack), + SFVAR(cpuDmaLast), + SFVAR(cpuDmaTicksToUpdate), + SFVAR(cpuDmaCount), + SFVAR(stopState), + SFVAR(intState), + SFVAR(DISPCNT), + SFVAR(DISPSTAT), + SFVAR(VCOUNT), + SFVAR(BG0CNT), + SFVAR(BG1CNT), + SFVAR(BG2CNT), + SFVAR(BG3CNT), + + + SFARRAY16(BGHOFS, 4), + SFARRAY16(BGVOFS, 4), + + SFVAR(BG2PA), + SFVAR(BG2PB), + SFVAR(BG2PC), + SFVAR(BG2PD), + SFVAR(BG2X_L), + SFVAR(BG2X_H), + SFVAR(BG2Y_L), + SFVAR(BG2Y_H), + + SFVAR(BG3PA), + SFVAR(BG3PB), + SFVAR(BG3PC), + SFVAR(BG3PD), + SFVAR(BG3X_L), + SFVAR(BG3X_H), + SFVAR(BG3Y_L), + SFVAR(BG3Y_H), + SFVAR(WIN0H), + SFVAR(WIN1H), + SFVAR(WIN0V), + SFVAR(WIN1V), + SFVAR(WININ), + SFVAR(WINOUT), + SFVAR(MOSAIC), + SFVAR(BLDMOD), + SFVAR(COLEV), + SFVAR(COLY), + + SFARRAY16(DMSAD_L, 4), + SFARRAY16(DMSAD_H, 4), + SFARRAY16(DMDAD_L, 4), + SFARRAY16(DMDAD_H, 4), + SFARRAY16(DMCNT_L, 4), + SFARRAY16(DMCNT_H, 4), + + SFVAR(timers[0].D), + SFVAR(timers[0].CNT), + SFVAR(timers[1].D), + SFVAR(timers[1].CNT), + SFVAR(timers[2].D), + SFVAR(timers[2].CNT), + SFVAR(timers[3].D), + SFVAR(timers[3].CNT), + + SFVAR(P1), + SFVAR(IE), + SFVAR(IF), + SFVAR(IME), + + SFVAR(holdState), + SFVAR(holdType), + SFVAR(lcdTicks), + + SFVAR(timers[0].On), + SFVAR(timers[0].Ticks), + SFVAR(timers[0].Reload), + SFVAR(timers[0].ClockReload), + + SFVAR(timers[1].On), + SFVAR(timers[1].Ticks), + SFVAR(timers[1].Reload), + SFVAR(timers[1].ClockReload), + + SFVAR(timers[2].On), + SFVAR(timers[2].Ticks), + SFVAR(timers[2].Reload), + SFVAR(timers[2].ClockReload), + + SFVAR(timers[3].On), + SFVAR(timers[3].Ticks), + SFVAR(timers[3].Reload), + SFVAR(timers[3].ClockReload), + + SFARRAY32(dmaSource, 4), + SFARRAY32(dmaDest, 4), + + SFVAR(fxOn), + SFVAR(windowOn), + + SFVAR(N_FLAG), + SFVAR(C_FLAG), + SFVAR(Z_FLAG), + SFVAR(V_FLAG), + SFVAR(armState), + SFVAR(armIrqEnable), + SFVAR(armNextPC), + SFVAR(armMode), + + SFVAR(cpuSramEnabled), + SFVAR(cpuFlashEnabled), + SFVAR(cpuEEPROMEnabled), + SFVAR(cpuEEPROMSensorEnabled), + + SFEND + }; + + ret &= MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAIN"); + + SFORMAT RAMState[] = + { + SFARRAY(internalRAM, 0x8000), + SFARRAY(paletteRAM, 0x400), + SFARRAY(workRAM, 0x40000), + SFARRAY(vram, 0x20000), + SFARRAY(oam, 0x400), + SFARRAY(ioMem, 0x400), + SFEND + }; + + ret &= MDFNSS_StateAction(sm, load, data_only, RAMState, "RAM"); + + if(cpuEEPROMEnabled) + ret &= MDFNSS_StateAction(sm, load, data_only, eepromSaveData, "EEPR"); + + ret &= GBA_Flash_StateAction(sm, load, data_only); + + if(GBA_RTC) + ret &= GBA_RTC->StateAction(sm, load, data_only); + + ret &= MDFNSS_StateAction(sm, load, data_only, Joy_StateRegs, "JOY"); + ret &= MDFNGBASOUND_StateAction(sm, load, data_only); + + if(load) + { + // set pointers! + layerEnable = layerSettings & DISPCNT; + + CPUUpdateRender(); + CPUUpdateRenderBuffers(true); + CPUUpdateWindow0(); + CPUUpdateWindow1(); + + if(armState) { + ARM_PREFETCH; + } else { + THUMB_PREFETCH; + } + CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204)); + } + return(ret); +} + +static bool CPUWriteBatteryFile(const char *filename) MDFN_COLD; +static bool CPUWriteBatteryFile(const char *filename) +{ + if(cpuSramEnabled || cpuFlashEnabled) + { + if(cpuSramEnabled) + { + if(!MDFN_DumpToFile(filename, 6, flashSaveMemory, 0x10000)) + return(0); + } + else if(cpuFlashEnabled) + { + if(!MDFN_DumpToFile(filename, 6, flashSaveMemory, flashSize)) + return(0); + } + return(TRUE); + } + return(FALSE); +} + +static bool CPUReadBatteryFile(const char *filename) MDFN_COLD; +static bool CPUReadBatteryFile(const char *filename) +{ + FILE *gp = gzopen(filename, "rb"); + long size; + + if(!gp) + return(FALSE); + + size = 0; + while(gzgetc(gp) != EOF) + size++; + + if(size == 512 || size == 0x2000) // Load the file as EEPROM for Mednafen < 0.8.2 + { + gzclose(gp); + + if(cpuEEPROMEnabled) + { + puts("note: Loading sav file as eeprom data"); + GBA_EEPROM_LoadFile(filename); + } + return(FALSE); + } + + gzseek(gp, 0, SEEK_SET); + + if(size == 0x20000) + { + if(gzread(gp, flashSaveMemory, 0x20000) != 0x20000) + { + gzclose(gp); + return(FALSE); + } + if(!FlashSizeSet) + { + flashSetSize(0x20000); + FlashSizeSet = TRUE; + } + } + else + { + if(gzread(gp, flashSaveMemory, 0x10000) != 0x10000) + { + gzclose(gp); + return(FALSE); + } + if(!FlashSizeSet) + { + flashSetSize(0x10000); + FlashSizeSet = TRUE; + } + } + gzclose(gp); + return(TRUE); +} + +static void CPUCleanUp(void) MDFN_COLD; +static void CPUCleanUp(void) +{ + if(rom) + { + MDFN_free(rom); + rom = NULL; + } + + if(vram) + { + MDFN_free(vram); + vram = NULL; + } + + if(paletteRAM) + { + MDFN_free(paletteRAM); + paletteRAM = NULL; + } + + if(internalRAM) + { + MDFN_free(internalRAM); + internalRAM = NULL; + } + + if(workRAM) + { + MDFN_free(workRAM); + workRAM = NULL; + } + + if(bios) + { + MDFN_free(bios); + bios = NULL; + } + + if(pix) + { + MDFN_free(pix); + pix = NULL; + } + + if(oam) + { + MDFN_free(oam); + oam = NULL; + } + + if(ioMem) + { + MDFN_free(ioMem); + ioMem = NULL; + } + + if(systemColorMap) + { + MDFN_free(systemColorMap); + systemColorMap = NULL; + } + + GBA_Flash_Kill(); + + if(GBA_RTC) + { + delete GBA_RTC; + GBA_RTC = NULL; + } +} + +static void CloseGame(void) MDFN_COLD; +static void CloseGame(void) +{ + GBA_EEPROM_SaveFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "eep").c_str()); + CPUWriteBatteryFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str()); + + // Call CPUCleanUp() to deallocate memory AFTER the backup memory is saved. + CPUCleanUp(); +} + +static bool LoadCPalette(const char *syspalname, uint8 **ptr, uint32 num_entries) MDFN_COLD; +static bool LoadCPalette(const char *syspalname, uint8 **ptr, uint32 num_entries) +{ + std::string colormap_fn = MDFN_MakeFName(MDFNMKF_PALETTE, 0, syspalname).c_str(); + + MDFN_printf(_("Loading custom palette from \"%s\"...\n"), colormap_fn.c_str()); + MDFN_indent(1); + + *ptr = NULL; + try + { + FileStream fp(colormap_fn.c_str(), FileStream::MODE_READ); + + if(!(*ptr = (uint8 *)MDFN_malloc(num_entries * 3, _("custom color map")))) + { + MDFN_indent(-1); + return(false); + } + + fp.read(*ptr, num_entries * 3); + } + catch(MDFN_Error &e) + { + if(*ptr) + { + MDFN_free(*ptr); + *ptr = NULL; + } + + MDFN_printf(_("Error: %s\n"), e.what()); + MDFN_indent(-1); + return(e.GetErrno() == ENOENT); // Return fatal error if it's an error other than the file not being found. + } + catch(std::exception &e) + { + if(*ptr) + { + MDFN_free(*ptr); + *ptr = NULL; + } + + MDFN_printf(_("Error: %s\n"), e.what()); + MDFN_indent(-1); + return(false); + } + + MDFN_indent(-1); + + return(true); +} + +static void RedoColorMap(const MDFN_PixelFormat &format) MDFN_COLD; +static void RedoColorMap(const MDFN_PixelFormat &format) +{ + for(int x = 0; x < 65536; x++) + { + int r, g, b; + + if(CustomColorMap) + { + r = CustomColorMap[(x & 0x7FFF) * 3 + 0]; + g = CustomColorMap[(x & 0x7FFF) * 3 + 1]; + b = CustomColorMap[(x & 0x7FFF) * 3 + 2]; + } + else + { + r = (x & 0x1F); + g = ((x & 0x3E0) >> 5); + b = ((x & 0x7C00) >> 10); + + if(format.bpp == 16) + { + r = (r * 255 + 15) / 31; + g = (g * 255 + 15) / 31; + b = (b * 255 + 15) / 31; + } + else + { + r = (r << 3); // | (r >> 2); + g = (g << 3); // | (g >> 2); + b = (b << 3); // | (b >> 2); + } + } + + if(format.bpp == 32) + systemColorMap->v32[x] = format.MakeColor(r, g, b); + else + systemColorMap->v16[x] = format.MakeColor(r, g, b); + } + + #if 0 + for(unsigned i = 0; i < 32; i++) + { + printf("%u %u\n", i, format.MakeColor(0, 0, (i * 255 + 15) / 31)); + } + #endif +} + +static bool TestMagic(const char *name, MDFNFILE *fp) MDFN_COLD; +static bool TestMagic(const char *name, MDFNFILE *fp) +{ + if(!memcmp(GET_FDATA_PTR(fp), "PSF\x22", 4)) + return(TRUE); + + if(!strcasecmp(GET_FEXTS_PTR(fp), "gba") || !strcasecmp(GET_FEXTS_PTR(fp), "agb")) + return(TRUE); + + if(GET_FSIZE_PTR(fp) >= 192 && !strcasecmp(GET_FEXTS_PTR(fp), "bin")) + { + if((GET_FDATA_PTR(fp)[0xb2] == 0x96 && GET_FDATA_PTR(fp)[0xb3] == 0x00) || + (GET_FDATA_PTR(fp)[0] == 0x2E && GET_FDATA_PTR(fp)[3] == 0xEA)) + return(TRUE); + } + + return(FALSE); +} + +static int Load(const char *name, MDFNFILE *fp) MDFN_COLD; +static int Load(const char *name, MDFNFILE *fp) +{ + layerSettings = 0xFF00; + + if(!(rom = (uint8 *)MDFN_malloc(0x2000000, _("ROM")))) + return(0); + + memset(rom, 0xFF, 0x2000000); + + if(!(workRAM = (uint8 *)MDFN_calloc(1, 0x40000, _("Work RAM")))) + { + MDFN_free(rom); + return(0); + } + + + { + uint32 size = GET_FSIZE_PTR(fp); + uint8 *whereToLoad; + + if(cpuIsMultiBoot) + { + whereToLoad = workRAM; + if(size > 0x40000) + size = 0x40000; + } + else + { + whereToLoad = rom; + if(size > 0x2000000) + size = 0x2000000; + } + + memcpy(whereToLoad, GET_FDATA_PTR(fp), size); + + md5_context md5; + md5.starts(); + md5.update(GET_FDATA_PTR(fp), size); + md5.finish(MDFNGameInfo->MD5); + + MDFN_printf(_("ROM: %dKiB\n"), (size + 1023) / 1024); + MDFN_printf(_("ROM CRC32: 0x%08x\n"), (unsigned int)crc32(0, GET_FDATA_PTR(fp), size)); + MDFN_printf(_("ROM MD5: 0x%s\n"), md5_context::asciistr(MDFNGameInfo->MD5, 0).c_str()); + + uint16 *temp = (uint16 *)(rom+((size+1)&~1)); + int i; + + for(i = (size+1)&~1; i < 0x2000000; i+=2) + { + WRITE16LE(temp, (i >> 1) & 0xFFFF); + temp++; + } + } + + if(!(bios = (uint8 *)MDFN_calloc(1, 0x4000, _("BIOS ROM")))) + { + CPUCleanUp(); + return 0; + } + + if(!(internalRAM = (uint8 *)MDFN_calloc(1, 0x8000, _("Internal RAM")))) + { + CPUCleanUp(); + return 0; + } + + if(!(paletteRAM = (uint8 *)MDFN_calloc(1, 0x400, _("Palette RAM")))) + { + CPUCleanUp(); + return 0; + } + + if(!(vram = (uint8 *)MDFN_calloc(1, 0x20000, _("VRAM")))) + { + CPUCleanUp(); + return 0; + } + + if(!(oam = (uint8 *)MDFN_calloc(1, 0x400, _("OAM")))) + { + CPUCleanUp(); + return 0; + } + + if(!(ioMem = (uint8 *)MDFN_calloc(1, 0x400, _("IO")))) + { + CPUCleanUp(); + return 0; + } + + if(!(systemColorMap = (SysCM*)MDFN_malloc(sizeof(SysCM), _("GBA Color Map")))) + { + CPUCleanUp(); + return(0); + } + + CPUUpdateRenderBuffers(true); + + MDFNGameInfo->GameSetMD5Valid = FALSE; + + MDFNGBASOUND_Init(); + + { + MDFNMP_Init(0x8000, (1 << 28) / 0x8000); + + MDFNMP_AddRAM(0x40000, 0x2 << 24, workRAM); + MDFNMP_AddRAM(0x08000, 0x3 << 24, internalRAM); + } + + if(!CPUInit(MDFN_GetSettingS("gba.bios"))) + { + CPUCleanUp(); + return(0); + } + CPUReset(); + + GBA_Flash_Init(); + eepromInit(); + + { + // EEPROM might be loaded from within CPUReadBatteryFile for support for Mednafen < 0.8.2, so call before GBA_EEPROM_LoadFile(), which + // is more specific...kinda. + if(cpuSramEnabled || cpuFlashEnabled) + CPUReadBatteryFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str()); + + if(cpuEEPROMEnabled) + GBA_EEPROM_LoadFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "eep").c_str()); + } + + if(!LoadCPalette(NULL, &CustomColorMap, 32768)) + { + CPUCleanUp(); + return(0); + } + + return(1); +} + +void doMirroring (bool b) +{ + uint32 mirroredRomSize = (((romSize)>>20) & 0x3F)<<20; + uint32 mirroredRomAddress = romSize; + if ((mirroredRomSize <=0x800000) && (b)) + { + mirroredRomAddress = mirroredRomSize; + if (mirroredRomSize==0) + mirroredRomSize=0x100000; + while (mirroredRomAddress<0x01000000) + { + memcpy ((uint16 *)(rom+mirroredRomAddress), (uint16 *)(rom), mirroredRomSize); + mirroredRomAddress+=mirroredRomSize; + } + } +} + +static void CPUUpdateRender(void) +{ + switch(DISPCNT & 7) { + case 0: + if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || + cpuDisableSfx) + renderLine = mode0RenderLine; + else if(fxOn && !windowOn && !(layerEnable & 0x8000)) + renderLine = mode0RenderLineNoWindow; + else + renderLine = mode0RenderLineAll; + break; + case 1: + if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || + cpuDisableSfx) + renderLine = mode1RenderLine; + else if(fxOn && !windowOn && !(layerEnable & 0x8000)) + renderLine = mode1RenderLineNoWindow; + else + renderLine = mode1RenderLineAll; + break; + case 2: + if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || + cpuDisableSfx) + renderLine = mode2RenderLine; + else if(fxOn && !windowOn && !(layerEnable & 0x8000)) + renderLine = mode2RenderLineNoWindow; + else + renderLine = mode2RenderLineAll; + break; + case 3: + if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || + cpuDisableSfx) + renderLine = mode3RenderLine; + else if(fxOn && !windowOn && !(layerEnable & 0x8000)) + renderLine = mode3RenderLineNoWindow; + else + renderLine = mode3RenderLineAll; + break; + case 4: + if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || + cpuDisableSfx) + renderLine = mode4RenderLine; + else if(fxOn && !windowOn && !(layerEnable & 0x8000)) + renderLine = mode4RenderLineNoWindow; + else + renderLine = mode4RenderLineAll; + break; + case 5: + if((!fxOn && !windowOn && !(layerEnable & 0x8000)) || + cpuDisableSfx) + renderLine = mode5RenderLine; + else if(fxOn && !windowOn && !(layerEnable & 0x8000)) + renderLine = mode5RenderLineNoWindow; + else + renderLine = mode5RenderLineAll; + default: + break; + } +} + +void CPUUpdateCPSR() +{ + uint32 CPSR = reg[16].I & 0x40; + if(N_FLAG) + CPSR |= 0x80000000; + if(Z_FLAG) + CPSR |= 0x40000000; + if(C_FLAG) + CPSR |= 0x20000000; + if(V_FLAG) + CPSR |= 0x10000000; + if(!armState) + CPSR |= 0x00000020; + if(!armIrqEnable) + CPSR |= 0x80; + CPSR |= (armMode & 0x1F); + reg[16].I = CPSR; +} + +void CPUUpdateFlags(bool breakLoop) +{ + uint32 CPSR = reg[16].I; + + N_FLAG = (CPSR & 0x80000000) ? true: false; + Z_FLAG = (CPSR & 0x40000000) ? true: false; + C_FLAG = (CPSR & 0x20000000) ? true: false; + V_FLAG = (CPSR & 0x10000000) ? true: false; + armState = (CPSR & 0x20) ? false : true; + armIrqEnable = (CPSR & 0x80) ? false : true; + if(breakLoop) { + if (armIrqEnable && (IF & IE) && (IME & 1)) + cpuNextEvent = cpuTotalTicks; + } +} + +void CPUUpdateFlags() +{ + CPUUpdateFlags(true); +} + +#ifndef LSB_FIRST +static void CPUSwap(volatile uint32 *a, volatile uint32 *b) +{ + volatile uint32 c = *b; + *b = *a; + *a = c; +} +#else +static void CPUSwap(uint32 *a, uint32 *b) +{ + uint32 c = *b; + *b = *a; + *a = c; +} +#endif + +void CPUSwitchMode(int mode, bool saveState, bool breakLoop) +{ + // if(armMode == mode) + // return; + + CPUUpdateCPSR(); + + switch(armMode) { + case 0x10: + case 0x1F: + reg[R13_USR].I = reg[13].I; + reg[R14_USR].I = reg[14].I; + reg[17].I = reg[16].I; + break; + case 0x11: + CPUSwap(®[R8_FIQ].I, ®[8].I); + CPUSwap(®[R9_FIQ].I, ®[9].I); + CPUSwap(®[R10_FIQ].I, ®[10].I); + CPUSwap(®[R11_FIQ].I, ®[11].I); + CPUSwap(®[R12_FIQ].I, ®[12].I); + reg[R13_FIQ].I = reg[13].I; + reg[R14_FIQ].I = reg[14].I; + reg[SPSR_FIQ].I = reg[17].I; + break; + case 0x12: + reg[R13_IRQ].I = reg[13].I; + reg[R14_IRQ].I = reg[14].I; + reg[SPSR_IRQ].I = reg[17].I; + break; + case 0x13: + reg[R13_SVC].I = reg[13].I; + reg[R14_SVC].I = reg[14].I; + reg[SPSR_SVC].I = reg[17].I; + break; + case 0x17: + reg[R13_ABT].I = reg[13].I; + reg[R14_ABT].I = reg[14].I; + reg[SPSR_ABT].I = reg[17].I; + break; + case 0x1b: + reg[R13_UND].I = reg[13].I; + reg[R14_UND].I = reg[14].I; + reg[SPSR_UND].I = reg[17].I; + break; + } + + uint32 CPSR = reg[16].I; + uint32 SPSR = reg[17].I; + + switch(mode) { + case 0x10: + case 0x1F: + reg[13].I = reg[R13_USR].I; + reg[14].I = reg[R14_USR].I; + reg[16].I = SPSR; + break; + case 0x11: + CPUSwap(®[8].I, ®[R8_FIQ].I); + CPUSwap(®[9].I, ®[R9_FIQ].I); + CPUSwap(®[10].I, ®[R10_FIQ].I); + CPUSwap(®[11].I, ®[R11_FIQ].I); + CPUSwap(®[12].I, ®[R12_FIQ].I); + reg[13].I = reg[R13_FIQ].I; + reg[14].I = reg[R14_FIQ].I; + if(saveState) + reg[17].I = CPSR; + else + reg[17].I = reg[SPSR_FIQ].I; + break; + case 0x12: + reg[13].I = reg[R13_IRQ].I; + reg[14].I = reg[R14_IRQ].I; + reg[16].I = SPSR; + if(saveState) + reg[17].I = CPSR; + else + reg[17].I = reg[SPSR_IRQ].I; + break; + case 0x13: + reg[13].I = reg[R13_SVC].I; + reg[14].I = reg[R14_SVC].I; + reg[16].I = SPSR; + if(saveState) + reg[17].I = CPSR; + else + reg[17].I = reg[SPSR_SVC].I; + break; + case 0x17: + reg[13].I = reg[R13_ABT].I; + reg[14].I = reg[R14_ABT].I; + reg[16].I = SPSR; + if(saveState) + reg[17].I = CPSR; + else + reg[17].I = reg[SPSR_ABT].I; + break; + case 0x1b: + reg[13].I = reg[R13_UND].I; + reg[14].I = reg[R14_UND].I; + reg[16].I = SPSR; + if(saveState) + reg[17].I = CPSR; + else + reg[17].I = reg[SPSR_UND].I; + break; + default: + //systemMessage(MSG_UNSUPPORTED_ARM_MODE, N_("Unsupported ARM mode %02x"), mode); + break; + } + armMode = mode; + CPUUpdateFlags(breakLoop); + CPUUpdateCPSR(); +} + +void CPUSwitchMode(int mode, bool saveState) +{ + CPUSwitchMode(mode, saveState, true); +} + +void CPUUndefinedException() +{ + uint32 PC = reg[15].I; + bool savedArmState = armState; + CPUSwitchMode(0x1b, true, false); + reg[14].I = PC - (savedArmState ? 4 : 2); + reg[15].I = 0x04; + armState = true; + armIrqEnable = false; + armNextPC = 0x04; + ARM_PREFETCH; + reg[15].I += 4; +} + +void CPUSoftwareInterrupt() +{ + uint32 PC = reg[15].I; + bool savedArmState = armState; + CPUSwitchMode(0x13, true, false); + reg[14].I = PC - (savedArmState ? 4 : 2); + reg[15].I = 0x08; + armState = true; + armIrqEnable = false; + armNextPC = 0x08; + ARM_PREFETCH; + reg[15].I += 4; +} + +void CPUSoftwareInterrupt(int comment) +{ + static bool disableMessage = false; + if(armState) comment >>= 16; + if(comment == 0xfa) { + return; + } + if(useBios) { + CPUSoftwareInterrupt(); + return; + } + // This would be correct, but it causes problems if uncommented + // else { + // biosProtected = 0xe3a02004; + // } + + switch(comment) { + case 0x00: + BIOS_SoftReset(); + ARM_PREFETCH; + break; + case 0x01: + BIOS_RegisterRamReset(); + break; + case 0x02: + holdState = true; + holdType = -1; + cpuNextEvent = cpuTotalTicks; + break; + case 0x03: + holdState = true; + holdType = -1; + stopState = true; + cpuNextEvent = cpuTotalTicks; + break; + case 0x04: + CPUSoftwareInterrupt(); + break; + case 0x05: + CPUSoftwareInterrupt(); + break; + case 0x06: + CPUSoftwareInterrupt(); + break; + case 0x07: + CPUSoftwareInterrupt(); + break; + case 0x08: + BIOS_Sqrt(); + break; + case 0x09: + BIOS_ArcTan(); + break; + case 0x0A: + BIOS_ArcTan2(); + break; + case 0x0B: + { + int len = (reg[2].I & 0x1FFFFF) >>1; + if (!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + len) & 0xe000000) == 0)) + { + if ((reg[2].I >> 24) & 1) + { + if ((reg[2].I >> 26) & 1) + SWITicks = (7 + memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1); + else + SWITicks = (8 + memoryWait[(reg[1].I>>24) & 0xF]) * (len); + } + else + { + if ((reg[2].I >> 26) & 1) + SWITicks = (10 + memoryWait32[(reg[0].I>>24) & 0xF] + + memoryWait32[(reg[1].I>>24) & 0xF]) * (len>>1); + else + SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } + } + } + BIOS_CpuSet(); + break; + case 0x0C: + { + int len = (reg[2].I & 0x1FFFFF) >>5; + if (!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + len) & 0xe000000) == 0)) + { + if ((reg[2].I >> 24) & 1) + SWITicks = (6 + memoryWait32[(reg[1].I>>24) & 0xF] + + 7 * (memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 1)) * len; + else + SWITicks = (9 + memoryWait32[(reg[0].I>>24) & 0xF] + + memoryWait32[(reg[1].I>>24) & 0xF] + + 7 * (memoryWaitSeq32[(reg[0].I>>24) & 0xF] + + memoryWaitSeq32[(reg[1].I>>24) & 0xF] + 2)) * len; + } + } + BIOS_CpuFastSet(); + break; + case 0x0E: + BIOS_BgAffineSet(); + break; + case 0x0F: + BIOS_ObjAffineSet(); + break; + case 0x10: + { + int len = CPUReadHalfWord(reg[2].I); + if (!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + len) & 0xe000000) == 0)) + SWITicks = (32 + memoryWait[(reg[0].I>>24) & 0xF]) * len; + } + BIOS_BitUnPack(); + break; + case 0x11: + { + uint32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (9 + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } + BIOS_LZ77UnCompWram(); + break; + case 0x12: + { + uint32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (19 + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } + BIOS_LZ77UnCompVram(); + break; + case 0x13: + { + uint32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (29 + (memoryWait[(reg[0].I>>24) & 0xF]<<1)) * len; + } + BIOS_HuffUnComp(); + break; + case 0x14: + { + uint32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (11 + memoryWait[(reg[0].I>>24) & 0xF] + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } + BIOS_RLUnCompWram(); + break; + case 0x15: + { + uint32 len = CPUReadMemory(reg[0].I) >> 9; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (34 + (memoryWait[(reg[0].I>>24) & 0xF] << 1) + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } + BIOS_RLUnCompVram(); + break; + case 0x16: + { + uint32 len = CPUReadMemory(reg[0].I) >> 8; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } + BIOS_Diff8bitUnFilterWram(); + break; + case 0x17: + { + uint32 len = CPUReadMemory(reg[0].I) >> 9; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (39 + (memoryWait[(reg[0].I>>24) & 0xF]<<1) + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } + BIOS_Diff8bitUnFilterVram(); + break; + case 0x18: + { + uint32 len = CPUReadMemory(reg[0].I) >> 9; + if(!(((reg[0].I & 0xe000000) == 0) || + ((reg[0].I + (len & 0x1fffff)) & 0xe000000) == 0)) + SWITicks = (13 + memoryWait[(reg[0].I>>24) & 0xF] + + memoryWait[(reg[1].I>>24) & 0xF]) * len; + } + BIOS_Diff16bitUnFilter(); + break; + case 0x19: + //if(reg[0].I) + // systemSoundPause(); + //else + // systemSoundResume(); + break; + case 0x1F: + BIOS_MidiKey2Freq(); + break; + case 0x2A: + BIOS_SndDriverJmpTableCopy(); + // let it go, because we don't really emulate this function + default: + if(!disableMessage) { + MDFN_PrintError(_("Unsupported BIOS function %02x called from %08x. A BIOS file is needed in order to get correct behaviour."), + comment, + armMode ? armNextPC - 4: armNextPC - 2); + disableMessage = true; + } + break; + } +} + +void CPUCompareVCOUNT() +{ + if(VCOUNT == (DISPSTAT >> 8)) { + DISPSTAT |= 4; + UPDATE_REG(0x04, DISPSTAT); + + if(DISPSTAT & 0x20) { + IF |= 4; + UPDATE_REG(0x202, IF); + } + } else { + DISPSTAT &= 0xFFFB; + UPDATE_REG(0x4, DISPSTAT); + } + if (layerEnableDelay>0) + { + layerEnableDelay--; + if (layerEnableDelay==1) + layerEnable = layerSettings & DISPCNT; + } + +} + +#define doDMA(s, d, _si, _di, _c, _transfer32) \ +{ \ + uint32 si = _si; \ + uint32 di = _di; \ + uint32 c = _c; \ + int sm = s >> 24; \ + int dm = d >> 24; \ + int sw = 0; \ + int dw = 0; \ + int sc = c; \ + cpuDmaCount = c; \ + if (sm>15) \ + sm=15; \ + if (dm>15) \ + dm=15; \ + if(_transfer32) { \ + s &= 0xFFFFFFFC; \ + if(s < 0x02000000 && (reg[15].I >> 24)) { \ + while(c != 0) { \ + CPUWriteMemory(d, 0); \ + d += di; \ + c--; \ + } \ + } else { \ + while(c != 0) { \ + cpuDmaLast = CPUReadMemory(s); \ + CPUWriteMemory(d, cpuDmaLast); \ + d += di; \ + s += si; \ + c--; \ + } \ + } \ + } else { \ + s &= 0xFFFFFFFE; \ + si = (int)si >> 1; \ + di = (int)di >> 1; \ + if(s < 0x02000000 && (reg[15].I >> 24)) { \ + while(c != 0) { \ + CPUWriteHalfWord(d, 0); \ + d += di; \ + c--; \ + } \ + } else { \ + while(c != 0) { \ + cpuDmaLast = CPUReadHalfWord(s); \ + CPUWriteHalfWord(d, cpuDmaLast); \ + cpuDmaLast |= (cpuDmaLast<<16); \ + d += di; \ + s += si; \ + c--; \ + } \ + } \ + } \ + cpuDmaCount = 0; \ + int totalTicks = 0; \ + if(_transfer32) { \ + sw =1+memoryWaitSeq32[sm & 15]; \ + dw =1+memoryWaitSeq32[dm & 15]; \ + totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait32[sm & 15] + \ + memoryWaitSeq32[dm & 15]; \ + } \ + else \ + { \ + sw = 1+memoryWaitSeq[sm & 15]; \ + dw = 1+memoryWaitSeq[dm & 15]; \ + totalTicks = (sw+dw)*(sc-1) + 6 + memoryWait[sm & 15] + \ + memoryWaitSeq[dm & 15]; \ + } \ + cpuDmaTicksToUpdate += totalTicks; \ +} + +void CPUCheckDMA(int reason, int dmamask) +{ + // DMA 0 + if((DMCNT_H[0] & 0x8000) && (dmamask & 1)) { + if(((DMCNT_H[0] >> 12) & 3) == reason) { + uint32 sourceIncrement = 4; + uint32 destIncrement = 4; + switch((DMCNT_H[0] >> 7) & 3) { + case 0: + break; + case 1: + sourceIncrement = (uint32)-4; + break; + case 2: + sourceIncrement = 0; + break; + } + switch((DMCNT_H[0] >> 5) & 3) { + case 0: + break; + case 1: + destIncrement = (uint32)-4; + break; + case 2: + destIncrement = 0; + break; + } + doDMA(dmaSource[0], dmaDest[0], sourceIncrement, destIncrement, + DMCNT_L[0] ? DMCNT_L[0] : 0x4000, + DMCNT_H[0] & 0x0400); + cpuDmaHack = true; + + if(DMCNT_H[0] & 0x4000) { + IF |= 0x0100; + UPDATE_REG(0x202, IF); + cpuNextEvent = cpuTotalTicks; + } + + if(((DMCNT_H[0] >> 5) & 3) == 3) { + dmaDest[0] = DMDAD_L[0] | (DMDAD_H[0] << 16); + } + + if(!(DMCNT_H[0] & 0x0200) || (reason == 0)) { + DMCNT_H[0] &= 0x7FFF; + UPDATE_REG(0xBA, DMCNT_H[0]); + } + } + } + + // DMA 1 + if((DMCNT_H[1] & 0x8000) && (dmamask & 2)) { + if(((DMCNT_H[1] >> 12) & 3) == reason) { + uint32 sourceIncrement = 4; + uint32 destIncrement = 4; + switch((DMCNT_H[1] >> 7) & 3) { + case 0: + break; + case 1: + sourceIncrement = (uint32)-4; + break; + case 2: + sourceIncrement = 0; + break; + } + switch((DMCNT_H[1] >> 5) & 3) { + case 0: + break; + case 1: + destIncrement = (uint32)-4; + break; + case 2: + destIncrement = 0; + break; + } + if(reason == 3) { + doDMA(dmaSource[1], dmaDest[1], sourceIncrement, 0, 4, + 0x0400); + } else { + doDMA(dmaSource[1], dmaDest[1], sourceIncrement, destIncrement, + DMCNT_L[1] ? DMCNT_L[1] : 0x4000, + DMCNT_H[1] & 0x0400); + } + cpuDmaHack = true; + + if(DMCNT_H[1] & 0x4000) { + IF |= 0x0200; + UPDATE_REG(0x202, IF); + cpuNextEvent = cpuTotalTicks; + } + + if(((DMCNT_H[1] >> 5) & 3) == 3) { + dmaDest[1] = DMDAD_L[1] | (DMDAD_H[1] << 16); + } + + if(!(DMCNT_H[1] & 0x0200) || (reason == 0)) { + DMCNT_H[1] &= 0x7FFF; + UPDATE_REG(0xC6, DMCNT_H[1]); + } + } + } + + // DMA 2 + if((DMCNT_H[2] & 0x8000) && (dmamask & 4)) { + if(((DMCNT_H[2] >> 12) & 3) == reason) { + uint32 sourceIncrement = 4; + uint32 destIncrement = 4; + switch((DMCNT_H[2] >> 7) & 3) { + case 0: + break; + case 1: + sourceIncrement = (uint32)-4; + break; + case 2: + sourceIncrement = 0; + break; + } + switch((DMCNT_H[2] >> 5) & 3) { + case 0: + break; + case 1: + destIncrement = (uint32)-4; + break; + case 2: + destIncrement = 0; + break; + } + if(reason == 3) { + doDMA(dmaSource[2], dmaDest[2], sourceIncrement, 0, 4, + 0x0400); + } else { + doDMA(dmaSource[2], dmaDest[2], sourceIncrement, destIncrement, + DMCNT_L[2] ? DMCNT_L[2] : 0x4000, + DMCNT_H[2] & 0x0400); + } + cpuDmaHack = true; + + if(DMCNT_H[2] & 0x4000) { + IF |= 0x0400; + UPDATE_REG(0x202, IF); + cpuNextEvent = cpuTotalTicks; + } + + if(((DMCNT_H[2] >> 5) & 3) == 3) { + dmaDest[2] = DMDAD_L[2] | (DMDAD_H[2] << 16); + } + + if(!(DMCNT_H[2] & 0x0200) || (reason == 0)) { + DMCNT_H[2] &= 0x7FFF; + UPDATE_REG(0xD2, DMCNT_H[2]); + } + } + } + + // DMA 3 + if((DMCNT_H[3] & 0x8000) && (dmamask & 8)) { + if(((DMCNT_H[3] >> 12) & 3) == reason) { + uint32 sourceIncrement = 4; + uint32 destIncrement = 4; + switch((DMCNT_H[3] >> 7) & 3) { + case 0: + break; + case 1: + sourceIncrement = (uint32)-4; + break; + case 2: + sourceIncrement = 0; + break; + } + switch((DMCNT_H[3] >> 5) & 3) { + case 0: + break; + case 1: + destIncrement = (uint32)-4; + break; + case 2: + destIncrement = 0; + break; + } + doDMA(dmaSource[3], dmaDest[3], sourceIncrement, destIncrement, + DMCNT_L[3] ? DMCNT_L[3] : 0x10000, + DMCNT_H[3] & 0x0400); + if(DMCNT_H[3] & 0x4000) { + IF |= 0x0800; + UPDATE_REG(0x202, IF); + cpuNextEvent = cpuTotalTicks; + } + + if(((DMCNT_H[3] >> 5) & 3) == 3) { + dmaDest[3] = DMDAD_L[3] | (DMDAD_H[3] << 16); + } + + if(!(DMCNT_H[3] & 0x0200) || (reason == 0)) { + DMCNT_H[3] &= 0x7FFF; + UPDATE_REG(0xDE, DMCNT_H[3]); + } + } + } +} + +void CPUUpdateRegister(uint32 address, uint16 value) +{ + switch(address) + { + case 0x00: + { + if ((value & 7) >5) + DISPCNT = (value &7); + bool change = ((DISPCNT ^ value) & 0x80) ? true : false; + bool changeBG = ((DISPCNT ^ value) & 0x0F00) ? true : false; + uint16 changeBGon = (((~DISPCNT) & value) & 0x0F00); + DISPCNT = (value & 0xFFF7); + UPDATE_REG(0x00, DISPCNT); + + if (changeBGon) + { + layerEnableDelay=4; + layerEnable = layerSettings & value & (~changeBGon); + } + else + layerEnable = layerSettings & value; + // CPUUpdateTicks(); + + windowOn = (layerEnable & 0x6000) ? true : false; + if(change && !((value & 0x80))) { + if(!(DISPSTAT & 1)) { + lcdTicks = 1008; + // VCOUNT = 0; + // UPDATE_REG(0x06, VCOUNT); + DISPSTAT &= 0xFFFC; + UPDATE_REG(0x04, DISPSTAT); + CPUCompareVCOUNT(); + } + // (*renderLine)(); + } + CPUUpdateRender(); + // we only care about changes in BG0-BG3 + if(changeBG) + CPUUpdateRenderBuffers(false); + } + break; + case 0x04: + DISPSTAT = (value & 0xFF38) | (DISPSTAT & 7); + UPDATE_REG(0x04, DISPSTAT); + break; + case 0x06: + // not writable + break; + case 0x08: + BG0CNT = (value & 0xDFCF); + UPDATE_REG(0x08, BG0CNT); + break; + case 0x0A: + BG1CNT = (value & 0xDFCF); + UPDATE_REG(0x0A, BG1CNT); + break; + case 0x0C: + BG2CNT = (value & 0xFFCF); + UPDATE_REG(0x0C, BG2CNT); + break; + case 0x0E: + BG3CNT = (value & 0xFFCF); + UPDATE_REG(0x0E, BG3CNT); + break; + case 0x10: + BGHOFS[0] = value & 511; + UPDATE_REG(0x10, BGHOFS[0]); + break; + case 0x12: + BGVOFS[0] = value & 511; + UPDATE_REG(0x12, BGVOFS[0]); + break; + case 0x14: + BGHOFS[1] = value & 511; + UPDATE_REG(0x14, BGHOFS[1]); + break; + case 0x16: + BGVOFS[1] = value & 511; + UPDATE_REG(0x16, BGVOFS[1]); + break; + case 0x18: + BGHOFS[2] = value & 511; + UPDATE_REG(0x18, BGHOFS[2]); + break; + case 0x1A: + BGVOFS[2] = value & 511; + UPDATE_REG(0x1A, BGVOFS[2]); + break; + case 0x1C: + BGHOFS[3] = value & 511; + UPDATE_REG(0x1C, BGHOFS[3]); + break; + case 0x1E: + BGVOFS[3] = value & 511; + UPDATE_REG(0x1E, BGVOFS[3]); + break; + case 0x20: + BG2PA = value; + UPDATE_REG(0x20, BG2PA); + break; + case 0x22: + BG2PB = value; + UPDATE_REG(0x22, BG2PB); + break; + case 0x24: + BG2PC = value; + UPDATE_REG(0x24, BG2PC); + break; + case 0x26: + BG2PD = value; + UPDATE_REG(0x26, BG2PD); + break; + case 0x28: + BG2X_L = value; + UPDATE_REG(0x28, BG2X_L); + gfxBG2Changed |= 1; + break; + case 0x2A: + BG2X_H = (value & 0xFFF); + UPDATE_REG(0x2A, BG2X_H); + gfxBG2Changed |= 1; + break; + case 0x2C: + BG2Y_L = value; + UPDATE_REG(0x2C, BG2Y_L); + gfxBG2Changed |= 2; + break; + case 0x2E: + BG2Y_H = value & 0xFFF; + UPDATE_REG(0x2E, BG2Y_H); + gfxBG2Changed |= 2; + break; + case 0x30: + BG3PA = value; + UPDATE_REG(0x30, BG3PA); + break; + case 0x32: + BG3PB = value; + UPDATE_REG(0x32, BG3PB); + break; + case 0x34: + BG3PC = value; + UPDATE_REG(0x34, BG3PC); + break; + case 0x36: + BG3PD = value; + UPDATE_REG(0x36, BG3PD); + break; + case 0x38: + BG3X_L = value; + UPDATE_REG(0x38, BG3X_L); + gfxBG3Changed |= 1; + break; + case 0x3A: + BG3X_H = value & 0xFFF; + UPDATE_REG(0x3A, BG3X_H); + gfxBG3Changed |= 1; + break; + case 0x3C: + BG3Y_L = value; + UPDATE_REG(0x3C, BG3Y_L); + gfxBG3Changed |= 2; + break; + case 0x3E: + BG3Y_H = value & 0xFFF; + UPDATE_REG(0x3E, BG3Y_H); + gfxBG3Changed |= 2; + break; + case 0x40: + WIN0H = value; + UPDATE_REG(0x40, WIN0H); + CPUUpdateWindow0(); + break; + case 0x42: + WIN1H = value; + UPDATE_REG(0x42, WIN1H); + CPUUpdateWindow1(); + break; + case 0x44: + WIN0V = value; + UPDATE_REG(0x44, WIN0V); + break; + case 0x46: + WIN1V = value; + UPDATE_REG(0x46, WIN1V); + break; + case 0x48: + WININ = value & 0x3F3F; + UPDATE_REG(0x48, WININ); + break; + case 0x4A: + WINOUT = value & 0x3F3F; + UPDATE_REG(0x4A, WINOUT); + break; + case 0x4C: + MOSAIC = value; + UPDATE_REG(0x4C, MOSAIC); + break; + case 0x50: + BLDMOD = value & 0x3FFF; + UPDATE_REG(0x50, BLDMOD); + fxOn = ((BLDMOD>>6)&3) != 0; + CPUUpdateRender(); + break; + case 0x52: + COLEV = value & 0x1F1F; + UPDATE_REG(0x52, COLEV); + break; + case 0x54: + COLY = value & 0x1F; + UPDATE_REG(0x54, COLY); + break; + case 0x60: + case 0x62: + case 0x64: + case 0x68: + case 0x6c: + case 0x70: + case 0x72: + case 0x74: + case 0x78: + case 0x7c: + case 0x80: + case 0x84: + soundEvent(address&0xFF, (uint8)(value & 0xFF)); + soundEvent((address&0xFF)+1, (uint8)(value>>8)); + break; + case 0x82: + case 0x88: + case 0xa0: + case 0xa2: + case 0xa4: + case 0xa6: + case 0x90: + case 0x92: + case 0x94: + case 0x96: + case 0x98: + case 0x9a: + case 0x9c: + case 0x9e: + soundEvent(address&0xFF, value); + break; + case 0xB0: + DMSAD_L[0] = value; + UPDATE_REG(0xB0, DMSAD_L[0]); + break; + case 0xB2: + DMSAD_H[0] = value & 0x07FF; + UPDATE_REG(0xB2, DMSAD_H[0]); + break; + case 0xB4: + DMDAD_L[0] = value; + UPDATE_REG(0xB4, DMDAD_L[0]); + break; + case 0xB6: + DMDAD_H[0] = value & 0x07FF; + UPDATE_REG(0xB6, DMDAD_H[0]); + break; + case 0xB8: + DMCNT_L[0] = value & 0x3FFF; + UPDATE_REG(0xB8, 0); + break; + case 0xBA: + { + bool start = ((DMCNT_H[0] ^ value) & 0x8000) ? true : false; + value &= 0xF7E0; + + DMCNT_H[0] = value; + UPDATE_REG(0xBA, DMCNT_H[0]); + + if(start && (value & 0x8000)) { + dmaSource[0] = DMSAD_L[0] | (DMSAD_H[0] << 16); + dmaDest[0] = DMDAD_L[0] | (DMDAD_H[0] << 16); + CPUCheckDMA(0, 1); + } + } + break; + case 0xBC: + DMSAD_L[1] = value; + UPDATE_REG(0xBC, DMSAD_L[1]); + break; + case 0xBE: + DMSAD_H[1] = value & 0x0FFF; + UPDATE_REG(0xBE, DMSAD_H[1]); + break; + case 0xC0: + DMDAD_L[1] = value; + UPDATE_REG(0xC0, DMDAD_L[1]); + break; + case 0xC2: + DMDAD_H[1] = value & 0x07FF; + UPDATE_REG(0xC2, DMDAD_H[1]); + break; + case 0xC4: + DMCNT_L[1] = value & 0x3FFF; + UPDATE_REG(0xC4, 0); + break; + case 0xC6: + { + bool start = ((DMCNT_H[1] ^ value) & 0x8000) ? true : false; + value &= 0xF7E0; + + DMCNT_H[1] = value; + UPDATE_REG(0xC6, DMCNT_H[1]); + + if(start && (value & 0x8000)) { + dmaSource[1] = DMSAD_L[1] | (DMSAD_H[1] << 16); + dmaDest[1] = DMDAD_L[1] | (DMDAD_H[1] << 16); + CPUCheckDMA(0, 2); + } + } + break; + case 0xC8: + DMSAD_L[2] = value; + UPDATE_REG(0xC8, DMSAD_L[2]); + break; + case 0xCA: + DMSAD_H[2] = value & 0x0FFF; + UPDATE_REG(0xCA, DMSAD_H[2]); + break; + case 0xCC: + DMDAD_L[2] = value; + UPDATE_REG(0xCC, DMDAD_L[2]); + break; + case 0xCE: + DMDAD_H[2] = value & 0x07FF; + UPDATE_REG(0xCE, DMDAD_H[2]); + break; + case 0xD0: + DMCNT_L[2] = value & 0x3FFF; + UPDATE_REG(0xD0, 0); + break; + case 0xD2: + { + bool start = ((DMCNT_H[2] ^ value) & 0x8000) ? true : false; + + value &= 0xF7E0; + + DMCNT_H[2] = value; + UPDATE_REG(0xD2, DMCNT_H[2]); + + if(start && (value & 0x8000)) { + dmaSource[2] = DMSAD_L[2] | (DMSAD_H[2] << 16); + dmaDest[2] = DMDAD_L[2] | (DMDAD_H[2] << 16); + + CPUCheckDMA(0, 4); + } + } + break; + case 0xD4: + DMSAD_L[3] = value; + UPDATE_REG(0xD4, DMSAD_L[3]); + break; + case 0xD6: + DMSAD_H[3] = value & 0x0FFF; + UPDATE_REG(0xD6, DMSAD_H[3]); + break; + case 0xD8: + DMDAD_L[3] = value; + UPDATE_REG(0xD8, DMDAD_L[3]); + break; + case 0xDA: + DMDAD_H[3] = value & 0x0FFF; + UPDATE_REG(0xDA, DMDAD_H[3]); + break; + case 0xDC: + DMCNT_L[3] = value; + UPDATE_REG(0xDC, 0); + break; + case 0xDE: + { + bool start = ((DMCNT_H[3] ^ value) & 0x8000) ? true : false; + + value &= 0xFFE0; + + DMCNT_H[3] = value; + UPDATE_REG(0xDE, DMCNT_H[3]); + + if(start && (value & 0x8000)) { + dmaSource[3] = DMSAD_L[3] | (DMSAD_H[3] << 16); + dmaDest[3] = DMDAD_L[3] | (DMDAD_H[3] << 16); + CPUCheckDMA(0,8); + } + } + break; + case 0x100: + timers[0].Reload = value; + break; + case 0x102: + timers[0].Value = value; + timerOnOffDelay|=1; + cpuNextEvent = cpuTotalTicks; + break; + case 0x104: + timers[1].Reload = value; + break; + case 0x106: + timers[1].Value = value; + timerOnOffDelay|=2; + cpuNextEvent = cpuTotalTicks; + break; + case 0x108: + timers[2].Reload = value; + break; + case 0x10A: + timers[2].Value = value; + timerOnOffDelay|=4; + cpuNextEvent = cpuTotalTicks; + break; + case 0x10C: + timers[3].Reload = value; + break; + case 0x10E: + timers[3].Value = value; + timerOnOffDelay|=8; + cpuNextEvent = cpuTotalTicks; + break; + case 0x128: + if(value & 0x80) { + value &= 0xff7f; + if(value & 1 && (value & 0x4000)) { + UPDATE_REG(0x12a, 0xFF); + IF |= 0x80; + UPDATE_REG(0x202, IF); + value &= 0x7f7f; + } + } + UPDATE_REG(0x128, value); + break; + case 0x130: + P1 |= (value & 0x3FF); + UPDATE_REG(0x130, P1); + break; + case 0x132: + UPDATE_REG(0x132, value & 0xC3FF); + break; + case 0x200: + IE = value & 0x3FFF; + UPDATE_REG(0x200, IE); + if ((IME & 1) && (IF & IE) && armIrqEnable) + cpuNextEvent = cpuTotalTicks; + break; + case 0x202: + IF ^= (value & IF); + UPDATE_REG(0x202, IF); + break; + case 0x204: + { + memoryWait[0x0e] = memoryWaitSeq[0x0e] = gamepakRamWaitState[value & 3]; + + memoryWait[0x08] = memoryWait[0x09] = gamepakWaitState[(value >> 2) & 3]; + memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = + gamepakWaitState0[(value >> 4) & 1]; + + memoryWait[0x0a] = memoryWait[0x0b] = gamepakWaitState[(value >> 5) & 3]; + memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = + gamepakWaitState1[(value >> 7) & 1]; + + memoryWait[0x0c] = memoryWait[0x0d] = gamepakWaitState[(value >> 8) & 3]; + memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = + gamepakWaitState2[(value >> 10) & 1]; + + for(int i = 8; i < 15; i++) { + memoryWait32[i] = memoryWait[i] + memoryWaitSeq[i] + 1; + memoryWaitSeq32[i] = memoryWaitSeq[i]*2 + 1; + } + + if((value & 0x4000) == 0x4000) { + busPrefetchEnable = true; + busPrefetch = false; + busPrefetchCount = 0; + } else { + busPrefetchEnable = false; + busPrefetch = false; + busPrefetchCount = 0; + } + UPDATE_REG(0x204, value & 0x7FFF); + + } + break; + case 0x208: + IME = value & 1; + UPDATE_REG(0x208, IME); + if ((IME & 1) && (IF & IE) && armIrqEnable) + cpuNextEvent = cpuTotalTicks; + break; + case 0x300: + if(value != 0) + value &= 0xFFFE; + UPDATE_REG(0x300, value); + break; + default: + UPDATE_REG(address&0x3FE, value); + break; + } +} + +void applyTimer () +{ + if (timerOnOffDelay & 1) + { + timers[0].ClockReload = TIMER_TICKS[timers[0].Value & 3]; + if(!timers[0].On && (timers[0].Value & 0x80)) { + // reload the counter + timers[0].D = timers[0].Reload; + timers[0].Ticks = (0x10000 - timers[0].D) << timers[0].ClockReload; + UPDATE_REG(0x100, timers[0].D); + } + timers[0].On = timers[0].Value & 0x80 ? true : false; + timers[0].CNT = timers[0].Value & 0xC7; + UPDATE_REG(0x102, timers[0].CNT); + // CPUUpdateTicks(); + } + if (timerOnOffDelay & 2) + { + timers[1].ClockReload = TIMER_TICKS[timers[1].Value & 3]; + if(!timers[1].On && (timers[1].Value & 0x80)) { + // reload the counter + timers[1].D = timers[1].Reload; + timers[1].Ticks = (0x10000 - timers[1].D) << timers[1].ClockReload; + UPDATE_REG(0x104, timers[1].D); + } + timers[1].On = timers[1].Value & 0x80 ? true : false; + timers[1].CNT = timers[1].Value & 0xC7; + UPDATE_REG(0x106, timers[1].CNT); + } + if (timerOnOffDelay & 4) + { + timers[2].ClockReload = TIMER_TICKS[timers[2].Value & 3]; + if(!timers[2].On && (timers[2].Value & 0x80)) { + // reload the counter + timers[2].D = timers[2].Reload; + timers[2].Ticks = (0x10000 - timers[2].D) << timers[2].ClockReload; + UPDATE_REG(0x108, timers[2].D); + } + timers[2].On = timers[2].Value & 0x80 ? true : false; + timers[2].CNT = timers[2].Value & 0xC7; + UPDATE_REG(0x10A, timers[2].CNT); + } + if (timerOnOffDelay & 8) + { + timers[3].ClockReload = TIMER_TICKS[timers[3].Value & 3]; + if(!timers[3].On && (timers[3].Value & 0x80)) { + // reload the counter + timers[3].D = timers[3].Reload; + timers[3].Ticks = (0x10000 - timers[3].D) << timers[3].ClockReload; + UPDATE_REG(0x10C, timers[3].D); + } + timers[3].On = timers[3].Value & 0x80 ? true : false; + timers[3].CNT = timers[3].Value & 0xC7; + UPDATE_REG(0x10E, timers[3].CNT); + } + cpuNextEvent = CPUUpdateTicks(); + timerOnOffDelay = 0; +} + +static void FLASH_SRAM_Write(uint32 A, uint32 V) +{ +// printf("%08x %08x\n", A, V); + + if(cpuFlashEnabled && cpuSramEnabled) + { + if((A & 0xFFFF) == 0x5555 && (V & 0xFF) == 0xAA) + cpuSramEnabled = FALSE; + else if((A & 0xFFFF) != 0x2AAA) + cpuFlashEnabled = FALSE; + + if(!cpuFlashEnabled || !cpuSramEnabled) + printf("%s emulation disabled by write to: %08x %08x\n", cpuSramEnabled ? "FLASH" : "SRAM", A, V); + } + + if(cpuSramEnabled) + sramWrite(A, V); + + if(cpuFlashEnabled) + flashWrite(A, V); +} + +void CPUWriteMemory(uint32 address, uint32 value) +{ + switch(address >> 24) + { + case 0x02: + WRITE32LE(((uint32 *)&workRAM[address & 0x3FFFC]), value); + break; \ + case 0x03: \ + WRITE32LE(((uint32 *)&internalRAM[address & 0x7ffC]), value); \ + break; \ + case 0x04: \ + if(address < 0x4000400) { \ + CPUUpdateRegister((address & 0x3FC), value & 0xFFFF); \ + CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16)); \ + } \ + break; \ + case 0x05: \ + WRITE32LE(((uint32 *)&paletteRAM[address & 0x3FC]), value); \ + break; \ + case 0x06: \ + address = (address & 0x1fffc); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + WRITE32LE(((uint32 *)&vram[address]), value); + break; \ + + case 0x07: + WRITE32LE(((uint32 *)&oam[address & 0x3fc]), value); + break; + + case 0x0D: + if(cpuEEPROMEnabled) + { + eepromWrite(address, value); + break; + } + break; + + case 0x0E: + FLASH_SRAM_Write(address, value); + break; + + default: break; + } +} + +void CPUWriteHalfWord(uint32 address, uint16 value) +{ + switch(address >> 24) + { + case 2: + WRITE16LE(((uint16 *)&workRAM[address & 0x3FFFE]),value); + break; + case 3: + WRITE16LE(((uint16 *)&internalRAM[address & 0x7ffe]), value); + break; + case 4: + if(address < 0x4000400) + CPUUpdateRegister(address & 0x3fe, value); + else goto unwritable; + break; + case 5: + WRITE16LE(((uint16 *)&paletteRAM[address & 0x3fe]), value); + break; + case 6: + address = (address & 0x1fffe); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + WRITE16LE(((uint16 *)&vram[address]), value); + break; + case 7: + WRITE16LE(((uint16 *)&oam[address & 0x3fe]), value); + break; + case 8: + case 9: + if(GBA_RTC && (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)) + GBA_RTC->Write(address, value); + else + goto unwritable; + break; + case 13: + if(cpuEEPROMEnabled) + { + eepromWrite(address, (uint8)value); + break; + } + goto unwritable; + + case 0x0E: + FLASH_SRAM_Write(address, value); + break; + + default: + unwritable: + break; + } +} + +void CPUWriteByte(uint32 address, uint8 b) +{ + switch(address >> 24) + { + case 2: + workRAM[address & 0x3FFFF] = b; + break; + + case 3: + internalRAM[address & 0x7fff] = b; + break; + + case 4: + if(address < 0x4000400) + { + switch(address & 0x3FF) + { + case 0x301: + if(b == 0x80) + stopState = true; + holdState = 1; + holdType = -1; + cpuNextEvent = cpuTotalTicks; + break; + + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x68: + case 0x69: + case 0x6c: + case 0x6d: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x78: + case 0x79: + case 0x7c: + case 0x7d: + case 0x80: + case 0x81: + case 0x84: + case 0x85: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9a: + case 0x9b: + case 0x9c: + case 0x9d: + case 0x9e: + case 0x9f: + soundEvent(address&0xFF, b); + break; + default: + if(address & 1) + CPUUpdateRegister(address & 0x3fe, + ((READ16LE(((uint16 *)&ioMem[address & 0x3fe]))) + & 0x00FF) | + b<<8); + else + CPUUpdateRegister(address & 0x3fe, + ((READ16LE(((uint16 *)&ioMem[address & 0x3fe])) & 0xFF00) | b)); + } + break; + } else goto unwritable; + break; + case 5: + // no need to switch + *((uint16 *)&paletteRAM[address & 0x3FE]) = (b << 8) | b; + break; + case 6: + address = (address & 0x1fffe); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + // no need to switch + // byte writes to OBJ VRAM are ignored + if ((address) < objTilesAddress[((DISPCNT&7)+1)>>2]) + *((uint16 *)&vram[address]) = (b << 8) | b; + break; + case 7: + // no need to switch + // byte writes to OAM are ignored + // *((uint16 *)&oam[address & 0x3FE]) = (b << 8) | b; + break; + + case 0xD: + if(cpuEEPROMEnabled) { + eepromWrite(address, b); + break; + } + goto unwritable; + + case 0xE: + FLASH_SRAM_Write(address, b); + break; + + // default + default: + unwritable: + break; + } +} + +uint8 cpuBitsSet[256]; +uint8 cpuLowestBitSet[256]; + +static bool CPUInit(const std::string bios_fn) +{ + FILE *memfp; + + FlashSizeSet = FALSE; + + memfp = fopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "type").c_str(), "rb"); + if(memfp) + { + char linebuffer[256]; + + cpuSramEnabled = FALSE; + cpuFlashEnabled = FALSE; + cpuEEPROMEnabled = FALSE; + cpuEEPROMSensorEnabled = FALSE; + + while(fgets(linebuffer, 256, memfp)) + { + char args[2][256]; + int acount = trio_sscanf(linebuffer, "%.255s %.255s", args[0], args[1]); + + if(acount < 1) + continue; + + //MDFN_printf(_("Backup memory type override: %s %s\n"), linebuffer, (acount > 1) ? args[1] : ""); + + if(!strcasecmp(args[0], "sram")) + { + cpuSramEnabled = TRUE; + } + else if(!strcasecmp(args[0], "flash")) + { + cpuFlashEnabled = TRUE; + if(acount == 2) + { + int size_temp = atoi(args[1]); + + if(size_temp == 0x10000 || size_temp == 0x20000) + { + flashSetSize(size_temp); + FlashSizeSet = TRUE; + } + else if(size_temp == 64 || size_temp == 128) + { + flashSetSize(size_temp * 1024); + FlashSizeSet = TRUE; + } + else + puts("Flash size error"); + } + } + else if(!strcasecmp(args[0], "eeprom")) + cpuEEPROMEnabled = TRUE; + else if(!strcasecmp(args[0], "sensor")) + cpuEEPROMSensorEnabled = TRUE; + else if(!strcasecmp(args[0], "rtc")) + GBA_RTC = new RTC(); + } + fclose(memfp); + } + else + { + cpuSramEnabled = true; + cpuFlashEnabled = true; + cpuEEPROMEnabled = true; + cpuEEPROMSensorEnabled = true; + } + + useBios = false; + + if(bios_fn != "" && bios_fn != "0" && bios_fn != "none") + { + static const FileExtensionSpecStruct KnownBIOSExtensions[] = + { + { ".gba", gettext_noop("GameBoy Advance ROM Image") }, + { ".agb", gettext_noop("GameBoy Advance ROM Image") }, + { ".bin", gettext_noop("GameBoy Advance ROM Image") }, + { ".bios", gettext_noop("BIOS Image") }, + { NULL, NULL } + }; + + MDFNFILE bios_fp; + + if(!bios_fp.Open(MDFN_MakeFName(MDFNMKF_FIRMWARE, 0, bios_fn.c_str()), KnownBIOSExtensions, _("GBA BIOS"))) + { + return(0); + } + + if(GET_FSIZE(bios_fp) != 0x4000) + { + MDFN_PrintError(_("Invalid BIOS file size")); + bios_fp.Close(); + return(0); + } + + memcpy(bios, GET_FDATA(bios_fp), 0x4000); + + bios_fp.Close(); + useBios = true; + } + + if(!useBios) + { + memcpy(bios, myROM, sizeof(myROM)); + Endian_A32_NE_to_LE(bios, sizeof(myROM) / 4); + } + + int i = 0; + + biosProtected[0] = 0x00; + biosProtected[1] = 0xf0; + biosProtected[2] = 0x29; + biosProtected[3] = 0xe1; + + for(i = 0; i < 256; i++) { + int count = 0; + int j; + for(j = 0; j < 8; j++) + if(i & (1 << j)) + count++; + cpuBitsSet[i] = count; + + for(j = 0; j < 8; j++) + if(i & (1 << j)) + break; + cpuLowestBitSet[i] = j; + } + + for(i = 0; i < 0x400; i++) + ioReadable[i] = true; + for(i = 0x10; i < 0x48; i++) + ioReadable[i] = false; + for(i = 0x4c; i < 0x50; i++) + ioReadable[i] = false; + for(i = 0x54; i < 0x60; i++) + ioReadable[i] = false; + for(i = 0x8c; i < 0x90; i++) + ioReadable[i] = false; + for(i = 0xa0; i < 0xb8; i++) + ioReadable[i] = false; + for(i = 0xbc; i < 0xc4; i++) + ioReadable[i] = false; + for(i = 0xc8; i < 0xd0; i++) + ioReadable[i] = false; + for(i = 0xd4; i < 0xdc; i++) + ioReadable[i] = false; + for(i = 0xe0; i < 0x100; i++) + ioReadable[i] = false; + for(i = 0x110; i < 0x120; i++) + ioReadable[i] = false; + for(i = 0x12c; i < 0x130; i++) + ioReadable[i] = false; + for(i = 0x138; i < 0x140; i++) + ioReadable[i] = false; + for(i = 0x144; i < 0x150; i++) + ioReadable[i] = false; + for(i = 0x15c; i < 0x200; i++) + ioReadable[i] = false; + for(i = 0x20c; i < 0x300; i++) + ioReadable[i] = false; + for(i = 0x304; i < 0x400; i++) + ioReadable[i] = false; + + if(romSize < 0x1fe2000) { + *((uint16 *)&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA + *((uint16 *)&rom[0x1fe209e]) = 0x4770; // BX LR + } else { + + } + return(1); +} + +static void CPUReset(void) MDFN_COLD; +static void CPUReset(void) +{ + if(GBA_RTC) + GBA_RTC->Reset(); + + // clean registers + memset(®[0], 0, sizeof(reg)); + // clean OAM + memset(oam, 0, 0x400); + // clean palette + memset(paletteRAM, 0, 0x400); + // clean vram + memset(vram, 0, 0x20000); + // clean io memory + memset(ioMem, 0, 0x400); + + DISPCNT = 0x0080; + DISPSTAT = 0x0000; + VCOUNT = (useBios && !skipBios) ? 0 :0x007E; + BG0CNT = 0x0000; + BG1CNT = 0x0000; + BG2CNT = 0x0000; + BG3CNT = 0x0000; + + for(int i = 0; i < 4; i++) + { + BGHOFS[i] = 0; + BGVOFS[i] = 0; + } + + BG2PA = 0x0100; + BG2PB = 0x0000; + BG2PC = 0x0000; + BG2PD = 0x0100; + BG2X_L = 0x0000; + BG2X_H = 0x0000; + BG2Y_L = 0x0000; + BG2Y_H = 0x0000; + BG3PA = 0x0100; + BG3PB = 0x0000; + BG3PC = 0x0000; + BG3PD = 0x0100; + BG3X_L = 0x0000; + BG3X_H = 0x0000; + BG3Y_L = 0x0000; + BG3Y_H = 0x0000; + WIN0H = 0x0000; + WIN1H = 0x0000; + WIN0V = 0x0000; + WIN1V = 0x0000; + WININ = 0x0000; + WINOUT = 0x0000; + MOSAIC = 0x0000; + BLDMOD = 0x0000; + COLEV = 0x0000; + COLY = 0x0000; + + for(int i = 0; i < 4; i++) + DMSAD_L[i] = DMSAD_H[i] = 0; + + for(int i = 0; i < 4; i++) + { + timers[i].D = 0; + timers[i].CNT = 0; + } + + P1 = 0x03FF; + IE = 0x0000; + IF = 0x0000; + IME = 0x0000; + + armMode = 0x1F; + + if(cpuIsMultiBoot) { + reg[13].I = 0x03007F00; + reg[15].I = 0x02000000; + reg[16].I = 0x00000000; + reg[R13_IRQ].I = 0x03007FA0; + reg[R13_SVC].I = 0x03007FE0; + armIrqEnable = true; + } else { + if(useBios && !skipBios) { + reg[15].I = 0x00000000; + armMode = 0x13; + armIrqEnable = false; + } else { + reg[13].I = 0x03007F00; + reg[15].I = 0x08000000; + reg[16].I = 0x00000000; + reg[R13_IRQ].I = 0x03007FA0; + reg[R13_SVC].I = 0x03007FE0; + armIrqEnable = true; + } + } + armState = true; + C_FLAG = false; + V_FLAG = false; + N_FLAG = false; + Z_FLAG = false; + + UPDATE_REG(0x00, DISPCNT); + UPDATE_REG(0x06, VCOUNT); + UPDATE_REG(0x20, BG2PA); + UPDATE_REG(0x26, BG2PD); + UPDATE_REG(0x30, BG3PA); + UPDATE_REG(0x36, BG3PD); + UPDATE_REG(0x130, P1); + UPDATE_REG(0x88, 0x200); + + // disable FIQ + reg[16].I |= 0x40; + + CPUUpdateCPSR(); + + armNextPC = reg[15].I; + reg[15].I += 4; + + // reset internal state + holdState = false; + holdType = 0; + + biosProtected[0] = 0x00; + biosProtected[1] = 0xf0; + biosProtected[2] = 0x29; + biosProtected[3] = 0xe1; + + lcdTicks = (useBios && !skipBios) ? 1008 : 208; + + for(int i = 0; i < 4; i++) + { + timers[i].On = false; + timers[i].Ticks = 0; + timers[i].Reload = 0; + timers[i].ClockReload = 0; + } + + dmaSource[0] = 0; + dmaDest[0] = 0; + dmaSource[1] = 0; + dmaDest[1] = 0; + dmaSource[2] = 0; + dmaDest[2] = 0; + dmaSource[3] = 0; + dmaDest[3] = 0; + + renderLine = mode0RenderLine; + fxOn = false; + windowOn = false; + saveType = 0; + layerEnable = DISPCNT & layerSettings; + + CPUUpdateRenderBuffers(true); + + for(int i = 0; i < 256; i++) { + map[i].address = (uint8 *)&dummyAddress; + map[i].mask = 0; + } + + map[0].address = bios; + map[0].mask = 0x3FFF; + map[2].address = workRAM; + map[2].mask = 0x3FFFF; + map[3].address = internalRAM; + map[3].mask = 0x7FFF; + map[4].address = ioMem; + map[4].mask = 0x3FF; + map[5].address = paletteRAM; + map[5].mask = 0x3FF; + map[6].address = vram; + map[6].mask = 0x1FFFF; + map[7].address = oam; + map[7].mask = 0x3FF; + map[8].address = rom; + map[8].mask = 0x1FFFFFF; + map[9].address = rom; + map[9].mask = 0x1FFFFFF; + map[10].address = rom; + map[10].mask = 0x1FFFFFF; + map[12].address = rom; + map[12].mask = 0x1FFFFFF; + map[14].address = flashSaveMemory; + map[14].mask = 0xFFFF; + + eepromReset(); + GBA_Flash_Reset(); + + soundReset(); + + CPUUpdateWindow0(); + CPUUpdateWindow1(); + + // make sure registers are correctly initialized if not using BIOS + if(!useBios) { + if(cpuIsMultiBoot) + BIOS_RegisterRamReset(0xfe); + else + BIOS_RegisterRamReset(0xff); + } else { + if(cpuIsMultiBoot) + BIOS_RegisterRamReset(0xfe); + } + + ARM_PREFETCH; + + cpuDmaHack = false; + + SWITicks = 0; +} + +void CPUInterrupt() +{ + uint32 PC = reg[15].I; + bool savedState = armState; + CPUSwitchMode(0x12, true, false); + reg[14].I = PC; + if(!savedState) + reg[14].I += 2; + reg[15].I = 0x18; + armState = true; + armIrqEnable = false; + + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + + // if(!holdState) + biosProtected[0] = 0x02; + biosProtected[1] = 0xc0; + biosProtected[2] = 0x5e; + biosProtected[3] = 0xe5; +} + +int32 soundTS = 0; +static uint8 *padq; + +static void SetInput(int port, const char *type, void *ptr) MDFN_COLD; +static void SetInput(int port, const char *type, void *ptr) +{ + padq = (uint8*)ptr; +} + +int32 MDFNGBA_GetTimerPeriod(int which) +{ + int32 ret = ((0x10000 - timers[which].Reload) << timers[which].ClockReload); +// printf("%d, %08x\n", ret, timers[which].Reload); + return(ret); +} + +static int frameready; +static int HelloSkipper; + +static void CPULoop(EmulateSpecStruct* espec, int ticks) +{ + MDFN_Surface* surface = espec->surface; + int clockTicks; + int timerOverflow = 0; + // variable used by the CPU core + cpuTotalTicks = 0; + cpuBreakLoop = false; + cpuNextEvent = CPUUpdateTicks(); + if(cpuNextEvent > ticks) + cpuNextEvent = ticks; + + + for(;;) { + if(!holdState && !SWITicks) { + if(armState) { + clockTicks = RunARM(); + } else { + clockTicks = RunTHUMB(); + } + } else + clockTicks = CPUUpdateTicks(); + + cpuTotalTicks += clockTicks; + + if(cpuTotalTicks >= cpuNextEvent) { + int remainingTicks = cpuTotalTicks - cpuNextEvent; + + if (SWITicks) + { + SWITicks-=clockTicks; + if (SWITicks<0) + SWITicks = 0; + } + + clockTicks = cpuNextEvent; + cpuTotalTicks = 0; + cpuDmaHack = false; + + updateLoop: + + if (IRQTicks) + { + IRQTicks -= clockTicks; + if (IRQTicks<0) + IRQTicks = 0; + } + soundTS += clockTicks; + lcdTicks -= clockTicks; + + + if(lcdTicks <= 0) { + if(DISPSTAT & 1) { // V-BLANK + // if in V-Blank mode, keep computing... + if(DISPSTAT & 2) { + lcdTicks += 1008; + VCOUNT++; + UPDATE_REG(0x06, VCOUNT); + DISPSTAT &= 0xFFFD; + UPDATE_REG(0x04, DISPSTAT); + CPUCompareVCOUNT(); + } else { + lcdTicks += 224; + DISPSTAT |= 2; + UPDATE_REG(0x04, DISPSTAT); + if(DISPSTAT & 16) { + IF |= 2; + UPDATE_REG(0x202, IF); + } + } + + if(VCOUNT >= 228) { //Reaching last line + DISPSTAT &= 0xFFFC; + UPDATE_REG(0x04, DISPSTAT); + VCOUNT = 0; + UPDATE_REG(0x06, VCOUNT); + CPUCompareVCOUNT(); + } + } else { + if(DISPSTAT & 2) { + // if in H-Blank, leave it and move to drawing mode + VCOUNT++; + UPDATE_REG(0x06, VCOUNT); + + lcdTicks += 1008; + DISPSTAT &= 0xFFFD; + if(VCOUNT == 160) + { + //ticks = 0; + //puts("VBlank"); + uint32 joy = padbufblah; + P1 = 0x03FF ^ (joy & 0x3FF); + //if(cpuEEPROMSensorEnabled) + //systemUpdateMotionSensor(); + UPDATE_REG(0x130, P1); + uint16 P1CNT = READ16LE(((uint16 *)&ioMem[0x132])); + // this seems wrong, but there are cases where the game + // can enter the stop state without requesting an IRQ from + // the joypad. + if((P1CNT & 0x4000) || stopState) { + uint16 p1 = (0x3FF ^ P1) & 0x3FF; + if(P1CNT & 0x8000) { + if(p1 == (P1CNT & 0x3FF)) { + IF |= 0x1000; + UPDATE_REG(0x202, IF); + } + } else { + if(p1 & P1CNT) { + IF |= 0x1000; + UPDATE_REG(0x202, IF); + } + } + } + + + DISPSTAT |= 1; + DISPSTAT &= 0xFFFD; + UPDATE_REG(0x04, DISPSTAT); + if(DISPSTAT & 0x0008) { + IF |= 1; + UPDATE_REG(0x202, IF); + } + CPUCheckDMA(1, 0x0f); + } + + UPDATE_REG(0x04, DISPSTAT); + CPUCompareVCOUNT(); + + } else { + if(!HelloSkipper) + { + //printf("RL: %d\n", VCOUNT); + const uint32 *src = lineMix; + + (*renderLine)(); + + if(surface->format.bpp == 32) + { + const uint32* cm = systemColorMap->v32; + uint32 *dest = surface->pixels + VCOUNT * surface->pitch32; + + for(int x = 120; x; x--) + { + *dest = cm[*src & 0xFFFF]; + dest++; + src++; + *dest = cm[*src & 0xFFFF]; + dest++; + src++; + } + } + else + { + const uint16* cm = systemColorMap->v16; + uint16* dest = surface->pixels16 + VCOUNT * surface->pitchinpix; + + for(int x = 0; x < 240; x += 2) + { + dest[x + 0] = cm[(uint16)src[x + 0]]; + dest[x + 1] = cm[(uint16)src[x + 1]]; + } + } + MDFN_MidLineUpdate(espec, VCOUNT); + } + // entering H-Blank + DISPSTAT |= 2; + UPDATE_REG(0x04, DISPSTAT); + lcdTicks += 224; + CPUCheckDMA(2, 0x0f); + if(DISPSTAT & 16) { + IF |= 2; + UPDATE_REG(0x202, IF); + } + if(VCOUNT == 159) + { + frameready = 1; + cpuBreakLoop = 1; + } + } + } + } + + if(!stopState) { + if(timers[0].On) { + timers[0].Ticks -= clockTicks; + if(timers[0].Ticks <= 0) { + timers[0].Ticks += (0x10000 - timers[0].Reload) << timers[0].ClockReload; + timerOverflow |= 1; + soundTimerOverflow(0); + if(timers[0].CNT & 0x40) { + IF |= 0x08; + UPDATE_REG(0x202, IF); + } + } + timers[0].D = 0xFFFF - (timers[0].Ticks >> timers[0].ClockReload); + UPDATE_REG(0x100, timers[0].D); + } + + if(timers[1].On) { + if(timers[1].CNT & 4) { + if(timerOverflow & 1) { + timers[1].D++; + if(timers[1].D == 0) { + timers[1].D += timers[1].Reload; + timerOverflow |= 2; + soundTimerOverflow(1); + if(timers[1].CNT & 0x40) { + IF |= 0x10; + UPDATE_REG(0x202, IF); + } + } + UPDATE_REG(0x104, timers[1].D); + } + } else { + timers[1].Ticks -= clockTicks; + if(timers[1].Ticks <= 0) { + timers[1].Ticks += (0x10000 - timers[1].Reload) << timers[1].ClockReload; + timerOverflow |= 2; + soundTimerOverflow(1); + if(timers[1].CNT & 0x40) { + IF |= 0x10; + UPDATE_REG(0x202, IF); + } + } + timers[1].D = 0xFFFF - (timers[1].Ticks >> timers[1].ClockReload); + UPDATE_REG(0x104, timers[1].D); + } + } + + if(timers[2].On) { + if(timers[2].CNT & 4) { + if(timerOverflow & 2) { + timers[2].D++; + if(timers[2].D == 0) { + timers[2].D += timers[2].Reload; + timerOverflow |= 4; + if(timers[2].CNT & 0x40) { + IF |= 0x20; + UPDATE_REG(0x202, IF); + } + } + UPDATE_REG(0x108, timers[2].D); + } + } else { + timers[2].Ticks -= clockTicks; + if(timers[2].Ticks <= 0) { + timers[2].Ticks += (0x10000 - timers[2].Reload) << timers[2].ClockReload; + timerOverflow |= 4; + if(timers[2].CNT & 0x40) { + IF |= 0x20; + UPDATE_REG(0x202, IF); + } + } + timers[2].D = 0xFFFF - (timers[2].Ticks >> timers[2].ClockReload); + UPDATE_REG(0x108, timers[2].D); + } + } + + if(timers[3].On) { + if(timers[3].CNT & 4) { + if(timerOverflow & 4) { + timers[3].D++; + if(timers[3].D == 0) { + timers[3].D += timers[3].Reload; + if(timers[3].CNT & 0x40) { + IF |= 0x40; + UPDATE_REG(0x202, IF); + } + } + UPDATE_REG(0x10C, timers[3].D); + } + } else { + timers[3].Ticks -= clockTicks; + if(timers[3].Ticks <= 0) { + timers[3].Ticks += (0x10000 - timers[3].Reload) << timers[3].ClockReload; + if(timers[3].CNT & 0x40) { + IF |= 0x40; + UPDATE_REG(0x202, IF); + } + } + timers[3].D = 0xFFFF - (timers[3].Ticks >> timers[3].ClockReload); + UPDATE_REG(0x10C, timers[3].D); + } + } + } + + timerOverflow = 0; + + ticks -= clockTicks; + + cpuNextEvent = CPUUpdateTicks(); + + if(cpuDmaTicksToUpdate > 0) { + if(cpuDmaTicksToUpdate > cpuNextEvent) + clockTicks = cpuNextEvent; + else + clockTicks = cpuDmaTicksToUpdate; + cpuDmaTicksToUpdate -= clockTicks; + if(cpuDmaTicksToUpdate < 0) + cpuDmaTicksToUpdate = 0; + cpuDmaHack = true; + goto updateLoop; + } + + if(IF && (IME & 1) && armIrqEnable) { + int res = IF & IE; + if(stopState) + res &= 0x3080; + if(res) { + if (intState) + { + if (!IRQTicks) + { + CPUInterrupt(); + intState = false; + holdState = false; + stopState = false; + holdType = 0; + } + } + else + { + if (!holdState) + { + intState = true; + IRQTicks=7; + if (cpuNextEvent> IRQTicks) + cpuNextEvent = IRQTicks; + } + else + { + CPUInterrupt(); + holdState = false; + stopState = false; + holdType = 0; + } + } + + // Stops the SWI Ticks emulation if an IRQ is executed + //(to avoid problems with nested IRQ/SWI) + if (SWITicks) + SWITicks = 0; + } + } + + if(remainingTicks > 0) { + if(remainingTicks > cpuNextEvent) + clockTicks = cpuNextEvent; + else + clockTicks = remainingTicks; + remainingTicks -= clockTicks; + if(remainingTicks < 0) + remainingTicks = 0; + goto updateLoop; + } + + if (timerOnOffDelay) + applyTimer(); + + if(cpuNextEvent > ticks) + cpuNextEvent = ticks; + + if(ticks <= 0 || cpuBreakLoop) + break; + + } + } +} + +static void Emulate(EmulateSpecStruct *espec) +{ + espec->DisplayRect.x = 0; + espec->DisplayRect.y = 0; + espec->DisplayRect.w = 240; + espec->DisplayRect.h = 160; + +#if 0 + { + static bool firstcat = true; + MDFN_PixelFormat nf; + + nf.bpp = 16; + nf.colorspace = MDFN_COLORSPACE_RGB; + nf.Rshift = 11; + nf.Gshift = 5; + nf.Bshift = 0; + nf.Ashift = 16; + + nf.Rprec = 5; + nf.Gprec = 5; + nf.Bprec = 5; + nf.Aprec = 8; + + espec->surface->SetFormat(nf, false); + espec->VideoFormatChanged = firstcat; + firstcat = false; + } +#endif + + if(espec->VideoFormatChanged) + RedoColorMap(espec->surface->format); //espec->surface->format.Rshift, espec->surface->format.Gshift, espec->surface->format.Bshift); + + if(espec->SoundFormatChanged) + MDFNGBA_SetSoundRate(espec->SoundRate); + + #if 0 + int cursong = workRAM[0x2020c96- (0x2 << 24)]; + static int last_song = 0; + + if(cursong != last_song) + { + if(last_song == 250) + { + MDFNI_EndWaveRecord(); + exit(1); + } + else + { + char wavepath[256]; + if(last_song != 0) + MDFNI_EndWaveRecord(); + trio_snprintf(wavepath, 256, "/meow/mother3-%d.wav", cursong); + MDFNI_BeginWaveRecord(FSettings.SndRate, 2, wavepath); + } + last_song = cursong; + } + #endif + + padbufblah = padq[0] | (padq[1] << 8); + + frameready = 0; + + HelloSkipper = espec->skip; + + MDFNMP_ApplyPeriodicCheats(); + + while(!frameready && (soundTS < 300000)) + CPULoop(espec, 300000); + + if(GBA_RTC) + GBA_RTC->AddTime(soundTS); + + espec->MasterCycles = soundTS; + + espec->SoundBufSize = MDFNGBASOUND_Flush(espec->SoundBuf, espec->SoundBufMaxSize); +} + +static void SetLayerEnableMask(uint64 mask) +{ + layerSettings = mask << 8; + layerEnable = layerSettings & DISPCNT; + + CPUUpdateRender(); + CPUUpdateRenderBuffers(true); + CPUUpdateWindow0(); + CPUUpdateWindow1(); +} + +static void DoSimpleCommand(int cmd) +{ + switch(cmd) + { + case MDFN_MSC_POWER: + case MDFN_MSC_RESET: CPUReset(); break; + } +} + +static MDFNSetting GBASettings[] = +{ + { "gba.bios", MDFNSF_EMU_STATE, gettext_noop("Path to optional GBA BIOS ROM image."), NULL, MDFNST_STRING, "" }, + { NULL } +}; + +static const InputDeviceInputInfoStruct IDII[] = +{ + { "a", "A", /*VIRTB_1,*/ 7, IDIT_BUTTON_CAN_RAPID, NULL }, + + { "b", "B", /*VIRTB_0,*/ 6, IDIT_BUTTON_CAN_RAPID, NULL }, + + { "select", "SELECT", /*VIRTB_SELECT,*/ 4, IDIT_BUTTON, NULL }, + + { "start", "START", /*VIRTB_START,*/ 5, IDIT_BUTTON, NULL }, + + { "right", "RIGHT →", /*VIRTB_DP0_R,*/ 3, IDIT_BUTTON, "left" }, + + { "left", "LEFT ←", /*VIRTB_DP0_L,*/ 2, IDIT_BUTTON, "right" }, + + { "up", "UP ↑", /*VIRTB_DP0_U,*/ 0, IDIT_BUTTON, "down" }, + + { "down", "DOWN ↓", /*VIRTB_DP0_D,*/ 1, IDIT_BUTTON, "up" }, + + { "shoulder_r", "SHOULDER R", /*VIRTB_SHLDR_L,*/ 9, IDIT_BUTTON, NULL }, + + { "shoulder_l", "SHOULDER L", /*VIRTB_SHLDR_R,*/ 8, IDIT_BUTTON, NULL }, +}; + +static InputDeviceInfoStruct InputDeviceInfo[] = +{ + { + "gamepad", + "Gamepad", + NULL, + NULL, + sizeof(IDII) / sizeof(InputDeviceInputInfoStruct), + IDII, + } +}; + +static const InputPortInfoStruct PortInfo[] = +{ + { "builtin", "Built-In", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" } +}; + +static InputInfoStruct InputInfo = +{ + sizeof(PortInfo) / sizeof(InputPortInfoStruct), + PortInfo +}; + +static const FileExtensionSpecStruct KnownExtensions[] = +{ + { ".gsf", gettext_noop("GSF Rip") }, + { ".minigsf", gettext_noop("MiniGSF Rip") }, + { ".gba", gettext_noop("GameBoy Advance ROM Image") }, + { ".agb", gettext_noop("GameBoy Advance ROM Image") }, + { ".bin", gettext_noop("GameBoy Advance ROM Image") }, + { NULL, NULL } +}; + +} + +using namespace MDFN_IEN_GBA; + +MDFNGI EmulatedGBA = +{ + "gba", + "GameBoy Advance", + KnownExtensions, + MODPRIO_INTERNAL_HIGH, + NULL, + &InputInfo, + Load, + TestMagic, + NULL, + NULL, + CloseGame, + SetLayerEnableMask, + "BG0\0BG1\0BG2\0BG3\0OBJ\0WIN 0\0WIN 1\0OBJ WIN\0", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + false, + StateAction, + Emulate, + SetInput, + DoSimpleCommand, + GBASettings, + MDFN_MASTERCLOCK_FIXED(16777216), + (uint32)((double)4194304 / 70224 * 65536 * 256), + + false, // Multires possible? + + 240, // lcm_width + 160, // lcm_height + NULL, // Dummy + + 240, // Nominal width + 160, // Nominal height + + 240, // Framebuffer width + 160, // Framebuffer height + + 2, // Number of output sound channels +}; + diff --git a/mednafen/gba-09333/GBA.h b/mednafen/gba-09333/GBA.h new file mode 100644 index 0000000..21485d8 --- /dev/null +++ b/mednafen/gba-09333/GBA.h @@ -0,0 +1,155 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_GBA_H +#define VBA_GBA_H + +#include "../mednafen.h" + +namespace MDFN_IEN_GBA +{ + +typedef struct { + uint8 *address; + uint32 mask; +} memoryMap; + +typedef union { + struct { +#ifdef MSB_FIRST + uint8 B3; + uint8 B2; + uint8 B1; + uint8 B0; +#else + uint8 B0; + uint8 B1; + uint8 B2; + uint8 B3; +#endif + } B; + struct { +#ifdef MSB_FIRST + uint16 W1; + uint16 W0; +#else + uint16 W0; + uint16 W1; +#endif + } W; +#ifdef MSB_FIRST + volatile uint32 I; +#else + uint32 I; +#endif +} reg_pair; + +#ifndef NO_GBA_MAP +extern memoryMap map[256]; +#endif + +extern bool busPrefetch; +extern bool busPrefetchEnable; +extern uint32 busPrefetchCount; +extern uint32 cpuPrefetch[2]; + + +extern uint8 memoryWait[16]; +extern uint8 memoryWait32[16]; +extern uint8 memoryWaitSeq[16]; +extern uint8 memoryWaitSeq32[16]; + +extern reg_pair reg[45]; +extern uint8 biosProtected[4]; + +extern uint32 N_FLAG; +extern bool Z_FLAG; +extern bool C_FLAG; +extern bool V_FLAG; +extern bool armIrqEnable; +extern bool armState; +extern int armMode; +extern void (*cpuSaveGameFunc)(uint32,uint8); + +extern void doMirroring(bool); +extern void CPUUpdateRegister(uint32, uint16); +extern void applyTimer (); + +void CPUWriteMemory(uint32 address, uint32 value); +void CPUWriteHalfWord(uint32, uint16); +void CPUWriteByte(uint32, uint8); + +extern void CPUCheckDMA(int,int); + +extern void CPUSwitchMode(int mode, bool saveState, bool breakLoop); +extern void CPUSwitchMode(int mode, bool saveState); +extern void CPUUndefinedException(); +extern void CPUSoftwareInterrupt(); +extern void CPUSoftwareInterrupt(int comment); +extern void CPUCompareVCOUNT(); +extern void CPUUpdateCPSR(); +extern void CPUUpdateFlags(bool breakLoop); +extern void CPUUpdateFlags(); + + +extern uint8 cpuBitsSet[256]; +extern uint8 cpuLowestBitSet[256]; + +extern struct EmulatedSystem GBASystem; + +int32 MDFNGBA_GetTimerPeriod(int which); + + +#define R13_IRQ 18 +#define R14_IRQ 19 +#define SPSR_IRQ 20 +#define R13_USR 26 +#define R14_USR 27 +#define R13_SVC 28 +#define R14_SVC 29 +#define SPSR_SVC 30 +#define R13_ABT 31 +#define R14_ABT 32 +#define SPSR_ABT 33 +#define R13_UND 34 +#define R14_UND 35 +#define SPSR_UND 36 +#define R8_FIQ 37 +#define R9_FIQ 38 +#define R10_FIQ 39 +#define R11_FIQ 40 +#define R12_FIQ 41 +#define R13_FIQ 42 +#define R14_FIQ 43 +#define SPSR_FIQ 44 +} + +#include "Globals.h" +#include "eeprom.h" +#include "flash.h" +#include "RTC.h" + +namespace MDFN_IEN_GBA +{ + +extern RTC *GBA_RTC; + +} + +#endif //VBA_GBA_H diff --git a/mednafen/gba-09333/GBAinline.cpp b/mednafen/gba-09333/GBAinline.cpp new file mode 100644 index 0000000..8e27224 --- /dev/null +++ b/mednafen/gba-09333/GBAinline.cpp @@ -0,0 +1,285 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Port.h" +#include "RTC.h" +#include "GBAinline.h" + +namespace MDFN_IEN_GBA +{ + +uint32 CPUReadMemory(uint32 address) +{ + uint32 value; + + switch(address >> 24) + { + case 0: + if(reg[15].I >> 24) + { + if(address < 0x4000) + { + value = READ32LE(((uint32 *)&biosProtected)); + } + else goto unreadable; + } + else + value = READ32LE(((uint32 *)&bios[address & 0x3FFC])); + break; + case 2: + value = READ32LE(((uint32 *)&workRAM[address & 0x3FFFC])); + break; + case 3: + value = READ32LE(((uint32 *)&internalRAM[address & 0x7ffC])); + break; + case 4: + if((address < 0x4000400) && ioReadable[address & 0x3fc]) { + if(ioReadable[(address & 0x3fc) + 2]) + value = READ32LE(((uint32 *)&ioMem[address & 0x3fC])); + else + value = READ16LE(((uint16 *)&ioMem[address & 0x3fc])); + } else goto unreadable; + break; + case 5: + value = READ32LE(((uint32 *)&paletteRAM[address & 0x3fC])); + break; + case 6: + address = (address & 0x1fffc); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + { + value = 0; + break; + } + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + value = READ32LE(((uint32 *)&vram[address])); + break; + case 7: + value = READ32LE(((uint32 *)&oam[address & 0x3FC])); + break; + case 8: + case 9: + case 10: + case 11: + case 12: + value = READ32LE(((uint32 *)&rom[address&0x1FFFFFC])); + break; + case 13: + if(cpuEEPROMEnabled) + // no need to swap this + return eepromRead(address); + goto unreadable; + case 14: + if(cpuFlashEnabled | cpuSramEnabled) + // no need to swap this + return flashRead(address); + // default + + default: + unreadable: + if(cpuDmaHack) { + value = cpuDmaLast; + } else { + if(armState) { + value = CPUReadMemoryQuick(reg[15].I); + } else { + value = CPUReadHalfWordQuick(reg[15].I) | + CPUReadHalfWordQuick(reg[15].I) << 16; + } + } + } + + if(address & 3) { + int shift = (address & 3) << 3; + value = (value >> shift) | (value << (32 - shift)); + } + return value; +} + +uint32 CPUReadHalfWord(uint32 address) +{ + uint32 value; + + switch(address >> 24) { + case 0: + if (reg[15].I >> 24) { + if(address < 0x4000) { + value = READ16LE(((uint16 *)&biosProtected[address&2])); + } else goto unreadable; + } else + value = READ16LE(((uint16 *)&bios[address & 0x3FFE])); + break; + case 2: + value = READ16LE(((uint16 *)&workRAM[address & 0x3FFFE])); + break; + case 3: + value = READ16LE(((uint16 *)&internalRAM[address & 0x7ffe])); + break; + case 4: + if((address < 0x4000400) && ioReadable[address & 0x3fe]) + { + value = READ16LE(((uint16 *)&ioMem[address & 0x3fe])); + if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E)) + { + if (((address & 0x3fe) == 0x100) && timers[0].On) + value = 0xFFFF - ((timers[0].Ticks-cpuTotalTicks) >> timers[0].ClockReload); + else + if (((address & 0x3fe) == 0x104) && timers[1].On && !(timers[1].CNT & 4)) + value = 0xFFFF - ((timers[1].Ticks-cpuTotalTicks) >> timers[1].ClockReload); + else + if (((address & 0x3fe) == 0x108) && timers[2].On && !(timers[2].CNT & 4)) + value = 0xFFFF - ((timers[2].Ticks-cpuTotalTicks) >> timers[2].ClockReload); + else + if (((address & 0x3fe) == 0x10C) && timers[3].On && !(timers[3].CNT & 4)) + value = 0xFFFF - ((timers[3].Ticks-cpuTotalTicks) >> timers[3].ClockReload); + } + } + else goto unreadable; + break; + case 5: + value = READ16LE(((uint16 *)&paletteRAM[address & 0x3fe])); + break; + case 6: + address = (address & 0x1fffe); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + { + value = 0; + break; + } + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + value = READ16LE(((uint16 *)&vram[address])); + break; + case 7: + value = READ16LE(((uint16 *)&oam[address & 0x3fe])); + break; + case 8: + case 9: + case 10: + case 11: + case 12: + if(GBA_RTC && (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)) + value = GBA_RTC->Read(address); + else + value = READ16LE(((uint16 *)&rom[address & 0x1FFFFFE])); + break; + case 13: + if(cpuEEPROMEnabled) + // no need to swap this + return eepromRead(address); + goto unreadable; + case 14: + if(cpuFlashEnabled | cpuSramEnabled) + // no need to swap this + return flashRead(address); + // default + default: + unreadable: + if(cpuDmaHack) { + value = cpuDmaLast & 0xFFFF; + } else { + if(armState) { + value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); + } else { + value = CPUReadHalfWordQuick(reg[15].I); + } + } + break; + } + + if(address & 1) { + value = (value >> 8) | (value << 24); + } + + return value; +} + +uint8 CPUReadByte(uint32 address) +{ + switch(address >> 24) { + case 0: + if (reg[15].I >> 24) { + if(address < 0x4000) { + return biosProtected[address & 3]; + } else goto unreadable; + } + return bios[address & 0x3FFF]; + case 2: + return workRAM[address & 0x3FFFF]; + case 3: + return internalRAM[address & 0x7fff]; + case 4: + if((address < 0x4000400) && ioReadable[address & 0x3ff]) + return ioMem[address & 0x3ff]; + else goto unreadable; + case 5: + return paletteRAM[address & 0x3ff]; + case 6: + address = (address & 0x1ffff); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return 0; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + return vram[address]; + case 7: + return oam[address & 0x3ff]; + case 8: + case 9: + case 10: + case 11: + case 12: + return rom[address & 0x1FFFFFF]; + case 13: + if(cpuEEPROMEnabled) + return eepromRead(address); + goto unreadable; + case 14: + if(cpuSramEnabled | cpuFlashEnabled) + return flashRead(address); + if(cpuEEPROMSensorEnabled) { + switch(address & 0x00008f00) { + case 0x8200: + //return systemGetSensorX() & 255; + case 0x8300: + //return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + //return systemGetSensorY() & 255; + case 0x8500: + //return systemGetSensorY() >> 8; + return(0); + } + } + // default + default: + unreadable: + if(cpuDmaHack) { + return cpuDmaLast & 0xFF; + } else { + if(armState) { + return CPUReadByteQuick(reg[15].I+(address & 3)); + } else { + return CPUReadByteQuick(reg[15].I+(address & 1)); + } + } + break; + } +} + +} diff --git a/mednafen/gba-09333/GBAinline.h b/mednafen/gba-09333/GBAinline.h new file mode 100644 index 0000000..92c5404 --- /dev/null +++ b/mednafen/gba-09333/GBAinline.h @@ -0,0 +1,315 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_GBAinline_H +#define VBA_GBAinline_H + +#include "Port.h" +#include "RTC.h" +#include "sram.h" + +namespace MDFN_IEN_GBA +{ + +#ifdef INCED_FROM_ARM_CPP +#define EXCLUDE_ARM_FROM_INLINE +#else +#define EXCLUDE_ARM_FROM_INLINE INLINE +#endif + +extern bool cpuSramEnabled; +extern bool cpuFlashEnabled; +extern bool cpuEEPROMEnabled; +extern bool cpuEEPROMSensorEnabled; +extern bool cpuDmaHack; +extern uint32 cpuDmaLast; + +typedef struct +{ + uint16 Value; + bool On; + int32 Ticks; + int32 Reload; + int32 ClockReload; + uint16 D; + uint16 CNT; +} GBATimer; + +extern GBATimer timers[4]; + +extern int cpuTotalTicks; + +#define ARM_PREFETCH \ + {\ + cpuPrefetch[0] = CPUReadMemoryQuick(armNextPC);\ + cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4);\ + } + +#define THUMB_PREFETCH \ + {\ + cpuPrefetch[0] = CPUReadHalfWordQuick(armNextPC);\ + cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2);\ + } + +#define ARM_PREFETCH_NEXT \ + cpuPrefetch[1] = CPUReadMemoryQuick(armNextPC+4); + +#define THUMB_PREFETCH_NEXT\ + cpuPrefetch[1] = CPUReadHalfWordQuick(armNextPC+2); + +#define CPUReadByteQuick(addr) \ + map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] + +#define CPUReadHalfWordQuick(addr) \ + READ16LE(((uint16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +#define CPUReadMemoryQuick(addr) \ + READ32LE(((uint32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +uint32 CPUReadMemory(uint32 address); + +uint32 CPUReadHalfWord(uint32 address); + +static INLINE uint16 CPUReadHalfWordSigned(uint32 address) +{ + uint16 value = CPUReadHalfWord(address); + if((address & 1)) + value = (int8)value; + return value; +} + +uint8 CPUReadByte(uint32 address); + +// Waitstates when accessing data +static EXCLUDE_ARM_FROM_INLINE int dataTicksAccesint16(uint32 address) // DATA 8/16bits NON SEQ +{ + int addr = (address>>24)&15; + int value = memoryWait[addr]; + + if (addr>=0x08) + { + busPrefetchCount=0; + busPrefetch=false; + } + else if (busPrefetch) + { + int waitState = value; + if (waitState>0) + waitState--; + waitState++; + busPrefetchCount = (busPrefetchCount<>(8-waitState)); + } + + return value; +} + +static EXCLUDE_ARM_FROM_INLINE int dataTicksAccesint32(uint32 address) // DATA 32bits NON SEQ +{ + int addr = (address>>24)&15; + int value = memoryWait32[addr]; + + if (addr>=0x08) + { + busPrefetchCount=0; + busPrefetch=false; + } + else if (busPrefetch) + { + int waitState = value; + if (waitState>0) + waitState--; + waitState++; + busPrefetchCount = (busPrefetchCount<>(8-waitState)); + } + + return value; +} + +static EXCLUDE_ARM_FROM_INLINE int dataTicksAccessSeq16(uint32 address)// DATA 8/16bits SEQ +{ + int addr = (address>>24)&15; + int value = memoryWaitSeq[addr]; + + if (addr>=0x08) + { + busPrefetchCount=0; + busPrefetch=false; + } + else if (busPrefetch) + { + int waitState = value; + if (waitState>0) + waitState--; + waitState++; + busPrefetchCount = (busPrefetchCount<>(8-waitState)); + } + + return value; +} + +static EXCLUDE_ARM_FROM_INLINE int dataTicksAccessSeq32(uint32 address)// DATA 32bits SEQ +{ + int addr = (address>>24)&15; + int value = memoryWaitSeq32[addr]; + + if (addr>=0x08) + { + busPrefetchCount=0; + busPrefetch=false; + } + else if (busPrefetch) + { + int waitState = value; + if (waitState>0) + waitState--; + waitState++; + busPrefetchCount = (busPrefetchCount<>(8-waitState)); + } + + return value; +} + +// Waitstates when executing opcode +static EXCLUDE_ARM_FROM_INLINE int codeTicksAccesint16(uint32 address) // THUMB NON SEQ +{ + int addr = (address>>24)&15; + + if ((addr>=0x08) && (addr<=0x0D)) + { + if ((busPrefetchCount&0x3) == 3) + { + busPrefetchCount=((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + return 0; + } + else + if (busPrefetchCount&0x1) + { + busPrefetchCount=((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + return memoryWaitSeq[addr]-1; + } + else + { + busPrefetchCount=0; + return memoryWait[addr]; + } + } + else + { + busPrefetchCount = 0; + return memoryWait[addr]; + } +} + +static EXCLUDE_ARM_FROM_INLINE int codeTicksAccesint32(uint32 address) // ARM NON SEQ +{ + int addr = (address>>24)&15; + + if ((addr>=0x08) && (addr<=0x0D)) + { + if (busPrefetchCount&0x1) + { + busPrefetchCount=((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + if (busPrefetchCount&0x1) + { + busPrefetchCount=((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + return 0; + } + else + { + busPrefetchCount = 0; + return memoryWaitSeq[addr]; + } + + } + else + { + busPrefetchCount = 0; + return memoryWait32[addr]; + } + } + else + { + busPrefetchCount = 0; + return memoryWait32[addr]; + } +} + +static EXCLUDE_ARM_FROM_INLINE int codeTicksAccessSeq16(uint32 address) // THUMB SEQ +{ + int addr = (address>>24)&15; + + if ((addr>=0x08) && (addr<=0x0D)) + { + if (busPrefetchCount&0x1) + { + busPrefetchCount=((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + return 0; + } + else + if (busPrefetchCount>0xFF) + { + busPrefetchCount=0; + return memoryWait[addr]; + } + else + return memoryWaitSeq[addr]; + } + else + { + busPrefetchCount = 0; + return memoryWaitSeq[addr]; + } +} + +static EXCLUDE_ARM_FROM_INLINE int codeTicksAccessSeq32(uint32 address) // ARM SEQ +{ + int addr = (address>>24)&15; + + if ((addr>=0x08) && (addr<=0x0D)) + { + if (busPrefetchCount&0x1) + { + busPrefetchCount=((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + if (busPrefetchCount&0x1) + { + busPrefetchCount=((busPrefetchCount&0xFF)>>1) | (busPrefetchCount&0xFFFFFF00); + return 0; + } + else + return memoryWaitSeq[addr]; + + } + else + if (busPrefetchCount>0xFF) + { + busPrefetchCount=0; + return memoryWait32[addr]; + } + else + return memoryWaitSeq32[addr]; + } + else + { + return memoryWaitSeq32[addr]; + } +} + +} + +#endif //VBA_GBAinline_H diff --git a/mednafen/gba-09333/Gfx.cpp b/mednafen/gba-09333/Gfx.cpp new file mode 100644 index 0000000..821f7cb --- /dev/null +++ b/mednafen/gba-09333/Gfx.cpp @@ -0,0 +1,1409 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "../mednafen.h" + +#include "Gfx.h" +#include "gfx-draw.h" + +namespace MDFN_IEN_GBA +{ + +int all_coeff[32] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 +}; + +uint32 AlphaClampLUT[64] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F +}; + + +MDFN_ALIGN(16) uint32 line0[512]; +MDFN_ALIGN(16) uint32 line1[512]; +MDFN_ALIGN(16) uint32 line2[512]; +MDFN_ALIGN(16) uint32 line3[512]; +MDFN_ALIGN(16) uint32 lineOBJ[512]; +MDFN_ALIGN(16) uint32 lineOBJWin[512]; +MDFN_ALIGN(16) uint32 lineMix[512]; + +bool gfxInWin0[512]; +bool gfxInWin1[512]; + +int gfxBG2Changed = 0; +int gfxBG3Changed = 0; + +int gfxBG2X = 0; +int gfxBG2Y = 0; +int gfxBG2LastX = 0; +int gfxBG2LastY = 0; +int gfxBG3X = 0; +int gfxBG3Y = 0; +int gfxBG3LastX = 0; +int gfxBG3LastY = 0; +int gfxLastVCOUNT = 0; + +void gfxDrawTextScreen(uint16 control, uint16 hofs, uint16 vofs, + uint32 *line) +{ + uint16 *palette = (uint16 *)paletteRAM; + uint8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000]; + uint16 *screenBase = (uint16 *)&vram[((control >> 8) & 0x1f) * 0x800]; + uint32 prio = ((control & 3)<<25) + 0x1000000; + int sizeX = 256; + int sizeY = 256; + switch((control >> 14) & 3) { + case 0: + break; + case 1: + sizeX = 512; + break; + case 2: + sizeY = 512; + break; + case 3: + sizeX = 512; + sizeY = 512; + break; + } + + int maskX = sizeX-1; + int maskY = sizeY-1; + + bool mosaicOn = (control & 0x40) ? true : false; + + int xxx = hofs & maskX; + int yyy = (vofs + VCOUNT) & maskY; + int mosaicX = (MOSAIC & 0x000F)+1; + int mosaicY = ((MOSAIC & 0x00F0)>>4)+1; + + if(mosaicOn) { + if((VCOUNT % mosaicY) != 0) { + mosaicY = (VCOUNT / mosaicY) * mosaicY; + yyy = (vofs + mosaicY) & maskY; + } + } + + if(yyy > 255 && sizeY > 256) { + yyy &= 255; + screenBase += 0x400; + if(sizeX > 256) + screenBase += 0x400; + } + + int yshift = ((yyy>>3)<<5); + if((control) & 0x80) + { + uint16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift; + for(int x = 0; x < 240; x++) { + uint16 data = READ16LE(screenSource); + + int tile = data & 0x3FF; + int tileX = (xxx & 7); + int tileY = yyy & 7; + + if(data & 0x0400) + tileX = 7 - tileX; + if(data & 0x0800) + tileY = 7 - tileY; + + uint8 color = charBase[tile * 64 + tileY * 8 + tileX]; + + line[x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000; + + if(data & 0x0400) { + if(tileX == 0) + screenSource++; + } else if(tileX == 7) + screenSource++; + xxx++; + if(xxx == 256) { + if(sizeX > 256) + screenSource = screenBase + 0x400 + yshift; + else { + screenSource = screenBase + yshift; + xxx = 0; + } + } else if(xxx >= sizeX) { + xxx = 0; + screenSource = screenBase + yshift; + } + } + } + else + { + uint16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) + yshift; + uint16 data = READ16LE(screenSource); + int tile = data & 0x3FF; + int pal = (READ16LE(screenSource)>>8) & 0xF0; + int tileXmatch = (data & 0x0400) ? 0 : 7; + + for(int x = 0; x < 240; x++) + { + int tileX = (xxx & 7); + int tileY = yyy & 7; + + if(data & 0x0400) + tileX = 7 - tileX; + if(data & 0x0800) + tileY = 7 - tileY; + + uint8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)]; + + if(tileX & 1) { + color = (color >> 4); + } else { + color &= 0x0F; + } + + line[x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000; + + if(tileX == tileXmatch) + { + screenSource++; + data = READ16LE(screenSource); + tile = data & 0x3FF; + pal = (READ16LE(screenSource)>>8) & 0xF0; + tileXmatch = (data & 0x0400) ? 0 : 7; + } + xxx++; + if(xxx == 256) + { + if(sizeX > 256) + screenSource = screenBase + 0x400 + yshift; + else + { + screenSource = screenBase + yshift; + xxx = 0; + } + data = READ16LE(screenSource); + tile = data & 0x3FF; + pal = (READ16LE(screenSource)>>8) & 0xF0; + tileXmatch = (data & 0x0400) ? 0 : 7; + } + else if(xxx >= sizeX) + { + xxx = 0; + screenSource = screenBase + yshift; + data = READ16LE(screenSource); + tile = data & 0x3FF; + pal = (READ16LE(screenSource)>>8) & 0xF0; + tileXmatch = (data & 0x0400) ? 0 : 7; + } + } + } + if(mosaicOn) + { + if(mosaicX > 1) + { + int m = 1; + for(int i = 0; i < 239; i++) + { + line[i+1] = line[i]; + m++; + if(m == mosaicX) + { + m = 1; + i++; + } + } + } + } +} + +void gfxDrawRotScreen(uint16 control, + uint16 x_l, uint16 x_h, + uint16 y_l, uint16 y_h, + uint16 pa, uint16 pb, + uint16 pc, uint16 pd, + int& currentX, int& currentY, + int changed, + uint32 *line) +{ + uint16 *palette = (uint16 *)paletteRAM; + uint8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000]; + uint8 *screenBase = (uint8 *)&vram[((control >> 8) & 0x1f) * 0x800]; + int prio = ((control & 3) << 25) + 0x1000000; + + int sizeX = 128; + int sizeY = 128; + switch((control >> 14) & 3) { + case 0: + break; + case 1: + sizeX = sizeY = 256; + break; + case 2: + sizeX = sizeY = 512; + break; + case 3: + sizeX = sizeY = 1024; + break; + } + + int dx = pa & 0x7FFF; + if(pa & 0x8000) + dx |= 0xFFFF8000; + int dmx = pb & 0x7FFF; + if(pb & 0x8000) + dmx |= 0xFFFF8000; + int dy = pc & 0x7FFF; + if(pc & 0x8000) + dy |= 0xFFFF8000; + int dmy = pd & 0x7FFF; + if(pd & 0x8000) + dmy |= 0xFFFF8000; + + if(VCOUNT == 0) + changed = 3; + + if(changed & 1) { + currentX = (x_l) | ((x_h & 0x07FF)<<16); + if(x_h & 0x0800) + currentX |= 0xF8000000; + } else { + currentX += dmx; + } + + if(changed & 2) { + currentY = (y_l) | ((y_h & 0x07FF)<<16); + if(y_h & 0x0800) + currentY |= 0xF8000000; + } else { + currentY += dmy; + } + + int realX = currentX; + int realY = currentY; + + if(control & 0x40) { + int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; + int y = (VCOUNT % mosaicY); + realX -= y*dmx; + realY -= y*dmy; + } + + int xxx = (realX >> 8); + int yyy = (realY >> 8); + + if(control & 0x2000) { + xxx %= sizeX; + yyy %= sizeY; + if(xxx < 0) + xxx += sizeX; + if(yyy < 0) + yyy += sizeY; + } + + if(control & 0x80) { + for(int x = 0; x < 240; x++) { + if(xxx < 0 || + yyy < 0 || + xxx >= sizeX || + yyy >= sizeY) { + line[x] = 0x80000000; + } else { + int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)]; + + int tileX = (xxx & 7); + int tileY = yyy & 7; + + uint8 color = charBase[(tile<<6) + (tileY<<3) + tileX]; + + line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000; + } + realX += dx; + realY += dy; + + xxx = (realX >> 8); + yyy = (realY >> 8); + + if(control & 0x2000) { + xxx %= sizeX; + yyy %= sizeY; + if(xxx < 0) + xxx += sizeX; + if(yyy < 0) + yyy += sizeY; + } + } + } else { + for(int x = 0; x < 240; x++) { + if(xxx < 0 || + yyy < 0 || + xxx >= sizeX || + yyy >= sizeY) { + line[x] = 0x80000000; + } else { + int tile = screenBase[(xxx>>3) + (yyy>>3)*(sizeX>>3)]; + + int tileX = (xxx & 7); + int tileY = yyy & 7; + + uint8 color = charBase[(tile<<6) + (tileY<<3) + tileX]; + + line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000; + } + realX += dx; + realY += dy; + + xxx = (realX >> 8); + yyy = (realY >> 8); + + if(control & 0x2000) { + xxx %= sizeX; + yyy %= sizeY; + if(xxx < 0) + xxx += sizeX; + if(yyy < 0) + yyy += sizeY; + } + } + } + + if(control & 0x40) { + int mosaicX = (MOSAIC & 0xF) + 1; + if(mosaicX > 1) { + int m = 1; + for(int i = 0; i < 239; i++) { + line[i+1] = line[i]; + m++; + if(m == mosaicX) { + m = 1; + i++; + } + } + } + } +} + +void gfxDrawRotScreen16Bit(uint16 control, + uint16 x_l, uint16 x_h, + uint16 y_l, uint16 y_h, + uint16 pa, uint16 pb, + uint16 pc, uint16 pd, + int& currentX, int& currentY, + int changed, + uint32 *line) +{ + uint16 *screenBase = (uint16 *)&vram[0]; + int prio = ((control & 3) << 25) + 0x1000000; + int sizeX = 240; + int sizeY = 160; + + int startX = (x_l) | ((x_h & 0x07FF)<<16); + if(x_h & 0x0800) + startX |= 0xF8000000; + int startY = (y_l) | ((y_h & 0x07FF)<<16); + if(y_h & 0x0800) + startY |= 0xF8000000; + + int dx = pa & 0x7FFF; + if(pa & 0x8000) + dx |= 0xFFFF8000; + int dmx = pb & 0x7FFF; + if(pb & 0x8000) + dmx |= 0xFFFF8000; + int dy = pc & 0x7FFF; + if(pc & 0x8000) + dy |= 0xFFFF8000; + int dmy = pd & 0x7FFF; + if(pd & 0x8000) + dmy |= 0xFFFF8000; + + if(VCOUNT == 0) + changed = 3; + + if(changed & 1) { + currentX = (x_l) | ((x_h & 0x07FF)<<16); + if(x_h & 0x0800) + currentX |= 0xF8000000; + } else + currentX += dmx; + + if(changed & 2) { + currentY = (y_l) | ((y_h & 0x07FF)<<16); + if(y_h & 0x0800) + currentY |= 0xF8000000; + } else { + currentY += dmy; + } + + int realX = currentX; + int realY = currentY; + + if(control & 0x40) { + int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; + int y = (VCOUNT % mosaicY); + realX -= y*dmx; + realY -= y*dmy; + } + + int xxx = (realX >> 8); + int yyy = (realY >> 8); + + for(int x = 0; x < 240; x++) { + if(xxx < 0 || + yyy < 0 || + xxx >= sizeX || + yyy >= sizeY) { + line[x] = 0x80000000; + } else { + line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio); + } + realX += dx; + realY += dy; + + xxx = (realX >> 8); + yyy = (realY >> 8); + } + + if(control & 0x40) { + int mosaicX = (MOSAIC & 0xF) + 1; + if(mosaicX > 1) { + int m = 1; + for(int i = 0; i < 239; i++) { + line[i+1] = line[i]; + m++; + if(m == mosaicX) { + m = 1; + i++; + } + } + } + } +} + +void gfxDrawRotScreen256(uint16 control, + uint16 x_l, uint16 x_h, + uint16 y_l, uint16 y_h, + uint16 pa, uint16 pb, + uint16 pc, uint16 pd, + int ¤tX, int& currentY, + int changed, + uint32 *line) +{ + uint16 *palette = (uint16 *)paletteRAM; + uint8 *screenBase = (DISPCNT & 0x0010) ? &vram[0xA000] : &vram[0x0000]; + int prio = ((control & 3) << 25) + 0x1000000; + int sizeX = 240; + int sizeY = 160; + + int startX = (x_l) | ((x_h & 0x07FF)<<16); + if(x_h & 0x0800) + startX |= 0xF8000000; + int startY = (y_l) | ((y_h & 0x07FF)<<16); + if(y_h & 0x0800) + startY |= 0xF8000000; + + int dx = pa & 0x7FFF; + if(pa & 0x8000) + dx |= 0xFFFF8000; + int dmx = pb & 0x7FFF; + if(pb & 0x8000) + dmx |= 0xFFFF8000; + int dy = pc & 0x7FFF; + if(pc & 0x8000) + dy |= 0xFFFF8000; + int dmy = pd & 0x7FFF; + if(pd & 0x8000) + dmy |= 0xFFFF8000; + + if(VCOUNT == 0) + changed = 3; + + if(changed & 1) { + currentX = (x_l) | ((x_h & 0x07FF)<<16); + if(x_h & 0x0800) + currentX |= 0xF8000000; + } else { + currentX += dmx; + } + + if(changed & 2) { + currentY = (y_l) | ((y_h & 0x07FF)<<16); + if(y_h & 0x0800) + currentY |= 0xF8000000; + } else { + currentY += dmy; + } + + int realX = currentX; + int realY = currentY; + + if(control & 0x40) { + int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; + int y = (VCOUNT / mosaicY) * mosaicY; + realX = startX + y*dmx; + realY = startY + y*dmy; + } + + int xxx = (realX >> 8); + int yyy = (realY >> 8); + + for(int x = 0; x < 240; x++) { + if(xxx < 0 || + yyy < 0 || + xxx >= sizeX || + yyy >= sizeY) { + line[x] = 0x80000000; + } else { + uint8 color = screenBase[yyy * 240 + xxx]; + + line[x] = color ? (READ16LE(&palette[color])|prio): 0x80000000; + } + realX += dx; + realY += dy; + + xxx = (realX >> 8); + yyy = (realY >> 8); + } + + if(control & 0x40) { + int mosaicX = (MOSAIC & 0xF) + 1; + if(mosaicX > 1) { + int m = 1; + for(int i = 0; i < 239; i++) { + line[i+1] = line[i]; + m++; + if(m == mosaicX) { + m = 1; + i++; + } + } + } + } +} + +void gfxDrawRotScreen16Bit160(uint16 control, + uint16 x_l, uint16 x_h, + uint16 y_l, uint16 y_h, + uint16 pa, uint16 pb, + uint16 pc, uint16 pd, + int& currentX, int& currentY, + int changed, + uint32 *line) +{ + uint16 *screenBase = (DISPCNT & 0x0010) ? (uint16 *)&vram[0xa000] : + (uint16 *)&vram[0]; + int prio = ((control & 3) << 25) + 0x1000000; + int sizeX = 160; + int sizeY = 128; + + int startX = (x_l) | ((x_h & 0x07FF)<<16); + if(x_h & 0x0800) + startX |= 0xF8000000; + int startY = (y_l) | ((y_h & 0x07FF)<<16); + if(y_h & 0x0800) + startY |= 0xF8000000; + + int dx = pa & 0x7FFF; + if(pa & 0x8000) + dx |= 0xFFFF8000; + int dmx = pb & 0x7FFF; + if(pb & 0x8000) + dmx |= 0xFFFF8000; + int dy = pc & 0x7FFF; + if(pc & 0x8000) + dy |= 0xFFFF8000; + int dmy = pd & 0x7FFF; + if(pd & 0x8000) + dmy |= 0xFFFF8000; + + if(VCOUNT == 0) + changed = 3; + + if(changed & 1) { + currentX = (x_l) | ((x_h & 0x07FF)<<16); + if(x_h & 0x0800) + currentX |= 0xF8000000; + } else { + currentX += dmx; + } + + if(changed & 2) { + currentY = (y_l) | ((y_h & 0x07FF)<<16); + if(y_h & 0x0800) + currentY |= 0xF8000000; + } else { + currentY += dmy; + } + + int realX = currentX; + int realY = currentY; + + if(control & 0x40) { + int mosaicY = ((MOSAIC & 0xF0)>>4) + 1; + int y = (VCOUNT / mosaicY) * mosaicY; + realX = startX + y*dmx; + realY = startY + y*dmy; + } + + int xxx = (realX >> 8); + int yyy = (realY >> 8); + + for(int x = 0; x < 240; x++) { + if(xxx < 0 || + yyy < 0 || + xxx >= sizeX || + yyy >= sizeY) { + line[x] = 0x80000000; + } else { + line[x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio); + } + realX += dx; + realY += dy; + + xxx = (realX >> 8); + yyy = (realY >> 8); + } + + if(control & 0x40) { + int mosaicX = (MOSAIC & 0xF) + 1; + if(mosaicX > 1) { + int m = 1; + for(int i = 0; i < 239; i++) { + line[i+1] = line[i]; + m++; + if(m == mosaicX) { + m = 1; + i++; + } + } + } + } +} + +void gfxDrawSprites(void) +{ + int m=0; + gfxClearArray(lineOBJ); + if(layerEnable & 0x1000) { + uint16 *sprites = (uint16 *)oam; + uint16 *spritePalette = &((uint16 *)paletteRAM)[256]; + int mosaicY = ((MOSAIC & 0xF000)>>12) + 1; + int mosaicX = ((MOSAIC & 0xF00)>>8) + 1; + + for(int i = 0; i < 128 ; i++) { + + uint16 a0 = READ16LE(sprites++); + uint16 a1 = READ16LE(sprites++); + uint16 a2 = READ16LE(sprites++); + sprites++; + + // ignore OBJ-WIN + if((a0 & 0x0c00) == 0x0800) + continue; + + int sizeY = 8; + int sizeX = 8; + + switch(((a0 >>12) & 0x0c)|(a1>>14)) { + case 0: + break; + case 1: + sizeX = sizeY = 16; + break; + case 2: + sizeX = sizeY = 32; + break; + case 3: + sizeX = sizeY = 64; + break; + case 4: + sizeX = 16; + break; + case 5: + sizeX = 32; + break; + case 6: + sizeX = 32; + sizeY = 16; + break; + case 7: + sizeX = 64; + sizeY = 32; + break; + case 8: + sizeY = 16; + break; + case 9: + sizeY = 32; + break; + case 10: + sizeX = 16; + sizeY = 32; + break; + case 11: + sizeX = 32; + sizeY = 64; + break; + default: + continue; + } + +#ifdef SPRITE_DEBUG + int maskX = sizeX-1; + int maskY = sizeY-1; +#endif + + int sy = (a0 & 255); + + if(sy > 160) + sy -= 256; + + if(a0 & 0x0100) { + int fieldX = sizeX; + int fieldY = sizeY; + if(a0 & 0x0200) { + fieldX <<= 1; + fieldY <<= 1; + } + + int t = VCOUNT - sy; + if((t >= 0) && (t < fieldY)) { + int sx = (a1 & 0x1FF); + if((sx < 240) || (((sx + fieldX) & 511) < 240)) { + // int t2 = t - (fieldY >> 1); + int rot = (a1 >> 9) & 0x1F; + uint16 *OAM = (uint16 *)oam; + int dx = READ16LE(&OAM[3 + (rot << 4)]); + if(dx & 0x8000) + dx |= 0xFFFF8000; + int dmx = READ16LE(&OAM[7 + (rot << 4)]); + if(dmx & 0x8000) + dmx |= 0xFFFF8000; + int dy = READ16LE(&OAM[11 + (rot << 4)]); + if(dy & 0x8000) + dy |= 0xFFFF8000; + int dmy = READ16LE(&OAM[15 + (rot << 4)]); + if(dmy & 0x8000) + dmy |= 0xFFFF8000; + + if(a0 & 0x1000) { + t -= (t % mosaicY); + } + + int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx + + t * dmx; + int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy + + t * dmy; + + uint32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); + + if(a0 & 0x2000) { + int c = (a2 & 0x3FF); + if((DISPCNT & 7) > 2 && (c < 512)) + continue; + int inc = 32; + if(DISPCNT & 0x40) + inc = sizeX >> 2; + else + c &= 0x3FE; + for(int x = 0; x < fieldX; x++) { + int xxx = realX >> 8; + int yyy = realY >> 8; + + if(xxx < 0 || xxx >= sizeX || + yyy < 0 || yyy >= sizeY || + sx >= 240); + else { + uint32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) + + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + + (xxx & 7))&0x7FFF)]; + if ((color==0) && (((prio >> 25)&3) < + ((lineOBJ[sx]>>25)&3))) { + lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { + lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + } + + if (a0 & 0x1000) { + m++; + if (m==mosaicX) + m=0; + } +#ifdef SPRITE_DEBUG + if(t == 0 || t == maskY || x == 0 || x == maskX) + lineOBJ[sx] = 0x001F; +#endif + } + sx = (sx+1)&511;; + realX += dx; + realY += dy; + } + } else { + int c = (a2 & 0x3FF); + if((DISPCNT & 7) > 2 && (c < 512)) + continue; + + int inc = 32; + if(DISPCNT & 0x40) + inc = sizeX >> 3; + int palette = (a2 >> 8) & 0xF0; + for(int x = 0; x < fieldX; x++) { + int xxx = realX >> 8; + int yyy = realY >> 8; + if(xxx < 0 || xxx >= sizeX || + yyy < 0 || yyy >= sizeY || + sx >= 240); + else { + uint32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) + + ((yyy & 7)<<2) + ((xxx >> 3)<<5) + + ((xxx & 7)>>1))&0x7FFF)]; + if(xxx & 1) + color >>= 4; + else + color &= 0x0F; + + if ((color==0) && (((prio >> 25)&3) < + ((lineOBJ[sx]>>25)&3))) { + lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { + lineOBJ[sx] = READ16LE(&spritePalette[palette+color]) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + } + } + if((a0 & 0x1000) && m) { + m++; + if (m==mosaicX) + m=0; + } + +#ifdef SPRITE_DEBUG + if(t == 0 || t == maskY || x == 0 || x == maskX) + lineOBJ[sx] = 0x001F; +#endif + sx = (sx+1)&511;; + realX += dx; + realY += dy; + + } + } + } + } + } else { + int t = VCOUNT - sy; + if((t >= 0) && (t < sizeY)) { + int sx = (a1 & 0x1FF); + if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) { + if(a0 & 0x2000) { + if(a1 & 0x2000) + t = sizeY - t - 1; + int c = (a2 & 0x3FF); + if((DISPCNT & 7) > 2 && (c < 512)) + continue; + + int inc = 32; + if(DISPCNT & 0x40) { + inc = sizeX >> 2; + } else { + c &= 0x3FE; + } + int xxx = 0; + if(a1 & 0x1000) + xxx = sizeX-1; + + if(a0 & 0x1000) { + t -= (t % mosaicY); + } + + int address = 0x10000 + ((((c+ (t>>3) * inc) << 5) + + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF); + + if(a1 & 0x1000) + xxx = 7; + uint32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); + + for(int xx = 0; xx < sizeX; xx++) { + if(sx < 240) { + uint8 color = vram[address]; + if ((color==0) && (((prio >> 25)&3) < + ((lineOBJ[sx]>>25)&3))) { + lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { + lineOBJ[sx] = READ16LE(&spritePalette[color]) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + } + + if (a0 & 0x1000) { + m++; + if (m==mosaicX) + m=0; + } + +#ifdef SPRITE_DEBUG + if(t == 0 || t == maskY || xx == 0 || xx == maskX) + lineOBJ[sx] = 0x001F; +#endif + } + + sx = (sx+1) & 511; + if(a1 & 0x1000) { + xxx--; + address--; + if(xxx == -1) { + address -= 56; + xxx = 7; + } + if(address < 0x10000) + address += 0x8000; + } else { + xxx++; + address++; + if(xxx == 8) { + address += 56; + xxx = 0; + } + if(address > 0x17fff) + address -= 0x8000; + } + } + } else { + if(a1 & 0x2000) + t = sizeY - t - 1; + int c = (a2 & 0x3FF); + if((DISPCNT & 7) > 2 && (c < 512)) + continue; + + int inc = 32; + if(DISPCNT & 0x40) { + inc = sizeX >> 3; + } + int xxx = 0; + if(a1 & 0x1000) + xxx = sizeX - 1; + + if(a0 & 0x1000) { + t -= (t % mosaicY); + } + + int address = 0x10000 + ((((c + (t>>3) * inc)<<5) + + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF); + uint32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); + int palette = (a2 >> 8) & 0xF0; + if(a1 & 0x1000) { + xxx = 7; + for(int xx = sizeX - 1; xx >= 0; xx--) { + if(sx < 240) { + uint8 color = vram[address]; + if(xx & 1) { + color = (color >> 4); + } else + color &= 0x0F; + + if ((color==0) && (((prio >> 25)&3) < + ((lineOBJ[sx]>>25)&3))) { + lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { + lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + } + } + if (a0 & 0x1000) { + m++; + if (m==mosaicX) + m=0; + } +#ifdef SPRITE_DEBUG + if(t == 0 || t == maskY || xx == 0 || xx == maskX) + lineOBJ[sx] = 0x001F; +#endif + sx = (sx+1) & 511; + xxx--; + if(!(xx & 1)) + address--; + if(xxx == -1) { + xxx = 7; + address -= 28; + } + if(address < 0x10000) + address += 0x8000; + } + } else { + for(int xx = 0; xx < sizeX; xx++) { + if(sx < 240) { + uint8 color = vram[address]; + if(xx & 1) { + color = (color >> 4); + } else + color &= 0x0F; + + if ((color==0) && (((prio >> 25)&3) < + ((lineOBJ[sx]>>25)&3))) { + lineOBJ[sx] = (lineOBJ[sx] & 0xF9FFFFFF) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + } else if((color) && (prio < (lineOBJ[sx]&0xFF000000))) { + lineOBJ[sx] = READ16LE(&spritePalette[palette + color]) | prio; + if((a0 & 0x1000) && m) + lineOBJ[sx]=(lineOBJ[sx-1] & 0xF9FFFFFF) | prio; + + } + } + if (a0 & 0x1000) { + m++; + if (m==mosaicX) + m=0; + } +#ifdef SPRITE_DEBUG + if(t == 0 || t == maskY || xx == 0 || xx == maskX) + lineOBJ[sx] = 0x001F; +#endif + sx = (sx+1) & 511; + xxx++; + if(xx & 1) + address++; + if(xxx == 8) { + address += 28; + xxx = 0; + } + if(address > 0x17fff) + address -= 0x8000; + } + } + } + } + } + } + } + } +} + +void gfxDrawOBJWin(void) +{ + gfxClearArray(lineOBJWin); + if(layerEnable & 0x8000) { + uint16 *sprites = (uint16 *)oam; + // uint16 *spritePalette = &((uint16 *)paletteRAM)[256]; + for(int i = 0; i < 128 ; i++) { + uint16 a0 = READ16LE(sprites++); + uint16 a1 = READ16LE(sprites++); + uint16 a2 = READ16LE(sprites++); + sprites++; + + // ignore non OBJ-WIN + if((a0 & 0x0c00) != 0x0800) + continue; + + int sizeY = 8; + int sizeX = 8; + + switch(((a0 >>12) & 0x0c)|(a1>>14)) { + case 0: + break; + case 1: + sizeX = sizeY = 16; + break; + case 2: + sizeX = sizeY = 32; + break; + case 3: + sizeX = sizeY = 64; + break; + case 4: + sizeX = 16; + break; + case 5: + sizeX = 32; + break; + case 6: + sizeX = 32; + sizeY = 16; + break; + case 7: + sizeX = 64; + sizeY = 32; + break; + case 8: + sizeY = 16; + break; + case 9: + sizeY = 32; + break; + case 10: + sizeX = 16; + sizeY = 32; + break; + case 11: + sizeX = 32; + sizeY = 64; + break; + default: + continue; + } + + int sy = (a0 & 255); + + if(sy > 160) + sy -= 256; + + if(a0 & 0x0100) { + int fieldX = sizeX; + int fieldY = sizeY; + if(a0 & 0x0200) { + fieldX <<= 1; + fieldY <<= 1; + } + + int t = VCOUNT - sy; + if((t >= 0) && (t < fieldY)) { + int sx = (a1 & 0x1FF); + if((sx < 240) || (((sx + fieldX) & 511) < 240)) { + // int t2 = t - (fieldY >> 1); + int rot = (a1 >> 9) & 0x1F; + uint16 *OAM = (uint16 *)oam; + int dx = READ16LE(&OAM[3 + (rot << 4)]); + if(dx & 0x8000) + dx |= 0xFFFF8000; + int dmx = READ16LE(&OAM[7 + (rot << 4)]); + if(dmx & 0x8000) + dmx |= 0xFFFF8000; + int dy = READ16LE(&OAM[11 + (rot << 4)]); + if(dy & 0x8000) + dy |= 0xFFFF8000; + int dmy = READ16LE(&OAM[15 + (rot << 4)]); + if(dmy & 0x8000) + dmy |= 0xFFFF8000; + + int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx + + t * dmx; + int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy + + t * dmy; + + // uint32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); + + if(a0 & 0x2000) { + int c = (a2 & 0x3FF); + if((DISPCNT & 7) > 2 && (c < 512)) + continue; + int inc = 32; + if(DISPCNT & 0x40) + inc = sizeX >> 2; + else + c &= 0x3FE; + for(int x = 0; x < fieldX; x++) { + int xxx = realX >> 8; + int yyy = realY >> 8; + + if(xxx < 0 || xxx >= sizeX || + yyy < 0 || yyy >= sizeY || + sx >= 240) { + } else { + uint32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) + + ((yyy & 7)<<3) + ((xxx >> 3)<<6) + + (xxx & 7))&0x7fff)]; + if(color) { + lineOBJWin[sx] = 1; + } + } + sx = (sx+1)&511;; + realX += dx; + realY += dy; + } + } else { + int c = (a2 & 0x3FF); + if((DISPCNT & 7) > 2 && (c < 512)) + continue; + + int inc = 32; + if(DISPCNT & 0x40) + inc = sizeX >> 3; + // int palette = (a2 >> 8) & 0xF0; + for(int x = 0; x < fieldX; x++) { + int xxx = realX >> 8; + int yyy = realY >> 8; + + // if(x == 0 || x == (sizeX-1) || + // t == 0 || t == (sizeY-1)) { + // lineOBJ[sx] = 0x001F | prio; + // } else { + if(xxx < 0 || xxx >= sizeX || + yyy < 0 || yyy >= sizeY || + sx >= 240){ + } else { + uint32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5) + + ((yyy & 7)<<2) + ((xxx >> 3)<<5) + + ((xxx & 7)>>1))&0x7fff)]; + if(xxx & 1) + color >>= 4; + else + color &= 0x0F; + + if(color) { + lineOBJWin[sx] = 1; + } + } + // } + sx = (sx+1)&511;; + realX += dx; + realY += dy; + } + } + } + } + } else { + int t = VCOUNT - sy; + if((t >= 0) && (t < sizeY)) { + int sx = (a1 & 0x1FF); + if(((sx < 240)||(((sx+sizeX)&511)<240)) && !(a0 & 0x0200)) { + if(a0 & 0x2000) { + if(a1 & 0x2000) + t = sizeY - t - 1; + int c = (a2 & 0x3FF); + if((DISPCNT & 7) > 2 && (c < 512)) + continue; + + int inc = 32; + if(DISPCNT & 0x40) { + inc = sizeX >> 2; + } else { + c &= 0x3FE; + } + int xxx = 0; + if(a1 & 0x1000) + xxx = sizeX-1; + int address = 0x10000 + ((((c+ (t>>3) * inc) << 5) + + ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff); + if(a1 & 0x1000) + xxx = 7; + // uint32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); + for(int xx = 0; xx < sizeX; xx++) { + if(sx < 240) { + uint8 color = vram[address]; + if(color) { + lineOBJWin[sx] = 1; + } + } + + sx = (sx+1) & 511; + if(a1 & 0x1000) { + xxx--; + address--; + if(xxx == -1) { + address -= 56; + xxx = 7; + } + if(address < 0x10000) + address += 0x8000; + } else { + xxx++; + address++; + if(xxx == 8) { + address += 56; + xxx = 0; + } + if(address > 0x17fff) + address -= 0x8000; + } + } + } else { + if(a1 & 0x2000) + t = sizeY - t - 1; + int c = (a2 & 0x3FF); + if((DISPCNT & 7) > 2 && (c < 512)) + continue; + + int inc = 32; + if(DISPCNT & 0x40) { + inc = sizeX >> 3; + } + int xxx = 0; + if(a1 & 0x1000) + xxx = sizeX - 1; + int address = 0x10000 + ((((c + (t>>3) * inc)<<5) + + ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff); + // uint32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6); + // int palette = (a2 >> 8) & 0xF0; + if(a1 & 0x1000) { + xxx = 7; + for(int xx = sizeX - 1; xx >= 0; xx--) { + if(sx < 240) { + uint8 color = vram[address]; + if(xx & 1) { + color = (color >> 4); + } else + color &= 0x0F; + + if(color) { + lineOBJWin[sx] = 1; + } + } + sx = (sx+1) & 511; + xxx--; + if(!(xx & 1)) + address--; + if(xxx == -1) { + xxx = 7; + address -= 28; + } + if(address < 0x10000) + address += 0x8000; + } + } else { + for(int xx = 0; xx < sizeX; xx++) { + if(sx < 240) { + uint8 color = vram[address]; + if(xx & 1) { + color = (color >> 4); + } else + color &= 0x0F; + + if(color) { + lineOBJWin[sx] = 1; + } + } + sx = (sx+1) & 511; + xxx++; + if(xx & 1) + address++; + if(xxx == 8) { + address += 28; + xxx = 0; + } + if(address > 0x17fff) + address -= 0x8000; + } + } + } + } + } + } + } + } +} + +} diff --git a/mednafen/gba-09333/Gfx.h b/mednafen/gba-09333/Gfx.h new file mode 100644 index 0000000..9bfa224 --- /dev/null +++ b/mednafen/gba-09333/Gfx.h @@ -0,0 +1,85 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_GFX_H +#define VBA_GFX_H + +#include "GBA.h" +#include "Gfx.h" +#include "Globals.h" + +#include "Port.h" + +namespace MDFN_IEN_GBA +{ + +//#define SPRITE_DEBUG + +void mode0RenderLine(); +void mode0RenderLineNoWindow(); +void mode0RenderLineAll(); + +void mode1RenderLine(); +void mode1RenderLineNoWindow(); +void mode1RenderLineAll(); + +void mode2RenderLine(); +void mode2RenderLineNoWindow(); +void mode2RenderLineAll(); + +void mode3RenderLine(); +void mode3RenderLineNoWindow(); +void mode3RenderLineAll(); + +void mode4RenderLine(); +void mode4RenderLineNoWindow(); +void mode4RenderLineAll(); + +void mode5RenderLine(); +void mode5RenderLineNoWindow(); +void mode5RenderLineAll(); + +extern int all_coeff[32]; +extern uint32 AlphaClampLUT[64]; +extern MDFN_ALIGN(16) uint32 line0[512]; +extern MDFN_ALIGN(16) uint32 line1[512]; +extern MDFN_ALIGN(16) uint32 line2[512]; +extern MDFN_ALIGN(16) uint32 line3[512]; +extern MDFN_ALIGN(16) uint32 lineOBJ[512]; +extern MDFN_ALIGN(16) uint32 lineOBJWin[512]; +extern MDFN_ALIGN(16) uint32 lineMix[512]; +extern bool gfxInWin0[512]; +extern bool gfxInWin1[512]; + +extern int gfxBG2Changed; +extern int gfxBG3Changed; + +extern int gfxBG2X; +extern int gfxBG2Y; +extern int gfxBG2LastX; +extern int gfxBG2LastY; +extern int gfxBG3X; +extern int gfxBG3Y; +extern int gfxBG3LastX; +extern int gfxBG3LastY; +extern int gfxLastVCOUNT; + +} + +#endif // VBA_GFX_H diff --git a/mednafen/gba-09333/Globals.cpp b/mednafen/gba-09333/Globals.cpp new file mode 100644 index 0000000..8b5ed26 --- /dev/null +++ b/mednafen/gba-09333/Globals.cpp @@ -0,0 +1,110 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" + +namespace MDFN_IEN_GBA +{ + +reg_pair reg[45]; +memoryMap map[256]; +bool ioReadable[0x400]; + +uint32 N_FLAG = 0; +bool C_FLAG = 0; +bool Z_FLAG = 0; +bool V_FLAG = 0; + +bool armState = true; +bool armIrqEnable = true; +uint32 armNextPC = 0x00000000; +int armMode = 0x1f; +uint32 stop = 0x08000568; +int saveType = 0; +bool useBios = false; +bool skipBios = false; +int frameSkip = 1; +bool speedup = false; +bool synchronize = true; +bool cpuDisableSfx = false; +bool cpuIsMultiBoot = false; +bool parseDebug = true; +int layerSettings = 0xff00; +int layerEnable = 0xff00; + +uint8 *bios = NULL; +uint8 *rom = NULL; +uint8 *internalRAM = NULL; +uint8 *workRAM = NULL; +uint8 *paletteRAM = NULL; +uint8 *vram = NULL; +uint8 *pix = NULL; +uint8 *oam = NULL; +uint8 *ioMem = NULL; + +uint16 DISPCNT = 0x0080; +uint16 DISPSTAT = 0x0000; +uint16 VCOUNT = 0x0000; +uint16 BG0CNT = 0x0000; +uint16 BG1CNT = 0x0000; +uint16 BG2CNT = 0x0000; +uint16 BG3CNT = 0x0000; + +uint16 BGHOFS[4]; +uint16 BGVOFS[4]; + +uint16 BG2PA = 0x0100; +uint16 BG2PB = 0x0000; +uint16 BG2PC = 0x0000; +uint16 BG2PD = 0x0100; +uint16 BG2X_L = 0x0000; +uint16 BG2X_H = 0x0000; +uint16 BG2Y_L = 0x0000; +uint16 BG2Y_H = 0x0000; +uint16 BG3PA = 0x0100; +uint16 BG3PB = 0x0000; +uint16 BG3PC = 0x0000; +uint16 BG3PD = 0x0100; +uint16 BG3X_L = 0x0000; +uint16 BG3X_H = 0x0000; +uint16 BG3Y_L = 0x0000; +uint16 BG3Y_H = 0x0000; +uint16 WIN0H = 0x0000; +uint16 WIN1H = 0x0000; +uint16 WIN0V = 0x0000; +uint16 WIN1V = 0x0000; +uint16 WININ = 0x0000; +uint16 WINOUT = 0x0000; +uint16 MOSAIC = 0x0000; +uint16 BLDMOD = 0x0000; +uint16 COLEV = 0x0000; +uint16 COLY = 0x0000; + +uint16 DMSAD_L[4] = {0}; +uint16 DMSAD_H[4] = {0}; +uint16 DMDAD_L[4] = {0}; +uint16 DMDAD_H[4] = {0}; +uint16 DMCNT_L[4] = {0}; +uint16 DMCNT_H[4] = {0}; + +uint16 P1 = 0xFFFF; +uint16 IE = 0x0000; +uint16 IF = 0x0000; +uint16 IME = 0x0000; + +} diff --git a/mednafen/gba-09333/Globals.h b/mednafen/gba-09333/Globals.h new file mode 100644 index 0000000..70dd1cf --- /dev/null +++ b/mednafen/gba-09333/Globals.h @@ -0,0 +1,132 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_GLOBALS_H +#define VBA_GLOBALS_H + +namespace MDFN_IEN_GBA +{ + +#define VERBOSE_SWI 1 +#define VERBOSE_UNALIGNED_MEMORY 2 +#define VERBOSE_ILLEGAL_WRITE 4 +#define VERBOSE_ILLEGAL_READ 8 +#define VERBOSE_DMA0 16 +#define VERBOSE_DMA1 32 +#define VERBOSE_DMA2 64 +#define VERBOSE_DMA3 128 +#define VERBOSE_UNDEFINED 256 +#define VERBOSE_AGBPRINT 512 + +extern reg_pair reg[45]; +extern bool ioReadable[0x400]; + +extern uint32 N_FLAG; +extern bool C_FLAG; +extern bool Z_FLAG; +extern bool V_FLAG; + +extern bool armState; +extern bool armIrqEnable; +extern uint32 armNextPC; +extern int armMode; +extern uint32 stop; +extern int saveType; +extern bool useBios; +extern bool skipBios; +extern int frameSkip; +extern bool speedup; +extern bool synchronize; +extern bool cpuDisableSfx; +extern bool cpuIsMultiBoot; +extern bool parseDebug; +extern int layerSettings; +extern int layerEnable; + +extern uint8 *bios; +extern uint8 *rom; +extern uint8 *internalRAM; +extern uint8 *workRAM; +extern uint8 *paletteRAM; +extern uint8 *vram; +extern uint8 *pix; +extern uint8 *oam; +extern uint8 *ioMem; + +extern uint16 DISPCNT; +extern uint16 DISPSTAT; +extern uint16 VCOUNT; +extern uint16 BG0CNT; +extern uint16 BG1CNT; +extern uint16 BG2CNT; +extern uint16 BG3CNT; + +extern uint16 BGHOFS[4]; +extern uint16 BGVOFS[4]; + +extern uint16 BG2PA; +extern uint16 BG2PB; +extern uint16 BG2PC; +extern uint16 BG2PD; +extern uint16 BG2X_L; +extern uint16 BG2X_H; +extern uint16 BG2Y_L; +extern uint16 BG2Y_H; +extern uint16 BG3PA; +extern uint16 BG3PB; +extern uint16 BG3PC; +extern uint16 BG3PD; +extern uint16 BG3X_L; +extern uint16 BG3X_H; +extern uint16 BG3Y_L; +extern uint16 BG3Y_H; +extern uint16 WIN0H; +extern uint16 WIN1H; +extern uint16 WIN0V; +extern uint16 WIN1V; +extern uint16 WININ; +extern uint16 WINOUT; +extern uint16 MOSAIC; +extern uint16 BLDMOD; +extern uint16 COLEV; +extern uint16 COLY; + +extern uint16 DMSAD_L[4]; +extern uint16 DMSAD_H[4]; +extern uint16 DMDAD_L[4]; +extern uint16 DMDAD_H[4]; +extern uint16 DMCNT_L[4]; +extern uint16 DMCNT_H[4]; + +extern uint16 TM0D; +extern uint16 TM0CNT; +extern uint16 TM1D; +extern uint16 TM1CNT; +extern uint16 TM2D; +extern uint16 TM2CNT; +extern uint16 TM3D; +extern uint16 TM3CNT; +extern uint16 P1; +extern uint16 IE; +extern uint16 IF; +extern uint16 IME; + +} + +#endif // VBA_GLOBALS_H diff --git a/mednafen/gba-09333/Makefile b/mednafen/gba-09333/Makefile new file mode 100644 index 0000000..bbc4ec6 --- /dev/null +++ b/mednafen/gba-09333/Makefile @@ -0,0 +1,644 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# src/gba/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/mednafen +pkgincludedir = $(includedir)/mednafen +pkglibdir = $(libdir)/mednafen +pkglibexecdir = $(libexecdir)/mednafen +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = x86_64-unknown-linux-gnu +host_triplet = x86_64-unknown-linux-gnu +target_triplet = x86_64-unknown-linux-gnu +subdir = src/gba +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/fcntl-o.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ + $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ + $(top_srcdir)/m4/inttypes-pri.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/uintmax_t.m4 \ + $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ + $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +AM_V_AR = $(am__v_AR_$(V)) +am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY)) +am__v_AR_0 = @echo " AR " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +libgba_a_AR = $(AR) $(ARFLAGS) +libgba_a_LIBADD = +am_libgba_a_OBJECTS = GBAinline.$(OBJEXT) arm.$(OBJEXT) \ + thumb.$(OBJEXT) bios.$(OBJEXT) eeprom.$(OBJEXT) \ + flash.$(OBJEXT) GBA.$(OBJEXT) Gfx.$(OBJEXT) Globals.$(OBJEXT) \ + Mode0.$(OBJEXT) Mode1.$(OBJEXT) Mode2.$(OBJEXT) \ + Mode3.$(OBJEXT) Mode4.$(OBJEXT) Mode5.$(OBJEXT) RTC.$(OBJEXT) \ + Sound.$(OBJEXT) sram.$(OBJEXT) +libgba_a_OBJECTS = $(am_libgba_a_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_$(V)) +am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) +am__v_CXX_0 = @echo " CXX " $@; +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_$(V)) +am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CXXLD_0 = @echo " CXXLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libgba_a_SOURCES) +DIST_SOURCES = $(libgba_a_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run aclocal-1.11 +ALLOCA = +ALSA_CFLAGS = +ALSA_LIBS = -lasound -lm -ldl -lpthread +AMTAR = $${TAR-tar} +AM_CFLAGS = -fsigned-char -Wall -Winline -Wshadow -Wempty-body -Wignored-qualifiers -fno-fast-math -fno-unsafe-math-optimizations -fno-aggressive-loop-optimizations -fomit-frame-pointer -finline-limit=6000 --param large-function-growth=800 --param inline-unit-growth=175 --param max-inline-insns-single=10000 -fno-strict-overflow +AM_CXXFLAGS = -fsigned-char -Wall -Winline -Wshadow -Wempty-body -Wignored-qualifiers -fno-fast-math -fno-unsafe-math-optimizations -fno-aggressive-loop-optimizations -fomit-frame-pointer -finline-limit=6000 --param large-function-growth=800 --param inline-unit-growth=175 --param max-inline-insns-single=10000 -fno-strict-overflow +AM_DEFAULT_VERBOSITY = 1 +AR = ar +AUTOCONF = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run autoconf +AUTOHEADER = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run autoheader +AUTOMAKE = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run automake-1.11 +AWK = gawk +BUILD_INCLUDED_LIBINTL = no +CATOBJEXT = .gmo +CC = gcc +CCAS = gcc +CCASDEPMODE = depmode=gcc3 +CCASFLAGS = -g -O2 +CCDEPMODE = depmode=gcc3 +CFLAGS = -g -O2 +CFLAG_VISIBILITY = -fvisibility=hidden +CPP = gcc -E +CPPFLAGS = +CXX = g++ +CXXCPP = g++ -E +CXXDEPMODE = depmode=gcc3 +CXXFLAGS = -g -O2 +CYGPATH_W = echo +DATADIRNAME = share +DEFS = -DLOCALEDIR=\"$(datadir)/locale\" -DHAVE_CONFIG_H -fno-unit-at-a-time +DEPDIR = .deps +DLLTOOL = false +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /usr/bin/grep -E +EXEEXT = +FGREP = /usr/bin/grep -F +GBA_EXTRA_FLAGS = -fno-unit-at-a-time +GENCAT = gencat +GETTEXT_MACRO_VERSION = 0.18 +GLIBC2 = yes +GLIBC21 = yes +GMSGFMT = /usr/bin/msgfmt +GMSGFMT_015 = /usr/bin/msgfmt +GREP = /usr/bin/grep +HAVE_ASPRINTF = 1 +HAVE_NEWLOCALE = 1 +HAVE_POSIX_PRINTF = 1 +HAVE_SNPRINTF = 1 +HAVE_VISIBILITY = 1 +HAVE_WPRINTF = 0 +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +INSTOBJEXT = .mo +INTLBISON = bison +INTLLIBS = +INTLOBJS = +INTL_DEFAULT_VERBOSITY = 1 +INTL_LIBTOOL_SUFFIX_PREFIX = +INTL_MACOSX_LIBS = +JACK_CFLAGS = +JACK_LIBS = -ljack -lpthread +LD = /usr/bin/ld -m elf_x86_64 +LDFLAGS = +LIBCDIO_CFLAGS = +LIBCDIO_LIBS = -lcdio -lm +LIBICONV = +LIBINTL = +LIBMULTITHREAD = -lpthread +LIBOBJS = +LIBPTH = +LIBPTH_PREFIX = +LIBS = -lsndfile -lcdio -lm -lz -lz -lasound -lm -ldl -lpthread -ljack -lpthread +LIBTHREAD = +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIPO = +LN_S = ln -s +LTLIBC = -lc +LTLIBICONV = +LTLIBINTL = +LTLIBMULTITHREAD = -lpthread +LTLIBOBJS = +LTLIBPTH = +LTLIBTHREAD = +MAKEINFO = ${SHELL} /home/squarepusher/Downloads/mednafen/missing --run makeinfo +MANIFEST_TOOL = : +MKDIR_P = /usr/bin/mkdir -p +MMX_CFLAGS = -mmmx +MSGFMT = /usr/bin/msgfmt +MSGFMT_015 = /usr/bin/msgfmt +MSGMERGE = /usr/bin/msgmerge +NM = /usr/bin/nm -B +NMEDIT = +OBJDUMP = objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = mednafen +PACKAGE_BUGREPORT = +PACKAGE_NAME = +PACKAGE_STRING = +PACKAGE_TARNAME = +PACKAGE_URL = +PACKAGE_VERSION = +PATH_SEPARATOR = : +PKG_CONFIG = /usr/bin/pkg-config +PKG_CONFIG_LIBDIR = +PKG_CONFIG_PATH = +POSUB = po +PRI_MACROS_BROKEN = 0 +RANLIB = ranlib +SDL_CFLAGS = -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT +SDL_CONFIG = /usr/bin/sdl-config +SDL_LIBS = -L/usr/lib -lSDL -lpthread +SED = /usr/bin/sed +SET_MAKE = +SHELL = /bin/sh +SNDFILE_CFLAGS = +SNDFILE_LIBS = -lsndfile +SNES_EXTRA_CXXFLAGS = +SNES_EXTRA_FLAGS = -Wno-unused -Wno-inline -Wno-shadow -Wno-sign-compare -Wno-ignored-qualifiers -Wno-uninitialized -Wno-parentheses -Wno-switch +SNES_PERF_EXTRA_CXXFLAGS = -funswitch-loops -fpredictive-commoning -fgcse-after-reload -ftree-vectorize -fipa-cp-clone -fno-stack-protector +SNES_PERF_EXTRA_FLAGS = -Wno-unused -Wno-inline -Wno-shadow -Wno-sign-compare -Wno-ignored-qualifiers -Wno-uninitialized -Wno-parentheses -Wno-switch +SSE2_CFLAGS = -msse2 +SSE3_CFLAGS = -msse3 +SSE_CFLAGS = -msse +STRIP = strip +TRIO_CFLAGS = +USE_INCLUDED_LIBINTL = no +USE_NLS = yes +VERSION = 0.9.33.3 +WARNING_FLAGS = -Wall -Winline -Wshadow -Wempty-body -Wignored-qualifiers +WINDRES = +WOE32 = no +WOE32DLL = no +XGETTEXT = /usr/bin/xgettext +XGETTEXT_015 = /usr/bin/xgettext +XGETTEXT_EXTRA_OPTIONS = +abs_builddir = /home/squarepusher/Downloads/mednafen/src/gba +abs_srcdir = /home/squarepusher/Downloads/mednafen/src/gba +abs_top_builddir = /home/squarepusher/Downloads/mednafen +abs_top_srcdir = /home/squarepusher/Downloads/mednafen +ac_ct_AR = ar +ac_ct_CC = gcc +ac_ct_CXX = g++ +ac_ct_DUMPBIN = +am__include = include +am__leading_dot = . +am__quote = +am__tar = $${TAR-tar} chof - "$$tardir" +am__untar = $${TAR-tar} xf - +bindir = ${exec_prefix}/bin +build = x86_64-unknown-linux-gnu +build_alias = +build_cpu = x86_64 +build_os = linux-gnu +build_vendor = unknown +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = x86_64-unknown-linux-gnu +host_alias = +host_cpu = x86_64 +host_os = linux-gnu +host_vendor = unknown +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /home/squarepusher/Downloads/mednafen/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = /usr/bin/mkdir -p +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /usr/local +program_transform_name = s,x,x, +psdir = ${docdir} +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target = x86_64-unknown-linux-gnu +target_alias = +target_cpu = x86_64 +target_os = linux-gnu +target_vendor = unknown +top_build_prefix = ../../ +top_builddir = ../.. +top_srcdir = ../.. +AUTOMAKE_OPTIONS = subdir-objects +DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_builddir)/include/blip -I$(top_srcdir)/src/hw_sound -I$(top_srcdir) +noinst_LIBRARIES = libgba.a +libgba_a_SOURCES = GBAinline.cpp arm.cpp thumb.cpp bios.cpp eeprom.cpp flash.cpp GBA.cpp Gfx.cpp Globals.cpp Mode0.cpp Mode1.cpp Mode2.cpp Mode3.cpp Mode4.cpp Mode5.cpp RTC.cpp Sound.cpp sram.cpp +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gba/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/gba/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libgba.a: $(libgba_a_OBJECTS) $(libgba_a_DEPENDENCIES) $(EXTRA_libgba_a_DEPENDENCIES) + $(AM_V_at)-rm -f libgba.a + $(AM_V_AR)$(libgba_a_AR) libgba.a $(libgba_a_OBJECTS) $(libgba_a_LIBADD) + $(AM_V_at)$(RANLIB) libgba.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/GBA.Po +include ./$(DEPDIR)/GBAinline.Po +include ./$(DEPDIR)/Gfx.Po +include ./$(DEPDIR)/Globals.Po +include ./$(DEPDIR)/Mode0.Po +include ./$(DEPDIR)/Mode1.Po +include ./$(DEPDIR)/Mode2.Po +include ./$(DEPDIR)/Mode3.Po +include ./$(DEPDIR)/Mode4.Po +include ./$(DEPDIR)/Mode5.Po +include ./$(DEPDIR)/RTC.Po +include ./$(DEPDIR)/Sound.Po +include ./$(DEPDIR)/arm.Po +include ./$(DEPDIR)/bios.Po +include ./$(DEPDIR)/eeprom.Po +include ./$(DEPDIR)/flash.Po +include ./$(DEPDIR)/sram.Po +include ./$(DEPDIR)/thumb.Po + +.cpp.o: + $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ + $(am__mv) $$depbase.Tpo $$depbase.Po +# $(AM_V_CXX)source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: + $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ + $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ + $(am__mv) $$depbase.Tpo $$depbase.Po +# $(AM_V_CXX)source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: + $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ + $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ + $(am__mv) $$depbase.Tpo $$depbase.Plo +# $(AM_V_CXX)source='$<' object='$@' libtool=yes \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/mednafen/gba-09333/Makefile.am b/mednafen/gba-09333/Makefile.am new file mode 100644 index 0000000..5bd66c4 --- /dev/null +++ b/mednafen/gba-09333/Makefile.am @@ -0,0 +1,6 @@ +AUTOMAKE_OPTIONS = subdir-objects +DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @GBA_EXTRA_FLAGS@ +DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_builddir)/include/blip -I$(top_srcdir)/src/hw_sound -I$(top_srcdir) + +noinst_LIBRARIES = libgba.a +libgba_a_SOURCES = GBAinline.cpp arm.cpp thumb.cpp bios.cpp eeprom.cpp flash.cpp GBA.cpp Gfx.cpp Globals.cpp Mode0.cpp Mode1.cpp Mode2.cpp Mode3.cpp Mode4.cpp Mode5.cpp RTC.cpp Sound.cpp sram.cpp diff --git a/mednafen/gba-09333/Makefile.in b/mednafen/gba-09333/Makefile.in new file mode 100644 index 0000000..debf9e3 --- /dev/null +++ b/mednafen/gba-09333/Makefile.in @@ -0,0 +1,644 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/gba +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cflags_gcc_option.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/fcntl-o.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ + $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ + $(top_srcdir)/m4/inttypes-pri.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/uintmax_t.m4 \ + $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/m4/wchar_t.m4 \ + $(top_srcdir)/m4/wint_t.m4 $(top_srcdir)/m4/xsize.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +libgba_a_AR = $(AR) $(ARFLAGS) +libgba_a_LIBADD = +am_libgba_a_OBJECTS = GBAinline.$(OBJEXT) arm.$(OBJEXT) \ + thumb.$(OBJEXT) bios.$(OBJEXT) eeprom.$(OBJEXT) \ + flash.$(OBJEXT) GBA.$(OBJEXT) Gfx.$(OBJEXT) Globals.$(OBJEXT) \ + Mode0.$(OBJEXT) Mode1.$(OBJEXT) Mode2.$(OBJEXT) \ + Mode3.$(OBJEXT) Mode4.$(OBJEXT) Mode5.$(OBJEXT) RTC.$(OBJEXT) \ + Sound.$(OBJEXT) sram.$(OBJEXT) +libgba_a_OBJECTS = $(am_libgba_a_OBJECTS) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libgba_a_SOURCES) +DIST_SOURCES = $(libgba_a_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AM_CFLAGS = @AM_CFLAGS@ +AM_CXXFLAGS = @AM_CXXFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = -DLOCALEDIR=\"$(datadir)/locale\" @DEFS@ @GBA_EXTRA_FLAGS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GBA_EXTRA_FLAGS = @GBA_EXTRA_FLAGS@ +GENCAT = @GENCAT@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIBC2 = @GLIBC2@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +HAVE_ASPRINTF = @HAVE_ASPRINTF@ +HAVE_NEWLOCALE = @HAVE_NEWLOCALE@ +HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@ +HAVE_SNPRINTF = @HAVE_SNPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WPRINTF = @HAVE_WPRINTF@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_DEFAULT_VERBOSITY = @INTL_DEFAULT_VERBOSITY@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +JACK_CFLAGS = @JACK_CFLAGS@ +JACK_LIBS = @JACK_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBCDIO_CFLAGS = @LIBCDIO_CFLAGS@ +LIBCDIO_LIBS = @LIBCDIO_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBPTH_PREFIX = @LIBPTH_PREFIX@ +LIBS = @LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBC = @LTLIBC@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MMX_CFLAGS = @MMX_CFLAGS@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SNDFILE_CFLAGS = @SNDFILE_CFLAGS@ +SNDFILE_LIBS = @SNDFILE_LIBS@ +SNES_EXTRA_CXXFLAGS = @SNES_EXTRA_CXXFLAGS@ +SNES_EXTRA_FLAGS = @SNES_EXTRA_FLAGS@ +SNES_PERF_EXTRA_CXXFLAGS = @SNES_PERF_EXTRA_CXXFLAGS@ +SNES_PERF_EXTRA_FLAGS = @SNES_PERF_EXTRA_FLAGS@ +SSE2_CFLAGS = @SSE2_CFLAGS@ +SSE3_CFLAGS = @SSE3_CFLAGS@ +SSE_CFLAGS = @SSE_CFLAGS@ +STRIP = @STRIP@ +TRIO_CFLAGS = @TRIO_CFLAGS@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WARNING_FLAGS = @WARNING_FLAGS@ +WINDRES = @WINDRES@ +WOE32 = @WOE32@ +WOE32DLL = @WOE32DLL@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = subdir-objects +DEFAULT_INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/intl -I$(top_builddir)/include/blip -I$(top_srcdir)/src/hw_sound -I$(top_srcdir) +noinst_LIBRARIES = libgba.a +libgba_a_SOURCES = GBAinline.cpp arm.cpp thumb.cpp bios.cpp eeprom.cpp flash.cpp GBA.cpp Gfx.cpp Globals.cpp Mode0.cpp Mode1.cpp Mode2.cpp Mode3.cpp Mode4.cpp Mode5.cpp RTC.cpp Sound.cpp sram.cpp +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gba/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/gba/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libgba.a: $(libgba_a_OBJECTS) $(libgba_a_DEPENDENCIES) $(EXTRA_libgba_a_DEPENDENCIES) + $(AM_V_at)-rm -f libgba.a + $(AM_V_AR)$(libgba_a_AR) libgba.a $(libgba_a_OBJECTS) $(libgba_a_LIBADD) + $(AM_V_at)$(RANLIB) libgba.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GBA.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GBAinline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Gfx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Globals.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mode0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mode1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mode2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mode3.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mode4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Mode5.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RTC.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Sound.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eeprom.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sram.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thumb.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/mednafen/gba-09333/Mode0.cpp b/mednafen/gba-09333/Mode0.cpp new file mode 100644 index 0000000..c9a08c2 --- /dev/null +++ b/mednafen/gba-09333/Mode0.cpp @@ -0,0 +1,558 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Globals.h" +#include "Gfx.h" +#include "gfx-draw.h" + +namespace MDFN_IEN_GBA +{ + +void mode0RenderLine() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + return; + } + + if(layerEnable & 0x0100) { + gfxDrawTextScreen(BG0CNT, BGHOFS[0], BGVOFS[0], line0); + } + + if(layerEnable & 0x0200) { + gfxDrawTextScreen(BG1CNT, BGHOFS[1], BGVOFS[1], line1); + } + + if(layerEnable & 0x0400) { + gfxDrawTextScreen(BG2CNT, BGHOFS[2], BGVOFS[2], line2); + } + + if(layerEnable & 0x0800) { + gfxDrawTextScreen(BG3CNT, BGHOFS[3], BGVOFS[3], line3); + } + + gfxDrawSprites(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + + if(line0[x] < color) { + color = line0[x]; + top = 0x01; + } + + if(line1[x] < (color & 0xFF000000)) { + color = line1[x]; + top = 0x02; + } + + if(line2[x] < (color & 0xFF000000)) { + color = line2[x]; + top = 0x04; + } + + if(line3[x] < (color & 0xFF000000)) { + color = line3[x]; + top = 0x08; + } + + if(lineOBJ[x] < (color & 0xFF000000)) { + color = lineOBJ[x]; + top = 0x10; + } + + if((top & 0x10) && (color & 0x00010000)) { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line0[x] < (back & 0xFF000000)) { + back = line0[x]; + top2 = 0x01; + } + + if(line1[x] < (back & 0xFF000000)) { + back = line1[x]; + top2 = 0x02; + } + + if(line2[x] < (back & 0xFF000000)) { + back = line2[x]; + top2 = 0x04; + } + + if(line3[x] < (back & 0xFF000000)) { + back = line3[x]; + top2 = 0x08; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } +} + +void mode0RenderLineNoWindow() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + return; + } + + if(layerEnable & 0x0100) { + gfxDrawTextScreen(BG0CNT, BGHOFS[0], BGVOFS[0], line0); + } + + if(layerEnable & 0x0200) { + gfxDrawTextScreen(BG1CNT, BGHOFS[1], BGVOFS[1], line1); + } + + if(layerEnable & 0x0400) { + gfxDrawTextScreen(BG2CNT, BGHOFS[2], BGVOFS[2], line2); + } + + if(layerEnable & 0x0800) { + gfxDrawTextScreen(BG3CNT, BGHOFS[3], BGVOFS[3], line3); + } + + gfxDrawSprites(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + int effect = (BLDMOD >> 6) & 3; + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + + if(line0[x] < color) { + color = line0[x]; + top = 0x01; + } + + if(line1[x] < (color & 0xFF000000)) { + color = line1[x]; + top = 0x02; + } + + if(line2[x] < (color & 0xFF000000)) { + color = line2[x]; + top = 0x04; + } + + if(line3[x] < (color & 0xFF000000)) { + color = line3[x]; + top = 0x08; + } + + if(lineOBJ[x] < (color & 0xFF000000)) { + color = lineOBJ[x]; + top = 0x10; + } + + if(!(color & 0x00010000)) { + switch(effect) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = backdrop; + uint8 top2 = 0x20; + if(line0[x] < back) { + if(top != 0x01) { + back = line0[x]; + top2 = 0x01; + } + } + + if(line1[x] < (back & 0xFF000000)) { + if(top != 0x02) { + back = line1[x]; + top2 = 0x02; + } + } + + if(line2[x] < (back & 0xFF000000)) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if(line3[x] < (back & 0xFF000000)) { + if(top != 0x08) { + back = line3[x]; + top2 = 0x08; + } + } + + if(lineOBJ[x] < (back & 0xFF000000)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line0[x] < back) { + back = line0[x]; + top2 = 0x01; + } + + if(line1[x] < (back & 0xFF000000)) { + back = line1[x]; + top2 = 0x02; + } + + if(line2[x] < (back & 0xFF000000)) { + back = line2[x]; + top2 = 0x04; + } + + if(line3[x] < (back & 0xFF000000)) { + back = line3[x]; + top2 = 0x08; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } +} + +void mode0RenderLineAll() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + return; + } + + bool inWindow0 = false; + bool inWindow1 = false; + + if(layerEnable & 0x2000) { + uint8 v0 = WIN0V >> 8; + uint8 v1 = WIN0V & 255; + inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1); + } + if(layerEnable & 0x4000) { + uint8 v0 = WIN1V >> 8; + uint8 v1 = WIN1V & 255; + inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1); + } + + if((layerEnable & 0x0100)) { + gfxDrawTextScreen(BG0CNT, BGHOFS[0], BGVOFS[0], line0); + } + + if((layerEnable & 0x0200)) { + gfxDrawTextScreen(BG1CNT, BGHOFS[1], BGVOFS[1], line1); + } + + if((layerEnable & 0x0400)) { + gfxDrawTextScreen(BG2CNT, BGHOFS[2], BGVOFS[2], line2); + } + + if((layerEnable & 0x0800)) { + gfxDrawTextScreen(BG3CNT, BGHOFS[3], BGVOFS[3], line3); + } + + gfxDrawSprites(); + gfxDrawOBJWin(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + uint8 inWin0Mask = WININ & 0xFF; + uint8 inWin1Mask = WININ >> 8; + uint8 outMask = WINOUT & 0xFF; + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + uint8 mask = outMask; + + if(!(lineOBJWin[x] & 0x80000000)) { + mask = WINOUT >> 8; + } + + if(inWindow1) { + if(gfxInWin1[x]) + mask = inWin1Mask; + } + + if(inWindow0) { + if(gfxInWin0[x]) { + mask = inWin0Mask; + } + } + + if((mask & 1) && (line0[x] < color)) { + color = line0[x]; + top = 0x01; + } + + if((mask & 2) && (line1[x] < (color & 0xFF000000))) { + color = line1[x]; + top = 0x02; + } + + if((mask & 4) && (line2[x] < (color & 0xFF000000))) { + color = line2[x]; + top = 0x04; + } + + if((mask & 8) && (line3[x] < (color & 0xFF000000))) { + color = line3[x]; + top = 0x08; + } + + if((mask & 16) && (lineOBJ[x] < (color & 0xFF000000))) { + color = lineOBJ[x]; + top = 0x10; + } + + // special FX on in the window + if(mask & 32) { + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = backdrop; + uint8 top2 = 0x20; + if((mask & 1) && line0[x] < (back & 0xFF000000)) { + if(top != 0x01) { + back = line0[x]; + top2 = 0x01; + } + } + + if((mask & 2) && line1[x] < (back & 0xFF000000)) { + if(top != 0x02) { + back = line1[x]; + top2 = 0x02; + } + } + + if((mask & 4) && line2[x] < (back & 0xFF000000)) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if((mask & 8) && line3[x] < (back & 0xFF000000)) { + if(top != 0x08) { + back = line3[x]; + top2 = 0x08; + } + } + + if((mask & 16) && lineOBJ[x] < (back & 0xFF000000)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 1) && (line0[x] < (back & 0xFF000000))) { + back = line0[x]; + top2 = 0x01; + } + + if((mask & 2) && (line1[x] < (back & 0xFF000000))) { + back = line1[x]; + top2 = 0x02; + } + + if((mask & 4) && (line2[x] < (back & 0xFF000000))) { + back = line2[x]; + top2 = 0x04; + } + + if((mask & 8) && (line3[x] < (back & 0xFF000000))) { + back = line3[x]; + top2 = 0x08; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + } else if(color & 0x00010000) { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 1) && (line0[x] < (back & 0xFF000000))) { + back = line0[x]; + top2 = 0x01; + } + + if((mask & 2) && (line1[x] < (back & 0xFF000000))) { + back = line1[x]; + top2 = 0x02; + } + + if((mask & 4) && (line2[x] < (back & 0xFF000000))) { + back = line2[x]; + top2 = 0x04; + } + + if((mask & 8) && (line3[x] < (back & 0xFF000000))) { + back = line3[x]; + top2 = 0x08; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } +} + +} diff --git a/mednafen/gba-09333/Mode1.cpp b/mednafen/gba-09333/Mode1.cpp new file mode 100644 index 0000000..0d19438 --- /dev/null +++ b/mednafen/gba-09333/Mode1.cpp @@ -0,0 +1,519 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Globals.h" +#include "Gfx.h" +#include "gfx-draw.h" + +namespace MDFN_IEN_GBA +{ + +void mode1RenderLine() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + if(layerEnable & 0x0100) { + gfxDrawTextScreen(BG0CNT, BGHOFS[0], BGVOFS[0], line0); + } + + if(layerEnable & 0x0200) { + gfxDrawTextScreen(BG1CNT, BGHOFS[1], BGVOFS[1], line1); + } + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, + BG2PA, BG2PB, BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, line2); + } + + gfxDrawSprites(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + + if(line0[x] < color) { + color = line0[x]; + top = 0x01; + } + + if(line1[x] < (color & 0xFF000000)) { + color = line1[x]; + top = 0x02; + } + + if(line2[x] < (color & 0xFF000000)) { + color = line2[x]; + top = 0x04; + } + + if(lineOBJ[x] < (color & 0xFF000000)) { + color = lineOBJ[x]; + top = 0x10; + } + + if((top & 0x10) && (color & 0x00010000)) { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line0[x] < (back & 0xFF000000)) { + back = line0[x]; + top2 = 0x01; + } + + if(line1[x] < (back & 0xFF000000)) { + back = line1[x]; + top2 = 0x02; + } + + if(line2[x] < (back & 0xFF000000)) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode1RenderLineNoWindow() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + if(layerEnable & 0x0100) { + gfxDrawTextScreen(BG0CNT, BGHOFS[0], BGVOFS[0], line0); + } + + + if(layerEnable & 0x0200) { + gfxDrawTextScreen(BG1CNT, BGHOFS[1], BGVOFS[1], line1); + } + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, + BG2PA, BG2PB, BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, line2); + } + + gfxDrawSprites(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + + if(line0[x] < color) { + color = line0[x]; + top = 0x01; + } + + if(line1[x] < (color & 0xFF000000)) { + color = line1[x]; + top = 0x02; + } + + if(line2[x] < (color & 0xFF000000)) { + color = line2[x]; + top = 0x04; + } + + if(lineOBJ[x] < (color & 0xFF000000)) { + color = lineOBJ[x]; + top = 0x10; + } + + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = backdrop; + uint8 top2 = 0x20; + if(line0[x] < (back & 0xFF000000)) { + if(top != 0x01) { + back = line0[x]; + top2 = 0x01; + } + } + + if(line1[x] < (back & 0xFF000000)) { + if(top != 0x02) { + back = line1[x]; + top2 = 0x02; + } + } + + if(line2[x] < (back & 0xFF000000)) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if(lineOBJ[x] < (back & 0xFF000000)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line0[x] < (back & 0xFF000000)) { + back = line0[x]; + top2 = 0x01; + } + + if(line1[x] < (back & 0xFF000000)) { + back = line1[x]; + top2 = 0x02; + } + + if(line2[x] < (back & 0xFF000000)) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode1RenderLineAll() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + bool inWindow0 = false; + bool inWindow1 = false; + + if(layerEnable & 0x2000) { + uint8 v0 = WIN0V >> 8; + uint8 v1 = WIN0V & 255; + inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1); + } + if(layerEnable & 0x4000) { + uint8 v0 = WIN1V >> 8; + uint8 v1 = WIN1V & 255; + inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1); + } + + if(layerEnable & 0x0100) { + gfxDrawTextScreen(BG0CNT, BGHOFS[0], BGVOFS[0], line0); + } + + if(layerEnable & 0x0200) { + gfxDrawTextScreen(BG1CNT, BGHOFS[1], BGVOFS[1], line1); + } + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, + BG2PA, BG2PB, BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, line2); + } + + gfxDrawSprites(); + gfxDrawOBJWin(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + uint8 inWin0Mask = WININ & 0xFF; + uint8 inWin1Mask = WININ >> 8; + uint8 outMask = WINOUT & 0xFF; + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + uint8 mask = outMask; + + if(!(lineOBJWin[x] & 0x80000000)) { + mask = WINOUT >> 8; + } + + if(inWindow1) { + if(gfxInWin1[x]) + mask = inWin1Mask; + } + + if(inWindow0) { + if(gfxInWin0[x]) { + mask = inWin0Mask; + } + } + + if(line0[x] < color && (mask & 1)) { + color = line0[x]; + top = 0x01; + } + + if(line1[x] < (color & 0xFF000000) && (mask & 2)) { + color = line1[x]; + top = 0x02; + } + + if(line2[x] < (color & 0xFF000000) && (mask & 4)) { + color = line2[x]; + top = 0x04; + } + + if(lineOBJ[x] < (color & 0xFF000000) && (mask & 16)) { + color = lineOBJ[x]; + top = 0x10; + } + + // special FX on the window + if(mask & 32) { + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = backdrop; + uint8 top2 = 0x20; + if((mask & 1) && line0[x] < (back & 0xFF000000)) { + if(top != 0x01) { + back = line0[x]; + top2 = 0x01; + } + } + + if((mask & 2) && line1[x] < (back & 0xFF000000)) { + if(top != 0x02) { + back = line1[x]; + top2 = 0x02; + } + } + + if((mask & 4) && line2[x] < (back & 0xFF000000)) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if((mask & 16) && lineOBJ[x] < (back & 0xFF000000)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 1) && line0[x] < (back & 0xFF000000)) { + back = line0[x]; + top2 = 0x01; + } + + if((mask & 2) && line1[x] < (back & 0xFF000000)) { + back = line1[x]; + top2 = 0x02; + } + + if((mask & 4) && line2[x] < (back & 0xFF000000)) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + } else if(color & 0x00010000) { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 1) && line0[x] < (back & 0xFF000000)) { + back = line0[x]; + top2 = 0x01; + } + + if((mask & 2) && line1[x] < (back & 0xFF000000)) { + back = line1[x]; + top2 = 0x02; + } + + if((mask & 4) && line2[x] < (back & 0xFF000000)) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +} diff --git a/mednafen/gba-09333/Mode2.cpp b/mednafen/gba-09333/Mode2.cpp new file mode 100644 index 0000000..3a6e7cb --- /dev/null +++ b/mednafen/gba-09333/Mode2.cpp @@ -0,0 +1,484 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Globals.h" +#include "Gfx.h" +#include "gfx-draw.h" + +namespace MDFN_IEN_GBA +{ + +void mode2RenderLine() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, + BG2PA, BG2PB, BG2PC, BG2PD, gfxBG2X, gfxBG2Y, + changed, line2); + } + + if(layerEnable & 0x0800) { + int changed = gfxBG3Changed; + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen(BG3CNT, BG3X_L, BG3X_H, BG3Y_L, BG3Y_H, + BG3PA, BG3PB, BG3PC, BG3PD, gfxBG3X, gfxBG3Y, + changed, line3); + } + + gfxDrawSprites(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + + + if(line2[x] < (color & 0xFF000000)) { + color = line2[x]; + top = 0x04; + } + + if(line3[x] < (color & 0xFF000000)) { + color = line3[x]; + top = 0x08; + } + + if(lineOBJ[x] < (color & 0xFF000000)) { + color = lineOBJ[x]; + top = 0x10; + } + + if((top & 0x10) && (color & 0x00010000)) { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line2[x] < (back & 0xFF000000)) { + back = line2[x]; + top2 = 0x04; + } + + if(line3[x] < (back & 0xFF000000)) { + back = line3[x]; + top2 = 0x08; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxBG3Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode2RenderLineNoWindow() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, + BG2PA, BG2PB, BG2PC, BG2PD, gfxBG2X, gfxBG2Y, + changed, line2); + } + + if(layerEnable & 0x0800) { + int changed = gfxBG3Changed; + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen(BG3CNT, BG3X_L, BG3X_H, BG3Y_L, BG3Y_H, + BG3PA, BG3PB, BG3PC, BG3PD, gfxBG3X, gfxBG3Y, + changed, line3); + } + + gfxDrawSprites(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + + + if(line2[x] < (color & 0xFF000000)) { + color = line2[x]; + top = 0x04; + } + + if(line3[x] < (color & 0xFF000000)) { + color = line3[x]; + top = 0x08; + } + + if(lineOBJ[x] < (color & 0xFF000000)) { + color = lineOBJ[x]; + top = 0x10; + } + + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line2[x] < (back & 0xFF000000)) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if(line3[x] < (back & 0xFF000000)) { + if(top != 0x08) { + back = line3[x]; + top2 = 0x08; + } + } + + if(lineOBJ[x] < (back & 0xFF000000)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line2[x] < (back & 0xFF000000)) { + back = line2[x]; + top2 = 0x04; + } + + if(line3[x] < (back & 0xFF000000)) { + back = line3[x]; + top2 = 0x08; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxBG3Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode2RenderLineAll() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + bool inWindow0 = false; + bool inWindow1 = false; + + if(layerEnable & 0x2000) { + uint8 v0 = WIN0V >> 8; + uint8 v1 = WIN0V & 255; + inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1); + } + if(layerEnable & 0x4000) { + uint8 v0 = WIN1V >> 8; + uint8 v1 = WIN1V & 255; + inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1); + } + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, + BG2PA, BG2PB, BG2PC, BG2PD, gfxBG2X, gfxBG2Y, + changed, line2); + } + + if(layerEnable & 0x0800) { + int changed = gfxBG3Changed; + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen(BG3CNT, BG3X_L, BG3X_H, BG3Y_L, BG3Y_H, + BG3PA, BG3PB, BG3PC, BG3PD, gfxBG3X, gfxBG3Y, + changed, line3); + } + + gfxDrawSprites(); + gfxDrawOBJWin(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + uint8 inWin0Mask = WININ & 0xFF; + uint8 inWin1Mask = WININ >> 8; + uint8 outMask = WINOUT & 0xFF; + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + uint8 mask = outMask; + + if(!(lineOBJWin[x] & 0x80000000)) { + mask = WINOUT >> 8; + } + + if(inWindow1) { + if(gfxInWin1[x]) + mask = inWin1Mask; + } + + if(inWindow0) { + if(gfxInWin0[x]) { + mask = inWin0Mask; + } + } + + if(line2[x] < color && (mask & 4)) { + color = line2[x]; + top = 0x04; + } + + if(line3[x] < (color & 0xFF000000) && (mask & 8)) { + color = line3[x]; + top = 0x08; + } + + if(lineOBJ[x] < (color & 0xFF000000) && (mask & 16)) { + color = lineOBJ[x]; + top = 0x10; + } + + if(mask & 32) { + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if((mask & 8) && line3[x] < (back & 0xFF000000)) { + if(top != 0x08) { + back = line3[x]; + top2 = 0x08; + } + } + + if((mask & 16) && lineOBJ[x] < (back & 0xFF000000)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if((mask & 8) && line3[x] < (back & 0xFF000000)) { + back = line3[x]; + top2 = 0x08; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + } else if(color & 0x00010000) { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if((mask & 8) && line3[x] < (back & 0xFF000000)) { + back = line3[x]; + top2 = 0x08; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxBG3Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +} diff --git a/mednafen/gba-09333/Mode3.cpp b/mednafen/gba-09333/Mode3.cpp new file mode 100644 index 0000000..ff29aa0 --- /dev/null +++ b/mednafen/gba-09333/Mode3.cpp @@ -0,0 +1,411 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Globals.h" +#include "Gfx.h" +#include "gfx-draw.h" + +namespace MDFN_IEN_GBA +{ + +void mode3RenderLine() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen16Bit(BG2CNT, BG2X_L, BG2X_H, + BG2Y_L, BG2Y_H, BG2PA, BG2PB, + BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, + line2); + } + + gfxDrawSprites(); + + uint32 background = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = background; + uint8 top = 0x20; + + if(line2[x] < color) { + color = line2[x]; + top = 0x04; + } + + if((uint8)(lineOBJ[x]>>24) < (uint8)(color >>24)) { + color = lineOBJ[x]; + top = 0x10; + } + + if((top & 0x10) && (color & 0x00010000)) { + // semi-transparent OBJ + uint32 back = background; + uint8 top2 = 0x20; + + if(line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode3RenderLineNoWindow() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen16Bit(BG2CNT, BG2X_L, BG2X_H, + BG2Y_L, BG2Y_H, BG2PA, BG2PB, + BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, + line2); + } + + gfxDrawSprites(); + + uint32 background = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = background; + uint8 top = 0x20; + + if(line2[x] < color) { + color = line2[x]; + top = 0x04; + } + + if((uint8)(lineOBJ[x]>>24) < (uint8)(color >>24)) { + color = lineOBJ[x]; + top = 0x10; + } + + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = background; + uint8 top2 = 0x20; + + if(line2[x] < back) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if((uint8)(lineOBJ[x]>>24) < (uint8)(back >> 24)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = background; + uint8 top2 = 0x20; + + if(line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode3RenderLineAll() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x80) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + bool inWindow0 = false; + bool inWindow1 = false; + + if(layerEnable & 0x2000) { + uint8 v0 = WIN0V >> 8; + uint8 v1 = WIN0V & 255; + inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1); + } + if(layerEnable & 0x4000) { + uint8 v0 = WIN1V >> 8; + uint8 v1 = WIN1V & 255; + inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1); + } + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen16Bit(BG2CNT, BG2X_L, BG2X_H, + BG2Y_L, BG2Y_H, BG2PA, BG2PB, + BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, + line2); + } + + gfxDrawSprites(); + gfxDrawOBJWin(); + + uint8 inWin0Mask = WININ & 0xFF; + uint8 inWin1Mask = WININ >> 8; + uint8 outMask = WINOUT & 0xFF; + + uint32 background = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = background; + uint8 top = 0x20; + uint8 mask = outMask; + + if(!(lineOBJWin[x] & 0x80000000)) { + mask = WINOUT >> 8; + } + + if(inWindow1) { + if(gfxInWin1[x]) + mask = inWin1Mask; + } + + if(inWindow0) { + if(gfxInWin0[x]) { + mask = inWin0Mask; + } + } + + if((mask & 4) && (line2[x] < color)) { + color = line2[x]; + top = 0x04; + } + + if((mask & 16) && ((uint8)(lineOBJ[x]>>24) < (uint8)(color >>24))) { + color = lineOBJ[x]; + top = 0x10; + } + + if(mask & 32) { + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = background; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if((mask & 16) && (uint8)(lineOBJ[x]>>24) < (uint8)(back >> 24)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = background; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + } else if(color & 0x00010000) { + // semi-transparent OBJ + uint32 back = background; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +} diff --git a/mednafen/gba-09333/Mode4.cpp b/mednafen/gba-09333/Mode4.cpp new file mode 100644 index 0000000..705175f --- /dev/null +++ b/mednafen/gba-09333/Mode4.cpp @@ -0,0 +1,407 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Gfx.h" +#include "Globals.h" +#include "gfx-draw.h" + +namespace MDFN_IEN_GBA +{ + +void mode4RenderLine() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x0080) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + if(layerEnable & 0x400) { + int changed = gfxBG2Changed; + + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + gfxDrawRotScreen256(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, + BG2PA, BG2PB, BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, + line2); + } + + gfxDrawSprites(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + + if(line2[x] < color) { + color = line2[x]; + top = 0x04; + } + + if((uint8)(lineOBJ[x]>>24) < (uint8)(color >> 24)) { + color = lineOBJ[x]; + top = 0x10; + } + + if((top & 0x10) && (color & 0x00010000)) { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode4RenderLineNoWindow() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x0080) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + if(layerEnable & 0x400) { + int changed = gfxBG2Changed; + + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen256(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, + BG2PA, BG2PB, BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, + line2); + } + + gfxDrawSprites(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + + if(line2[x] < color) { + color = line2[x]; + top = 0x04; + } + + if((uint8)(lineOBJ[x]>>24) < (uint8)(color >> 24)) { + color = lineOBJ[x]; + top = 0x10; + } + + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line2[x] < back) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if((uint8)(lineOBJ[x]>>24) < (uint8)(back >> 24)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if(line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode4RenderLineAll() +{ + uint16 *palette = (uint16 *)paletteRAM; + + if(DISPCNT & 0x0080) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + bool inWindow0 = false; + bool inWindow1 = false; + + if(layerEnable & 0x2000) { + uint8 v0 = WIN0V >> 8; + uint8 v1 = WIN0V & 255; + inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1); + } + if(layerEnable & 0x4000) { + uint8 v0 = WIN1V >> 8; + uint8 v1 = WIN1V & 255; + inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1); + } + + if(layerEnable & 0x400) { + int changed = gfxBG2Changed; + + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen256(BG2CNT, BG2X_L, BG2X_H, BG2Y_L, BG2Y_H, + BG2PA, BG2PB, BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, + line2); + } + + gfxDrawSprites(); + gfxDrawOBJWin(); + + uint32 backdrop = (READ16LE(&palette[0]) | 0x30000000); + + uint8 inWin0Mask = WININ & 0xFF; + uint8 inWin1Mask = WININ >> 8; + uint8 outMask = WINOUT & 0xFF; + + for(int x = 0; x < 240; x++) { + uint32 color = backdrop; + uint8 top = 0x20; + uint8 mask = outMask; + + if(!(lineOBJWin[x] & 0x80000000)) { + mask = WINOUT >> 8; + } + + if(inWindow1) { + if(gfxInWin1[x]) + mask = inWin1Mask; + } + + if(inWindow0) { + if(gfxInWin0[x]) { + mask = inWin0Mask; + } + } + + if((mask & 4) && (line2[x] < color)) { + color = line2[x]; + top = 0x04; + } + + if((mask & 16) && ((uint8)(lineOBJ[x]>>24) < (uint8)(color >>24))) { + color = lineOBJ[x]; + top = 0x10; + } + + if(mask & 32) { + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if((mask & 16) && (uint8)(lineOBJ[x]>>24) < (uint8)(back >> 24)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + } else if(color & 0x00010000) { + // semi-transparent OBJ + uint32 back = backdrop; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +} diff --git a/mednafen/gba-09333/Mode5.cpp b/mednafen/gba-09333/Mode5.cpp new file mode 100644 index 0000000..da4acdc --- /dev/null +++ b/mednafen/gba-09333/Mode5.cpp @@ -0,0 +1,411 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Globals.h" +#include "Gfx.h" +#include "gfx-draw.h" + +namespace MDFN_IEN_GBA +{ + +void mode5RenderLine() +{ + if(DISPCNT & 0x0080) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + uint16 *palette = (uint16 *)paletteRAM; + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen16Bit160(BG2CNT, BG2X_L, BG2X_H, + BG2Y_L, BG2Y_H, BG2PA, BG2PB, + BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, + line2); + } + + gfxDrawSprites(); + + uint32 background = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = background; + uint8 top = 0x20; + + if(line2[x] < color) { + color = line2[x]; + top = 0x04; + } + + if((uint8)(lineOBJ[x]>>24) < (uint8)(color >>24)) { + color = lineOBJ[x]; + top = 0x10; + } + + if((top & 0x10) && (color & 0x00010000)) { + // semi-transparent OBJ + uint32 back = background; + uint8 top2 = 0x20; + + if(line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode5RenderLineNoWindow() +{ + if(DISPCNT & 0x0080) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + uint16 *palette = (uint16 *)paletteRAM; + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen16Bit160(BG2CNT, BG2X_L, BG2X_H, + BG2Y_L, BG2Y_H, BG2PA, BG2PB, + BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, + line2); + } + + gfxDrawSprites(); + + uint32 background = ( READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = background; + uint8 top = 0x20; + + if(line2[x] < color) { + color = line2[x]; + top = 0x04; + } + + if((uint8)(lineOBJ[x]>>24) < (uint8)(color >>24)) { + color = lineOBJ[x]; + top = 0x10; + } + + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = background; + uint8 top2 = 0x20; + + if(line2[x] < back) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if((uint8)(lineOBJ[x]>>24) < (uint8)(back >> 24)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = background; + uint8 top2 = 0x20; + + if(line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +void mode5RenderLineAll() +{ + if(DISPCNT & 0x0080) { + for(int x = 0; x < 240; x++) { + lineMix[x] = 0x7fff; + } + gfxLastVCOUNT = VCOUNT; + return; + } + + uint16 *palette = (uint16 *)paletteRAM; + + if(layerEnable & 0x0400) { + int changed = gfxBG2Changed; + + if(gfxLastVCOUNT > VCOUNT) + changed = 3; + + gfxDrawRotScreen16Bit160(BG2CNT, BG2X_L, BG2X_H, + BG2Y_L, BG2Y_H, BG2PA, BG2PB, + BG2PC, BG2PD, + gfxBG2X, gfxBG2Y, changed, + line2); + } + + gfxDrawSprites(); + gfxDrawOBJWin(); + + bool inWindow0 = false; + bool inWindow1 = false; + + if(layerEnable & 0x2000) { + uint8 v0 = WIN0V >> 8; + uint8 v1 = WIN0V & 255; + inWindow0 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow0 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow0 |= (VCOUNT >= v0 || VCOUNT < v1); + } + if(layerEnable & 0x4000) { + uint8 v0 = WIN1V >> 8; + uint8 v1 = WIN1V & 255; + inWindow1 = ((v0 == v1) && (v0 >= 0xe8)); + if(v1 >= v0) + inWindow1 |= (VCOUNT >= v0 && VCOUNT < v1); + else + inWindow1 |= (VCOUNT >= v0 || VCOUNT < v1); + } + + uint8 inWin0Mask = WININ & 0xFF; + uint8 inWin1Mask = WININ >> 8; + uint8 outMask = WINOUT & 0xFF; + + uint32 background = (READ16LE(&palette[0]) | 0x30000000); + + for(int x = 0; x < 240; x++) { + uint32 color = background; + uint8 top = 0x20; + uint8 mask = outMask; + + if(!(lineOBJWin[x] & 0x80000000)) { + mask = WINOUT >> 8; + } + + if(inWindow1) { + if(gfxInWin1[x]) + mask = inWin1Mask; + } + + if(inWindow0) { + if(gfxInWin0[x]) { + mask = inWin0Mask; + } + } + + if((mask & 4) && (line2[x] < color)) { + color = line2[x]; + top = 0x04; + } + + if((mask & 16) && ((uint8)(lineOBJ[x]>>24) < (uint8)(color >>24))) { + color = lineOBJ[x]; + top = 0x10; + } + + if(mask & 32) { + if(!(color & 0x00010000)) { + switch((BLDMOD >> 6) & 3) { + case 0: + break; + case 1: + { + if(top & BLDMOD) { + uint32 back = background; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + if(top != 0x04) { + back = line2[x]; + top2 = 0x04; + } + } + + if((mask & 16) && (uint8)(lineOBJ[x]>>24) < (uint8)(back >> 24)) { + if(top != 0x10) { + back = lineOBJ[x]; + top2 = 0x10; + } + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + + } + } + break; + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } else { + // semi-transparent OBJ + uint32 back = background; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + } else if(color & 0x00010000) { + // semi-transparent OBJ + uint32 back = background; + uint8 top2 = 0x20; + + if((mask & 4) && line2[x] < back) { + back = line2[x]; + top2 = 0x04; + } + + if(top2 & (BLDMOD>>8)) + color = gfxAlphaBlend(color, back, + all_coeff[COLEV & 0x1F], + all_coeff[(COLEV >> 8) & 0x1F]); + else { + switch((BLDMOD >> 6) & 3) { + case 2: + if(BLDMOD & top) + color = gfxIncreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + case 3: + if(BLDMOD & top) + color = gfxDecreaseBrightness(color, all_coeff[COLY & 0x1F]); + break; + } + } + } + + lineMix[x] = color; + } + gfxBG2Changed = 0; + gfxLastVCOUNT = VCOUNT; +} + +} diff --git a/mednafen/gba-09333/Port.h b/mednafen/gba-09333/Port.h new file mode 100644 index 0000000..a1e63eb --- /dev/null +++ b/mednafen/gba-09333/Port.h @@ -0,0 +1,31 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_PORT_H +#define VBA_PORT_H + +#include + +#define READ16LE(base) LoadU16_LE(base) +#define READ32LE(base) LoadU32_LE(base) + +#define WRITE16LE(x,v) StoreU16_LE(x,v) +#define WRITE32LE(x,v) StoreU32_LE(x,v) + +#endif diff --git a/mednafen/gba-09333/RTC.cpp b/mednafen/gba-09333/RTC.cpp new file mode 100644 index 0000000..96414cd --- /dev/null +++ b/mednafen/gba-09333/RTC.cpp @@ -0,0 +1,229 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "../mednafen.h" +#include "GBA.h" +#include "Globals.h" +#include "Port.h" + +#include +#include + +namespace MDFN_IEN_GBA +{ + +RTC::RTC() +{ + InitTime(); + Reset(); +} + +RTC::~RTC() +{ + +} + +void RTC::InitTime(void) +{ + time_t long_time; + + time( &long_time ); /* Get time as long integer. */ + + curtime = (int64)long_time * 16777216; +} + +void RTC::AddTime(int32 amount) +{ + curtime += amount; +} + +uint16 RTC::Read(uint32 address) +{ + if(address == 0x80000c8) + return byte2; + else if(address == 0x80000c6) + return byte1; + else if(address == 0x80000c4) + return byte0; + + abort(); +} + +static uint8 toBCD(uint8 value) +{ + value = value % 100; + int l = value % 10; + int h = value / 10; + return h * 16 + l; +} + +void RTC::Write(uint32 address, uint16 value) +{ + if(address == 0x80000c8) { + byte2 = (uint8)value; // enable ? + } else if(address == 0x80000c6) { + byte1 = (uint8)value; // read/write + } else if(address == 0x80000c4) { + if(byte2 & 1) { + if(state == IDLE && byte0 == 1 && value == 5) { + state = COMMAND; + bits = 0; + command = 0; + } else if(!(byte0 & 1) && (value & 1)) { // bit transfer + byte0 = (uint8)value; + switch(state) { + case COMMAND: + command |= ((value & 2) >> 1) << (7-bits); + bits++; + if(bits == 8) { + bits = 0; + switch(command) { + case 0x60: + // not sure what this command does but it doesn't take parameters + // maybe it is a reset or stop + state = IDLE; + bits = 0; + break; + case 0x62: + // this sets the control state but not sure what those values are + state = READDATA; + dataLen = 1; + break; + case 0x63: + dataLen = 1; + data[0] = 0x40; + state = DATA; + break; + case 0x64: + break; + case 0x65: + { + struct tm *newtime; + time_t long_time; + + long_time = curtime / 16777216; + newtime = localtime( &long_time ); /* Convert to local time. */ + + dataLen = 7; + data[0] = toBCD(newtime->tm_year); + data[1] = toBCD(newtime->tm_mon+1); + data[2] = toBCD(newtime->tm_mday); + data[3] = toBCD(newtime->tm_wday); + data[4] = toBCD(newtime->tm_hour); + data[5] = toBCD(newtime->tm_min); + data[6] = toBCD(newtime->tm_sec); + state = DATA; + } + break; + case 0x67: + { + struct tm *newtime; + time_t long_time; + + long_time = curtime / 16777216; + newtime = localtime( &long_time ); /* Convert to local time. */ + + dataLen = 3; + data[0] = toBCD(newtime->tm_hour); + data[1] = toBCD(newtime->tm_min); + data[2] = toBCD(newtime->tm_sec); + state = DATA; + } + break; + default: + //systemMessage(0, N_("Unknown RTC command %02x"), command); + state = IDLE; + break; + } + } + break; + case DATA: + if(byte1 & 2) { + } else { + byte0 = (byte0 & ~2) | + ((data[bits >> 3] >> + (bits & 7)) & 1)*2; + bits++; + if(bits == 8*dataLen) { + bits = 0; + state = IDLE; + } + } + break; + case READDATA: + if(!(byte1 & 2)) { + } else { + data[bits >> 3] = + (data[bits >> 3] >> 1) | + ((value << 6) & 128); + bits++; + if(bits == 8*dataLen) { + bits = 0; + state = IDLE; + } + } + break; + default: + break; + } + } else + byte0 = (uint8)value; + } + } +} + +void RTC::Reset(void) +{ + byte0 = 0; + byte1 = 0; + byte2 = 0; + command = 0; + dataLen = 0; + bits = 0; + state = IDLE; + + memset(data, 0, sizeof(data)); +} + +int RTC::StateAction(StateMem *sm, int load, int data_only) +{ + SFORMAT StateRegs[] = + { + SFVAR(byte0), + SFVAR(byte1), + SFVAR(byte2), + SFVAR(command), + SFVAR(dataLen), + SFVAR(bits), + SFVAR(state), + SFARRAY(data, 12), + SFEND + }; + + + int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "RTC"); + + if(load) + { + + } + + return(ret); +} + +} diff --git a/mednafen/gba-09333/RTC.h b/mednafen/gba-09333/RTC.h new file mode 100644 index 0000000..d5ead21 --- /dev/null +++ b/mednafen/gba-09333/RTC.h @@ -0,0 +1,62 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_RTC_H +#define VBA_RTC_H + +namespace MDFN_IEN_GBA +{ + +class RTC +{ + public: + + RTC(); + ~RTC(); + + void InitTime(void); + + uint16 Read(uint32 address); + void Write(uint32 address, uint16 value); + void Reset(void); + + void AddTime(int32 amount); + + int StateAction(StateMem *sm, int load, int data_only); + + private: + + enum RTCSTATE { IDLE, COMMAND, DATA, READDATA }; + + uint8 byte0; + uint8 byte1; + uint8 byte2; + uint8 command; + int dataLen; + int bits; + RTCSTATE state; + uint8 data[12]; + + int64 curtime; // GBA CPU cycles since the Epoch, in local time. + +}; + +} + +#endif diff --git a/mednafen/gba-09333/Sound.cpp b/mednafen/gba-09333/Sound.cpp new file mode 100644 index 0000000..40965b8 --- /dev/null +++ b/mednafen/gba-09333/Sound.cpp @@ -0,0 +1,451 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Globals.h" +#include "Sound.h" +#include "Port.h" + +#include +#include + +#include +#include "gb_apu/Gb_Apu.h" + +#include + +namespace MDFN_IEN_GBA +{ + +typedef Blip_Synth Synth; + +static Synth synth; + +static Gb_Apu gba_apu; +static Stereo_Buffer gba_buf; + +extern uint32 soundTS; + +static int lleft = 0, lright = 0; + +int soundControl = 0; + +typedef struct +{ + int32 FifoIndex; + int32 FifoCount; + int32 FifoWriteIndex; + bool Enabled; + int32 Timer; + uint8 Fifo[32]; + uint8 Value; +} GBADigiSound; + +GBADigiSound DSChans[2]; // Digital sound channels, not Nintendo DS :b + +#define soundDSFifoAIndex DSChans[0].FifoIndex +#define soundDSFifoACount DSChans[0].FifoCount +#define soundDSFifoAWriteIndex DSChans[0].FifoWriteIndex +#define soundDSAEnabled DSChans[0].Enabled +#define soundDSATimer DSChans[0].Timer +#define soundDSFifoA DSChans[0].Fifo +#define soundDSAValue DSChans[0].Value + +#define soundDSFifoBIndex DSChans[1].FifoIndex +#define soundDSFifoBCount DSChans[1].FifoCount +#define soundDSFifoBWriteIndex DSChans[1].FifoWriteIndex +#define soundDSBEnabled DSChans[1].Enabled +#define soundDSBTimer DSChans[1].Timer +#define soundDSFifoB DSChans[1].Fifo +#define soundDSBValue DSChans[1].Value + +#include "../state.h" + +int MDFNGBASOUND_StateAction(StateMem *sm, int load, int data_only) +{ + gb_apu_state_t apu_state; + + //if(!load) // always save state, in case there is none to load + gba_apu.save_state( &apu_state ); + + SFORMAT StateRegs[] = + { + SFVAR(soundControl), + SFVAR(soundDSFifoAIndex), + SFVAR(soundDSFifoACount), + SFVAR(soundDSFifoAWriteIndex), + SFVAR(soundDSAEnabled), + SFVAR(soundDSATimer), + SFARRAYN(soundDSFifoA, sizeof(soundDSFifoA), "soundDSFifoA"), + SFVAR(soundDSAValue), + SFVAR(soundDSFifoBIndex), + SFVAR(soundDSFifoBCount), + SFVAR(soundDSFifoBWriteIndex), + SFVAR(soundDSBEnabled), + SFVAR(soundDSBTimer), + SFARRAYN(soundDSFifoB, sizeof(soundDSFifoB), "soundDSFifoB"), + SFVAR(soundDSBValue), + + SFVARN(apu_state, "apu_state"), + SFEND + }; + + int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "SND"); + if(ret && load) + { + gba_apu.reset( gba_apu.mode_agb, true ); + (void) gba_apu.load_state( apu_state ); // TODO: warn if this returns error + } + return(ret); +} + +uint8 soundRead(uint32 address) +{ + if(address == 0x80) + return(gba_apu.read_register(soundTS, 0xff24)); + else if(address == 0x81) + return(gba_apu.read_register(soundTS, 0xff25)); + else if(address == 0x84) + return(gba_apu.read_register(soundTS, 0xff26)); + else if(address >= 0x90 && address <= 0x9f) + { + return(gba_apu.read_register(soundTS, address - 0x90 + 0xff30)); + } + return(ioMem[address]); +} + +void soundEvent(uint32 address, uint8 data) +{ + uint32 origa = address; + address &= 0xFF; + + if(address == 0x60) + address = 0xff10; + else if(address == 0x62) + address = 0xff11; + else if(address == 0x63) + address = 0xff12; + else if(address == 0x64) + address = 0xff13; + else if(address == 0x65) + address = 0xff14; + + else if(address == 0x68) + address = 0xff16; + else if(address == 0x69) + address = 0xff17; + else if(address == 0x6c) + address = 0xff18; + else if(address == 0x6d) + address = 0xff19; + + else if(address == 0x70) + address = 0xff1a; + else if(address == 0x72) + address = 0xff1b; + else if(address == 0x73) + address = 0xff1c; + else if(address == 0x74) + address = 0xff1d; + else if(address == 0x75) + address = 0xff1e; + + else if(address == 0x78) + address = 0xff20; + else if(address == 0x79) + address = 0xff21; + else if(address == 0x7c) + address = 0xff22; + else if(address == 0x7d) + address = 0xff23; + + else if(address == 0x80) + address = 0xff24; + else if(address == 0x81) + address = 0xff25; + else if(address == 0x84) + address = 0xff26; + else if(address >= 0x90 && address <= 0x9f) + { + address += 0xff30 - 0x90; + } + else + { + ioMem[origa] = data; + return; + } + ioMem[origa] = data; + + gba_apu.write_register(soundTS, address, data); +} + +void soundEvent(uint32 address, uint16 data) +{ + switch(address) { + case SGCNT0_H: + data &= 0xFF0F; + soundControl = data & 0x770F;; + if(data & 0x0800) { + soundDSFifoAWriteIndex = 0; + soundDSFifoAIndex = 0; + soundDSFifoACount = 0; + soundDSAValue = 0; + memset(soundDSFifoA, 0, 32); + } + soundDSAEnabled = (data & 0x0300) ? true : false; + soundDSATimer = (data & 0x0400) ? 1 : 0; + if(data & 0x8000) { + soundDSFifoBWriteIndex = 0; + soundDSFifoBIndex = 0; + soundDSFifoBCount = 0; + soundDSBValue = 0; + memset(soundDSFifoB, 0, 32); + } + soundDSBEnabled = (data & 0x3000) ? true : false; + soundDSBTimer = (data & 0x4000) ? 1 : 0; + WRITE16LE(((uint16 *)&ioMem[address]), data); + break; + case FIFOA_L: + case FIFOA_H: + soundDSFifoA[soundDSFifoAWriteIndex++] = data & 0xFF; + soundDSFifoA[soundDSFifoAWriteIndex++] = data >> 8; + soundDSFifoACount += 2; + soundDSFifoAWriteIndex &= 31; + WRITE16LE(((uint16 *)&ioMem[address]), data); + break; + case FIFOB_L: + case FIFOB_H: + soundDSFifoB[soundDSFifoBWriteIndex++] = data & 0xFF; + soundDSFifoB[soundDSFifoBWriteIndex++] = data >> 8; + soundDSFifoBCount += 2; + soundDSFifoBWriteIndex &= 31; + WRITE16LE(((uint16 *)&ioMem[address]), data); + break; + case 0x88: + data &= 0xC3FF; + WRITE16LE(((uint16 *)&ioMem[address]), data); + break; + case 0x90: + case 0x92: + case 0x94: + case 0x96: + case 0x98: + case 0x9a: + case 0x9c: + case 0x9e: + //printf("Yay: %04x: %04x\n", 0xFF30 + (address & 0xF), data); + gba_apu.write_register(soundTS, 0xFF30 + (address & 0xF), data & 0xFF); + gba_apu.write_register(soundTS, 0xFF30 + (address & 0xF) + 1, data >> 8); + //*((uint16 *)&sound3WaveRam[(sound3Bank*0x10)^0x10+(address&14)]) = data; + //WRITE16LE(((uint16 *)&ioMem[address]), data); + break; + } +} + +#ifndef max +#define max(a,b) (a)<(b)?(b):(a) +#endif + +static inline void soundMix(int &left, int &right) +{ + int res = 0; + int dsaRatio = ioMem[0x82] & 4; + int dsbRatio = ioMem[0x82] & 8; + + if(soundControl & 0x0200) + { + if(!dsaRatio) + { + res = (int8)soundDSAValue >> 1; + } + else + res = (int8)soundDSAValue; + } + + if(soundControl & 0x2000) + { + if(!dsbRatio) + { + res += (int8)soundDSBValue >> 1; + } + else + res += (int8)soundDSBValue; + } + + left = res; + + res = 0; + + if(soundControl & 0x0100) + { + if(!dsaRatio) + res = (int8)soundDSAValue >> 1; + else + res = (int8)soundDSAValue; + } + + if(soundControl & 0x1000) + { + if(!dsbRatio) + res += (int8)soundDSAValue >> 1; + else + res += (int8)soundDSBValue; + } + right = res; +} + +int meow = 0; + +static inline void soundLick(void) +{ + int left, right; + + left = right = 0; + + soundMix(left, right); + + if(left != lleft) + synth.offset_inline(soundTS, left - lleft, gba_buf.left()); + + if(right != lright) + synth.offset_inline(soundTS, right - lright, gba_buf.right()); + + lleft = left; + lright = right; +} + +static void DSTimer(int which, int dmamask) +{ + if(DSChans[which].Enabled) + { + if(DSChans[which].FifoCount <= 16) + { + CPUCheckDMA(3, dmamask); + } + + if(DSChans[which].FifoCount > 16) + { + DSChans[which].Value = (DSChans[which].Fifo[DSChans[which].FifoIndex]); + DSChans[which].FifoIndex = (DSChans[which].FifoIndex + 1) & 0x1F; + DSChans[which].FifoCount--; + } + } + else + { + DSChans[which].Value = 0; + } +} + +void soundTimerOverflow(int timer) +{ + bool NeedLick = FALSE; + + if(soundDSAEnabled && (soundDSATimer == timer)) + { + DSTimer(0, 2); + NeedLick = TRUE; + } + + if(soundDSBEnabled && (soundDSBTimer == timer)) + { + DSTimer(1, 4); + NeedLick = TRUE; + } + + if(NeedLick) + soundLick(); +} + +int32 MDFNGBASOUND_Flush(int16 *SoundBuf, const int32 MaxSoundFrames) +{ + const int ratio = ioMem[0x82] & 3; + static const int rat_table[4] = { 2, 1, 0, 2 }; + int32 FrameCount = 0; + + gba_apu.volume(0.333 * (double)(4 >> rat_table[ratio]) / 4); + + gba_apu.end_frame(soundTS); + + gba_buf.end_frame(soundTS); + + if(SoundBuf) + FrameCount = gba_buf.read_samples(SoundBuf, MaxSoundFrames * 2) / 2; + else + gba_buf.clear(); + + soundTS = 0; + + +#if 0 + if(SoundBuf) + { + unsigned long long crf = (unsigned long long)gba_buf.left()->clock_rate_factor(gba_buf.left()->clock_rate()); + double real_rate = (double)crf * gba_buf.left()->clock_rate() / (1ULL << BLIP_BUFFER_ACCURACY); + + printf("%f\n", real_rate); + } +#endif + + return(FrameCount); +} + +void MDFNGBASOUND_Init(void) +{ + MDFNGBA_SetSoundRate(0); + + gba_buf.clock_rate((long)(4194304 * 4)); + + gba_apu.set_output(gba_buf.center(), gba_buf.left(), gba_buf.right()); + + gba_apu.reset( gba_apu.mode_agb, true ); + + gba_apu.volume(0.333); + synth.volume(0.666); + + gba_buf.bass_freq(20); +} + +void soundReset() +{ + for(int ch = 0; ch < 2; ch++) + { + DSChans[ch].FifoIndex = 0; + DSChans[ch].FifoCount = 0; + DSChans[ch].FifoWriteIndex = 0; + DSChans[ch].Enabled = false; + DSChans[ch].Timer = 0; + memset(DSChans[ch].Fifo, 0, 32); + DSChans[ch].Value = 0; + } + + for(int addr = 0x90; addr < 0xA0;) + { + ioMem[addr++] = 0x00; + ioMem[addr++] = 0xff; + } + + gba_apu.reset( gba_apu.mode_agb, true ); +} + +bool MDFNGBA_SetSoundRate(uint32 rate) +{ + gba_buf.set_sample_rate(rate?rate:44100, 60); + return(TRUE); +} + +} diff --git a/mednafen/gba-09333/Sound.h b/mednafen/gba-09333/Sound.h new file mode 100644 index 0000000..64d951c --- /dev/null +++ b/mednafen/gba-09333/Sound.h @@ -0,0 +1,69 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_SOUND_H +#define VBA_SOUND_H + +namespace MDFN_IEN_GBA +{ + +#define NR10 0x60 +#define NR11 0x62 +#define NR12 0x63 +#define NR13 0x64 +#define NR14 0x65 +#define NR21 0x68 +#define NR22 0x69 +#define NR23 0x6c +#define NR24 0x6d +#define NR30 0x70 +#define NR31 0x72 +#define NR32 0x73 +#define NR33 0x74 +#define NR34 0x75 +#define NR41 0x78 +#define NR42 0x79 +#define NR43 0x7c +#define NR44 0x7d +#define NR50 0x80 +#define NR51 0x81 +#define NR52 0x84 +#define SGCNT0_H 0x82 +#define FIFOA_L 0xa0 +#define FIFOA_H 0xa2 +#define FIFOB_L 0xa4 +#define FIFOB_H 0xa6 + +extern void soundReset(); +extern void soundEvent(uint32, uint8); +extern void soundEvent(uint32, uint16); +extern void soundTimerOverflow(int); + +int32 MDFNGBASOUND_Flush(int16 *SoundBuf, const int32 MaxSoundFrames); +void MDFNGBASOUND_Init(void); + +uint8 soundRead(uint32 address); + +void MDFNGBA_SetSoundVolume(uint32 volume); +bool MDFNGBA_SetSoundRate(uint32 rate); +int MDFNGBASOUND_StateAction(StateMem *sm, int load, int data_only); + +} + +#endif // VBA_SOUND_H diff --git a/mednafen/gba-09333/arm.cpp b/mednafen/gba-09333/arm.cpp new file mode 100644 index 0000000..c9b269c --- /dev/null +++ b/mednafen/gba-09333/arm.cpp @@ -0,0 +1,7952 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#define INCED_FROM_ARM_CPP + +#include "GBA.h" +#include "GBAinline.h" +#include "Globals.h" + +namespace MDFN_IEN_GBA +{ + +unsigned int RunARM(void) +{ + unsigned int clockTicks; + +#define OP_AND \ + reg[dest].I = reg[(opcode>>16)&15].I & value; + +#define OP_ANDS \ + reg[dest].I = reg[(opcode>>16)&15].I & value;\ + \ + N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\ + Z_FLAG = (reg[dest].I) ? false : true;\ + C_FLAG = C_OUT; + +#define OP_EOR \ + reg[dest].I = reg[(opcode>>16)&15].I ^ value; + +#define OP_EORS \ + reg[dest].I = reg[(opcode>>16)&15].I ^ value;\ + \ + N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\ + Z_FLAG = (reg[dest].I) ? false : true;\ + C_FLAG = C_OUT; + +#define NEG(i) ((i) >> 31) +#define POS(i) ((~(i)) >> 31) +#define ADDCARRY(a, b, c) \ + C_FLAG = ((NEG(a) & NEG(b)) |\ + (NEG(a) & POS(c)) |\ + (NEG(b) & POS(c))) ? true : false; +#define ADDOVERFLOW(a, b, c) \ + V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\ + (POS(a) & POS(b) & NEG(c))) ? true : false; +#define SUBCARRY(a, b, c) \ + C_FLAG = ((NEG(a) & POS(b)) |\ + (NEG(a) & POS(c)) |\ + (POS(b) & POS(c))) ? true : false; +#define SUBOVERFLOW(a, b, c)\ + V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\ + (POS(a) & NEG(b) & NEG(c))) ? true : false; +#define OP_SUB \ + {\ + reg[dest].I = reg[base].I - value;\ + } +#define OP_SUBS \ + {\ + uint32 lhs = reg[base].I;\ + uint32 rhs = value;\ + uint32 res = lhs - rhs;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(lhs, rhs, res);\ + SUBOVERFLOW(lhs, rhs, res);\ + } +#define OP_RSB \ + {\ + reg[dest].I = value - reg[base].I;\ + } +#define OP_RSBS \ + {\ + uint32 lhs = reg[base].I;\ + uint32 rhs = value;\ + uint32 res = rhs - lhs;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(rhs, lhs, res);\ + SUBOVERFLOW(rhs, lhs, res);\ + } +#define OP_ADD \ + {\ + reg[dest].I = reg[base].I + value;\ + } +#define OP_ADDS \ + {\ + uint32 lhs = reg[base].I;\ + uint32 rhs = value;\ + uint32 res = lhs + rhs;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + ADDCARRY(lhs, rhs, res);\ + ADDOVERFLOW(lhs, rhs, res);\ + } +#define OP_ADC \ + {\ + reg[dest].I = reg[base].I + value + (uint32)C_FLAG;\ + } +#define OP_ADCS \ + {\ + uint32 lhs = reg[base].I;\ + uint32 rhs = value;\ + uint32 res = lhs + rhs + (uint32)C_FLAG;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + ADDCARRY(lhs, rhs, res);\ + ADDOVERFLOW(lhs, rhs, res);\ + } +#define OP_SBC \ + {\ + reg[dest].I = reg[base].I - value - !((uint32)C_FLAG);\ + } +#define OP_SBCS \ + {\ + uint32 lhs = reg[base].I;\ + uint32 rhs = value;\ + uint32 res = lhs - rhs - !((uint32)C_FLAG);\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(lhs, rhs, res);\ + SUBOVERFLOW(lhs, rhs, res);\ + } +#define OP_RSC \ + {\ + reg[dest].I = value - reg[base].I - !((uint32)C_FLAG);\ + } +#define OP_RSCS \ + {\ + uint32 lhs = reg[base].I;\ + uint32 rhs = value;\ + uint32 res = rhs - lhs - !((uint32)C_FLAG);\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(rhs, lhs, res);\ + SUBOVERFLOW(rhs, lhs, res);\ + } +#define OP_CMP \ + {\ + uint32 lhs = reg[base].I;\ + uint32 rhs = value;\ + uint32 res = lhs - rhs;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(lhs, rhs, res);\ + SUBOVERFLOW(lhs, rhs, res);\ + } +#define OP_CMN \ + {\ + uint32 lhs = reg[base].I;\ + uint32 rhs = value;\ + uint32 res = lhs + rhs;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + ADDCARRY(lhs, rhs, res);\ + ADDOVERFLOW(lhs, rhs, res);\ + } + +#define LOGICAL_LSL_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + C_OUT = (v >> (32 - shift)) & 1 ? true : false;\ + value = v << shift;\ + } +#define LOGICAL_LSR_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + C_OUT = (v >> (shift - 1)) & 1 ? true : false;\ + value = v >> shift;\ + } +#define LOGICAL_ASR_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + C_OUT = ((int32)v >> (int)(shift - 1)) & 1 ? true : false;\ + value = (int32)v >> (int)shift;\ + } +#define LOGICAL_ROR_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + C_OUT = (v >> (shift - 1)) & 1 ? true : false;\ + value = ((v << (32 - shift)) |\ + (v >> shift));\ + } +#define LOGICAL_RRX_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + shift = (int)C_FLAG;\ + C_OUT = (v & 1) ? true : false;\ + value = ((v >> 1) |\ + (shift << 31));\ + } +#define LOGICAL_ROR_IMM \ + {\ + uint32 v = opcode & 0xff;\ + C_OUT = (v >> (shift - 1)) & 1 ? true : false;\ + value = ((v << (32 - shift)) |\ + (v >> shift));\ + } +#define ARITHMETIC_LSL_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + value = v << shift;\ + } +#define ARITHMETIC_LSR_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + value = v >> shift;\ + } +#define ARITHMETIC_ASR_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + value = (int32)v >> (int)shift;\ + } +#define ARITHMETIC_ROR_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + value = ((v << (32 - shift)) |\ + (v >> shift));\ + } +#define ARITHMETIC_RRX_REG \ + {\ + uint32 v = reg[opcode & 0x0f].I;\ + shift = (int)C_FLAG;\ + value = ((v >> 1) |\ + (shift << 31));\ + } +#define ARITHMETIC_ROR_IMM \ + {\ + uint32 v = opcode & 0xff;\ + value = ((v << (32 - shift)) |\ + (v >> shift));\ + } +#define ROR_IMM_MSR \ + {\ + uint32 v = opcode & 0xff;\ + value = ((v << (32 - shift)) |\ + (v >> shift));\ + } +#define ROR_VALUE \ + {\ + value = ((value << (32 - shift)) |\ + (value >> shift));\ + } +#define RCR_VALUE \ + {\ + shift = (int)C_FLAG;\ + value = ((value >> 1) |\ + (shift << 31));\ + } + +#define OP_TST \ + uint32 res = reg[base].I & value;\ + N_FLAG = (res & 0x80000000) ? true : false;\ + Z_FLAG = (res) ? false : true;\ + C_FLAG = C_OUT; + +#define OP_TEQ \ + uint32 res = reg[base].I ^ value;\ + N_FLAG = (res & 0x80000000) ? true : false;\ + Z_FLAG = (res) ? false : true;\ + C_FLAG = C_OUT; + +#define OP_ORR \ + reg[dest].I = reg[base].I | value; + +#define OP_ORRS \ + reg[dest].I = reg[base].I | value;\ + N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\ + Z_FLAG = (reg[dest].I) ? false : true;\ + C_FLAG = C_OUT; + +#define OP_MOV \ + reg[dest].I = value; + +#define OP_MOVS \ + reg[dest].I = value;\ + N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\ + Z_FLAG = (reg[dest].I) ? false : true;\ + C_FLAG = C_OUT; + +#define OP_BIC \ + reg[dest].I = reg[base].I & (~value); + +#define OP_BICS \ + reg[dest].I = reg[base].I & (~value);\ + N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\ + Z_FLAG = (reg[dest].I) ? false : true;\ + C_FLAG = C_OUT; + +#define OP_MVN \ + reg[dest].I = ~value; + +#define OP_MVNS \ + reg[dest].I = ~value; \ + N_FLAG = (reg[dest].I & 0x80000000) ? true : false;\ + Z_FLAG = (reg[dest].I) ? false : true;\ + C_FLAG = C_OUT; + +#define CASE_16(BASE) \ + case BASE:\ + case BASE+1:\ + case BASE+2:\ + case BASE+3:\ + case BASE+4:\ + case BASE+5:\ + case BASE+6:\ + case BASE+7:\ + case BASE+8:\ + case BASE+9:\ + case BASE+10:\ + case BASE+11:\ + case BASE+12:\ + case BASE+13:\ + case BASE+14:\ + case BASE+15: + +#define CASE_256(BASE) \ + CASE_16(BASE)\ + CASE_16(BASE+0x10)\ + CASE_16(BASE+0x20)\ + CASE_16(BASE+0x30)\ + CASE_16(BASE+0x40)\ + CASE_16(BASE+0x50)\ + CASE_16(BASE+0x60)\ + CASE_16(BASE+0x70)\ + CASE_16(BASE+0x80)\ + CASE_16(BASE+0x90)\ + CASE_16(BASE+0xa0)\ + CASE_16(BASE+0xb0)\ + CASE_16(BASE+0xc0)\ + CASE_16(BASE+0xd0)\ + CASE_16(BASE+0xe0)\ + CASE_16(BASE+0xf0) + +#define LOGICAL_DATA_OPCODE(OPCODE, OPCODE2, BASE) \ + case BASE: \ + case BASE+8:\ + {\ + /* OP Rd,Rb,Rm LSL # */ \ + int base = (opcode >> 16) & 0x0F;\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + \ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + LOGICAL_LSL_REG\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+2:\ + case BASE+10:\ + {\ + /* OP Rd,Rb,Rm LSR # */ \ + int base = (opcode >> 16) & 0x0F;\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + LOGICAL_LSR_REG\ + } else {\ + value = 0;\ + C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false;\ + }\ + \ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+4:\ + case BASE+12:\ + {\ + /* OP Rd,Rb,Rm ASR # */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + LOGICAL_ASR_REG\ + } else {\ + if(reg[opcode & 0x0F].I & 0x80000000){\ + value = 0xFFFFFFFF;\ + C_OUT = true;\ + } else {\ + value = 0;\ + C_OUT = false;\ + } \ + }\ + \ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+6:\ + case BASE+14:\ + {\ + /* OP Rd,Rb,Rm ROR # */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + LOGICAL_ROR_REG\ + } else {\ + LOGICAL_RRX_REG\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+1:\ + {\ + /* OP Rd,Rb,Rm LSL Rs */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + if(shift == 32) {\ + value = 0;\ + C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\ + } else if(shift < 32) {\ + LOGICAL_LSL_REG\ + } else {\ + value = 0;\ + C_OUT = false;\ + }\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+3:\ + {\ + /* OP Rd,Rb,Rm LSR Rs */ \ + int base = (opcode >> 16) & 0x0F;\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + if(shift == 32) {\ + value = 0;\ + C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\ + } else if(shift < 32) {\ + LOGICAL_LSR_REG\ + } else {\ + value = 0;\ + C_OUT = false;\ + }\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+5:\ + {\ + /* OP Rd,Rb,Rm ASR Rs */ \ + int base = (opcode >> 16) & 0x0F;\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift < 32) {\ + if(shift) {\ + LOGICAL_ASR_REG\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + } else {\ + if(reg[opcode & 0x0F].I & 0x80000000){\ + value = 0xFFFFFFFF;\ + C_OUT = true;\ + } else {\ + value = 0;\ + C_OUT = false;\ + }\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+7:\ + {\ + /* OP Rd,Rb,Rm ROR Rs */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + shift &= 0x1f;\ + if(shift) {\ + LOGICAL_ROR_REG\ + } else {\ + value = reg[opcode & 0x0F].I;\ + C_OUT = (value & 0x80000000 ? true : false);\ + }\ + } else {\ + value = reg[opcode & 0x0F].I;\ + C_OUT = (value & 0x80000000 ? true : false);\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+0x200:\ + case BASE+0x201:\ + case BASE+0x202:\ + case BASE+0x203:\ + case BASE+0x204:\ + case BASE+0x205:\ + case BASE+0x206:\ + case BASE+0x207:\ + case BASE+0x208:\ + case BASE+0x209:\ + case BASE+0x20a:\ + case BASE+0x20b:\ + case BASE+0x20c:\ + case BASE+0x20d:\ + case BASE+0x20e:\ + case BASE+0x20f:\ + {\ + int shift = (opcode & 0xF00) >> 7;\ + int base = (opcode >> 16) & 0x0F;\ + int dest = (opcode >> 12) & 0x0F;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + LOGICAL_ROR_IMM\ + } else {\ + value = opcode & 0xff;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break; + +#define LOGICAL_DATA_OPCODE_WITHOUT_base(OPCODE, OPCODE2, BASE) \ + case BASE: \ + case BASE+8:\ + {\ + /* OP Rd,Rb,Rm LSL # */ \ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + \ + if(shift) {\ + LOGICAL_LSL_REG\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+2:\ + case BASE+10:\ + {\ + /* OP Rd,Rb,Rm LSR # */ \ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + LOGICAL_LSR_REG\ + } else {\ + value = 0;\ + C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false;\ + }\ + \ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+4:\ + case BASE+12:\ + {\ + /* OP Rd,Rb,Rm ASR # */\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + LOGICAL_ASR_REG\ + } else {\ + if(reg[opcode & 0x0F].I & 0x80000000){\ + value = 0xFFFFFFFF;\ + C_OUT = true;\ + } else {\ + value = 0;\ + C_OUT = false;\ + } \ + }\ + \ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+6:\ + case BASE+14:\ + {\ + /* OP Rd,Rb,Rm ROR # */\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + LOGICAL_ROR_REG\ + } else {\ + LOGICAL_RRX_REG\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+1:\ + {\ + /* OP Rd,Rb,Rm LSL Rs */\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + if(shift == 32) {\ + value = 0;\ + C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false);\ + } else if(shift < 32) {\ + LOGICAL_LSL_REG\ + } else {\ + value = 0;\ + C_OUT = false;\ + }\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+3:\ + {\ + /* OP Rd,Rb,Rm LSR Rs */ \ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + if(shift == 32) {\ + value = 0;\ + C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false);\ + } else if(shift < 32) {\ + LOGICAL_LSR_REG\ + } else {\ + value = 0;\ + C_OUT = false;\ + }\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+5:\ + {\ + /* OP Rd,Rb,Rm ASR Rs */ \ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift < 32) {\ + if(shift) {\ + LOGICAL_ASR_REG\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + } else {\ + if(reg[opcode & 0x0F].I & 0x80000000){\ + value = 0xFFFFFFFF;\ + C_OUT = true;\ + } else {\ + value = 0;\ + C_OUT = false;\ + }\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+7:\ + {\ + /* OP Rd,Rb,Rm ROR Rs */\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + shift &= 0x1f;\ + if(shift) {\ + LOGICAL_ROR_REG\ + } else {\ + value = reg[opcode & 0x0F].I;\ + C_OUT = (value & 0x80000000 ? true : false);\ + }\ + } else {\ + value = reg[opcode & 0x0F].I;\ + C_OUT = (value & 0x80000000 ? true : false);\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+0x200:\ + case BASE+0x201:\ + case BASE+0x202:\ + case BASE+0x203:\ + case BASE+0x204:\ + case BASE+0x205:\ + case BASE+0x206:\ + case BASE+0x207:\ + case BASE+0x208:\ + case BASE+0x209:\ + case BASE+0x20a:\ + case BASE+0x20b:\ + case BASE+0x20c:\ + case BASE+0x20d:\ + case BASE+0x20e:\ + case BASE+0x20f:\ + {\ + int shift = (opcode & 0xF00) >> 7;\ + int dest = (opcode >> 12) & 0x0F;\ + bool C_OUT = C_FLAG;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + LOGICAL_ROR_IMM\ + } else {\ + value = opcode & 0xff;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break; + +#define ARITHMETIC_DATA_OPCODE(OPCODE, OPCODE2, BASE) \ + case BASE:\ + case BASE+8:\ + {\ + /* OP Rd,Rb,Rm LSL # */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + ARITHMETIC_LSL_REG\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+2:\ + case BASE+10:\ + {\ + /* OP Rd,Rb,Rm LSR # */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + ARITHMETIC_LSR_REG\ + } else {\ + value = 0;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+4:\ + case BASE+12:\ + {\ + /* OP Rd,Rb,Rm ASR # */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + ARITHMETIC_ASR_REG\ + } else {\ + if(reg[opcode & 0x0F].I & 0x80000000){\ + value = 0xFFFFFFFF;\ + } else value = 0;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+6:\ + case BASE+14:\ + {\ + /* OP Rd,Rb,Rm ROR # */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = (opcode >> 7) & 0x1F;\ + int dest = (opcode>>12) & 15;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + ARITHMETIC_ROR_REG\ + } else {\ + ARITHMETIC_RRX_REG\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+1:\ + {\ + /* OP Rd,Rb,Rm LSL Rs */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + if(shift == 32) {\ + value = 0;\ + } else if(shift < 32) {\ + ARITHMETIC_LSL_REG\ + } else value = 0;\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+3:\ + {\ + /* OP Rd,Rb,Rm LSR Rs */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + if(shift == 32) {\ + value = 0;\ + } else if(shift < 32) {\ + ARITHMETIC_LSR_REG\ + } else value = 0;\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+5:\ + {\ + /* OP Rd,Rb,Rm ASR Rs */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift < 32) {\ + if(shift) {\ + ARITHMETIC_ASR_REG\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + } else {\ + if(reg[opcode & 0x0F].I & 0x80000000){\ + value = 0xFFFFFFFF;\ + } else value = 0;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+7:\ + {\ + /* OP Rd,Rb,Rm ROR Rs */\ + int base = (opcode >> 16) & 0x0F;\ + int shift = reg[(opcode >> 8)&15].B.B0;\ + int dest = (opcode>>12) & 15;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + if(shift) {\ + shift &= 0x1f;\ + if(shift) {\ + ARITHMETIC_ROR_REG\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + } else {\ + value = reg[opcode & 0x0F].I;\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break;\ + case BASE+0x200:\ + case BASE+0x201:\ + case BASE+0x202:\ + case BASE+0x203:\ + case BASE+0x204:\ + case BASE+0x205:\ + case BASE+0x206:\ + case BASE+0x207:\ + case BASE+0x208:\ + case BASE+0x209:\ + case BASE+0x20a:\ + case BASE+0x20b:\ + case BASE+0x20c:\ + case BASE+0x20d:\ + case BASE+0x20e:\ + case BASE+0x20f:\ + {\ + int shift = (opcode & 0xF00) >> 7;\ + int base = (opcode >> 16) & 0x0F;\ + int dest = (opcode >> 12) & 0x0F;\ + uint32 value;\ + if ((dest == 15)||((opcode & 0x02000010)==0x10))\ + {\ + clockTicks = 1+codeTicksAccesint32(armNextPC);\ + if ((opcode & 0x02000010)==0x10)\ + clockTicks++;\ + }\ + {\ + ARITHMETIC_ROR_IMM\ + }\ + if(dest == 15) {\ + clockTicks+=2+codeTicksAccessSeq32(armNextPC)+codeTicksAccessSeq32(armNextPC);\ + OPCODE2\ + /* todo */\ + if(opcode & 0x00100000) {\ + CPUSwitchMode(reg[17].I & 0x1f, false);\ + }\ + if(armState) {\ + reg[15].I &= 0xFFFFFFFC;\ + armNextPC = reg[15].I;\ + reg[15].I += 4;\ + ARM_PREFETCH;\ + } else {\ + reg[15].I &= 0xFFFFFFFE;\ + armNextPC = reg[15].I;\ + reg[15].I += 2;\ + THUMB_PREFETCH;\ + }\ + } else {\ + OPCODE \ + }\ + }\ + break; + + uint32 opcode = cpuPrefetch[0]; + cpuPrefetch[0] = cpuPrefetch[1]; + + busPrefetch = false; + if (busPrefetchCount & 0xFFFFFE00) + busPrefetchCount = 0x100 | (busPrefetchCount & 0xFF); + + + clockTicks = 0;//codeTicksAccessSeq32(armNextPC)+1; + int oldArmNextPC = armNextPC; + +#ifndef FINAL_VERSION + if(armNextPC == stop) { + armNextPC++; + } +#endif + + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH_NEXT; + + int cond = opcode >> 28; + // suggested optimization for frequent cases + bool cond_res; + if(cond == 0x0e) { + cond_res = true; + } else { + switch(cond) { + case 0x00: // EQ + cond_res = Z_FLAG; + break; + case 0x01: // NE + cond_res = !Z_FLAG; + break; + case 0x02: // CS + cond_res = C_FLAG; + break; + case 0x03: // CC + cond_res = !C_FLAG; + break; + case 0x04: // MI + cond_res = N_FLAG; + break; + case 0x05: // PL + cond_res = !N_FLAG; + break; + case 0x06: // VS + cond_res = V_FLAG; + break; + case 0x07: // VC + cond_res = !V_FLAG; + break; + case 0x08: // HI + cond_res = C_FLAG && !Z_FLAG; + break; + case 0x09: // LS + cond_res = !C_FLAG || Z_FLAG; + break; + case 0x0A: // GE + cond_res = N_FLAG == V_FLAG; + break; + case 0x0B: // LT + cond_res = N_FLAG != V_FLAG; + break; + case 0x0C: // GT + cond_res = !Z_FLAG &&(N_FLAG == V_FLAG); + break; + case 0x0D: // LE + cond_res = Z_FLAG || (N_FLAG != V_FLAG); + break; + case 0x0E: + cond_res = true; + break; + case 0x0F: + default: + // ??? + cond_res = false; + break; + } + } + +if(cond_res) { + switch(((opcode>>16)&0xFF0) | ((opcode>>4)&0x0F)) { + LOGICAL_DATA_OPCODE_WITHOUT_base(OP_AND, OP_AND, 0x000); + LOGICAL_DATA_OPCODE_WITHOUT_base(OP_ANDS, OP_AND, 0x010); + case 0x009: + { + // MUL Rd, Rm, Rs + int dest = (opcode >> 16) & 0x0F; + int mult = (opcode & 0x0F); + clockTicks = 1; + uint32 rs = reg[(opcode >> 8) & 0x0F].I; + reg[dest].I = reg[mult].I * rs; + if(((int32)rs)<0) + rs = ~rs; + if((rs & 0xFFFFFF00) == 0) + clockTicks += 0; + else if ((rs & 0xFFFF0000) == 0) + clockTicks += 1; + else if ((rs & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + + } + break; + case 0x019: + { + // MULS Rd, Rm, Rs + int dest = (opcode >> 16) & 0x0F; + int mult = (opcode & 0x0F); + clockTicks = 1; + uint32 rs = reg[(opcode >> 8) & 0x0F].I; + reg[dest].I = reg[mult].I * rs; + N_FLAG = (reg[dest].I & 0x80000000) ? true : false; + Z_FLAG = (reg[dest].I) ? false : true; + if(((int32)rs)<0) + rs = ~rs; + if((rs & 0xFFFFFF00) == 0) + clockTicks += 0; + else if ((rs & 0xFFFF0000) == 0) + clockTicks += 1; + else if ((rs & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + } + break; + case 0x00b: + case 0x02b: + { + // STRH Rd, [Rn], -Rm + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = reg[opcode & 0x0F].I; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + address -= offset; + reg[base].I = address; + } + break; + case 0x04b: + case 0x06b: + { + // STRH Rd, [Rn], #-offset + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + address -= offset; + reg[base].I = address; + } + break; + case 0x08b: + case 0x0ab: + { + // STRH Rd, [Rn], Rm + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = reg[opcode & 0x0F].I; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + address += offset; + reg[base].I = address; + } + break; + case 0x0cb: + case 0x0eb: + { + // STRH Rd, [Rn], #offset + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + address += offset; + reg[base].I = address; + } + break; + case 0x10b: + { + // STRH Rd, [Rn, -Rm] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - reg[opcode & 0x0F].I; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + } + break; + case 0x12b: + { + // STRH Rd, [Rn, -Rm]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - reg[opcode & 0x0F].I; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + reg[base].I = address; + } + break; + case 0x14b: + { + // STRH Rd, [Rn, -#offset] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + } + break; + case 0x16b: + { + // STRH Rd, [Rn, -#offset]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + reg[base].I = address; + } + break; + case 0x18b: + { + // STRH Rd, [Rn, Rm] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + reg[opcode & 0x0F].I; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + } + break; + case 0x1ab: + { + // STRH Rd, [Rn, Rm]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + reg[opcode & 0x0F].I; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + reg[base].I = address; + } + break; + case 0x1cb: + { + // STRH Rd, [Rn, #offset] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + } + break; + case 0x1eb: + { + // STRH Rd, [Rn, #offset]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + CPUWriteHalfWord(address, reg[dest].W.W0); + reg[base].I = address; + } + break; + case 0x01b: + case 0x03b: + { + // LDRH Rd, [Rn], -Rm + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = reg[opcode & 0x0F].I; + reg[dest].I = CPUReadHalfWord(address); + if(dest != base) { + address -= offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x05b: + case 0x07b: + { + // LDRH Rd, [Rn], #-offset + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); + reg[dest].I = CPUReadHalfWord(address); + if(dest != base) { + address -= offset; + reg[base].I = address; + } + clockTicks=0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x09b: + case 0x0bb: + { + // LDRH Rd, [Rn], Rm + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = reg[opcode & 0x0F].I; + reg[dest].I = CPUReadHalfWord(address); + if(dest != base) { + address += offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x0db: + case 0x0fb: + { + // LDRH Rd, [Rn], #offset + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); + reg[dest].I = CPUReadHalfWord(address); + if(dest != base) { + address += offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x11b: + { + // LDRH Rd, [Rn, -Rm] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - reg[opcode & 0x0F].I; + reg[dest].I = CPUReadHalfWord(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x13b: + { + // LDRH Rd, [Rn, -Rm]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - reg[opcode & 0x0F].I; + reg[dest].I = CPUReadHalfWord(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x15b: + { + // LDRH Rd, [Rn, -#offset] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = CPUReadHalfWord(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x17b: + { + // LDRH Rd, [Rn, -#offset]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = CPUReadHalfWord(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x19b: + { + // LDRH Rd, [Rn, Rm] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + reg[opcode & 0x0F].I; + reg[dest].I = CPUReadHalfWord(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x1bb: + { + // LDRH Rd, [Rn, Rm]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + reg[opcode & 0x0F].I; + reg[dest].I = CPUReadHalfWord(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x1db: + { + // LDRH Rd, [Rn, #offset] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = CPUReadHalfWord(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x1fb: + { + // LDRH Rd, [Rn, #offset]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = CPUReadHalfWord(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x01d: + case 0x03d: + { + // LDRSB Rd, [Rn], -Rm + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = reg[opcode & 0x0F].I; + reg[dest].I = (int8)CPUReadByte(address); + if(dest != base) { + address -= offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x05d: + case 0x07d: + { + // LDRSB Rd, [Rn], #-offset + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); + reg[dest].I = (int8)CPUReadByte(address); + if(dest != base) { + address -= offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x09d: + case 0x0bd: + { + // LDRSB Rd, [Rn], Rm + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = reg[opcode & 0x0F].I; + reg[dest].I = (int8)CPUReadByte(address); + if(dest != base) { + address += offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x0dd: + case 0x0fd: + { + // LDRSB Rd, [Rn], #offset + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); + reg[dest].I = (int8)CPUReadByte(address); + if(dest != base) { + address += offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x11d: + { + // LDRSB Rd, [Rn, -Rm] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - reg[opcode & 0x0F].I; + reg[dest].I = (int8)CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x13d: + { + // LDRSB Rd, [Rn, -Rm]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - reg[opcode & 0x0F].I; + reg[dest].I = (int8)CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x15d: + { + // LDRSB Rd, [Rn, -#offset] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = (int8)CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x17d: + { + // LDRSB Rd, [Rn, -#offset]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = (int8)CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x19d: + { + // LDRSB Rd, [Rn, Rm] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + reg[opcode & 0x0F].I; + reg[dest].I = (int8)CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x1bd: + { + // LDRSB Rd, [Rn, Rm]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + reg[opcode & 0x0F].I; + reg[dest].I = (int8)CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x1dd: + { + // LDRSB Rd, [Rn, #offset] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = (int8)CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x1fd: + { + // LDRSB Rd, [Rn, #offset]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = (int8)CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x01f: + case 0x03f: + { + // LDRSH Rd, [Rn], -Rm + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = reg[opcode & 0x0F].I; + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + if(dest != base) { + address -= offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x05f: + case 0x07f: + { + // LDRSH Rd, [Rn], #-offset + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + if(dest != base) { + address -= offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x09f: + case 0x0bf: + { + // LDRSH Rd, [Rn], Rm + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = reg[opcode & 0x0F].I; + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + if(dest != base) { + address += offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x0df: + case 0x0ff: + { + // LDRSH Rd, [Rn], #offset + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I; + int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0); + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + if(dest != base) { + address += offset; + reg[base].I = address; + } + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x11f: + { + // LDRSH Rd, [Rn, -Rm] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - reg[opcode & 0x0F].I; + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x13f: + { + // LDRSH Rd, [Rn, -Rm]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - reg[opcode & 0x0F].I; + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x15f: + { + // LDRSH Rd, [Rn, -#offset] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x17f: + { + // LDRSH Rd, [Rn, -#offset]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I - ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x19f: + { + // LDRSH Rd, [Rn, Rm] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + reg[opcode & 0x0F].I; + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x1bf: + { + // LDRSH Rd, [Rn, Rm]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + reg[opcode & 0x0F].I; + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x1df: + { + // LDRSH Rd, [Rn, #offset] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x1ff: + { + // LDRSH Rd, [Rn, #offset]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode >> 16) & 0x0F; + int dest = (opcode >> 12) & 0x0F; + uint32 address = reg[base].I + ((opcode & 0x0F)|((opcode>>4)&0xF0)); + reg[dest].I = (int16)CPUReadHalfWordSigned(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EOR, OP_EOR, 0x020); + LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EORS, OP_EOR, 0x030); + case 0x029: + { + // MLA Rd, Rm, Rs, Rn + clockTicks = 2; + int dest = (opcode >> 16) & 0x0F; + int mult = (opcode & 0x0F); + uint32 rs = reg[(opcode >> 8) & 0x0F].I; + reg[dest].I = reg[mult].I * rs + reg[(opcode>>12)&0x0f].I; + if((rs & 0xFFFFFF00) == 0) + clockTicks += 0; + else if ((rs & 0xFFFF0000) == 0) + clockTicks += 1; + else if ((rs & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + } + break; + case 0x039: + { + // MLAS Rd, Rm, Rs, Rn + clockTicks = 2; + int dest = (opcode >> 16) & 0x0F; + int mult = (opcode & 0x0F); + uint32 rs = reg[(opcode >> 8) & 0x0F].I; + reg[dest].I = reg[mult].I * rs + reg[(opcode>>12)&0x0f].I; + N_FLAG = (reg[dest].I & 0x80000000) ? true : false; + Z_FLAG = (reg[dest].I) ? false : true; + if(((int32)rs)<0) + rs = ~rs; + if((rs & 0xFFFFFF00) == 0) + clockTicks += 0; + else if ((rs & 0xFFFF0000) == 0) + clockTicks += 1; + else if ((rs & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + } + break; + ARITHMETIC_DATA_OPCODE(OP_SUB, OP_SUB, 0x040); + ARITHMETIC_DATA_OPCODE(OP_SUBS, OP_SUB, 0x050); + ARITHMETIC_DATA_OPCODE(OP_RSB, OP_RSB, 0x060); + ARITHMETIC_DATA_OPCODE(OP_RSBS, OP_RSB, 0x070); + ARITHMETIC_DATA_OPCODE(OP_ADD, OP_ADD, 0x080); + ARITHMETIC_DATA_OPCODE(OP_ADDS, OP_ADD, 0x090); + case 0x089: + { + // UMULL RdLo, RdHi, Rn, Rs + clockTicks = 2; + uint32 umult = reg[(opcode & 0x0F)].I; + uint32 usource = reg[(opcode >> 8) & 0x0F].I; + int destLo = (opcode >> 12) & 0x0F; + int destHi = (opcode >> 16) & 0x0F; + uint64 uTemp = ((uint64)umult)*((uint64)usource); + reg[destLo].I = (uint32)uTemp; + reg[destHi].I = (uint32)(uTemp >> 32); + if ((usource & 0xFFFFFF00) == 0) + clockTicks += 0; + else if ((usource & 0xFFFF0000) == 0) + clockTicks += 1; + else if ((usource & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + } + break; + case 0x099: + { + // UMULLS RdLo, RdHi, Rn, Rs + clockTicks = 2; + uint32 umult = reg[(opcode & 0x0F)].I; + uint32 usource = reg[(opcode >> 8) & 0x0F].I; + int destLo = (opcode >> 12) & 0x0F; + int destHi = (opcode >> 16) & 0x0F; + uint64 uTemp = ((uint64)umult)*((uint64)usource); + reg[destLo].I = (uint32)uTemp; + reg[destHi].I = (uint32)(uTemp >> 32); + Z_FLAG = (uTemp) ? false : true; + N_FLAG = (reg[destHi].I & 0x80000000) ? true : false; + if ((usource & 0xFFFFFF00) == 0) + clockTicks += 0; + else if ((usource & 0xFFFF0000) == 0) + clockTicks += 1; + else if ((usource & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + } + break; + ARITHMETIC_DATA_OPCODE(OP_ADC, OP_ADC, 0x0a0); + ARITHMETIC_DATA_OPCODE(OP_ADCS, OP_ADC, 0x0b0); + case 0x0a9: + { + // UMLAL RdLo, RdHi, Rn, Rs + clockTicks = 3; + uint32 umult = reg[(opcode & 0x0F)].I; + uint32 usource = reg[(opcode >> 8) & 0x0F].I; + int destLo = (opcode >> 12) & 0x0F; + int destHi = (opcode >> 16) & 0x0F; + uint64 uTemp = (uint64)reg[destHi].I; + uTemp <<= 32; + uTemp |= (uint64)reg[destLo].I; + uTemp += ((uint64)umult)*((uint64)usource); + reg[destLo].I = (uint32)uTemp; + reg[destHi].I = (uint32)(uTemp >> 32); + if ((usource & 0xFFFFFF00) == 0) + clockTicks += 0; + else if ((usource & 0xFFFF0000) == 0) + clockTicks += 1; + else if ((usource & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + } + break; + case 0x0b9: + { + // UMLALS RdLo, RdHi, Rn, Rs + clockTicks = 3; + uint32 umult = reg[(opcode & 0x0F)].I; + uint32 usource = reg[(opcode >> 8) & 0x0F].I; + int destLo = (opcode >> 12) & 0x0F; + int destHi = (opcode >> 16) & 0x0F; + uint64 uTemp = (uint64)reg[destHi].I; + uTemp <<= 32; + uTemp |= (uint64)reg[destLo].I; + uTemp += ((uint64)umult)*((uint64)usource); + reg[destLo].I = (uint32)uTemp; + reg[destHi].I = (uint32)(uTemp >> 32); + Z_FLAG = (uTemp) ? false : true; + N_FLAG = (reg[destHi].I & 0x80000000) ? true : false; + if ((usource & 0xFFFFFF00) == 0) + clockTicks += 0; + else if ((usource & 0xFFFF0000) == 0) + clockTicks += 1; + else if ((usource & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + } + break; + ARITHMETIC_DATA_OPCODE(OP_SBC, OP_SBC, 0x0c0); + ARITHMETIC_DATA_OPCODE(OP_SBCS, OP_SBC, 0x0d0); + case 0x0c9: + { + // SMULL RdLo, RdHi, Rm, Rs + clockTicks = 2; + int destLo = (opcode >> 12) & 0x0F; + int destHi = (opcode >> 16) & 0x0F; + uint32 rs = reg[(opcode >> 8) & 0x0F].I; + int64 m = (int32)reg[(opcode & 0x0F)].I; + int64 s = (int32)rs; + int64 sTemp = m*s; + reg[destLo].I = (uint32)sTemp; + reg[destHi].I = (uint32)(sTemp >> 32); + if(((int32)rs) < 0) + rs = ~rs; + if((rs & 0xFFFFFF00) == 0) + clockTicks += 0; + else if((rs & 0xFFFF0000) == 0) + clockTicks += 1; + else if((rs & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + } + break; + case 0x0d9: + { + // SMULLS RdLo, RdHi, Rm, Rs + clockTicks = 2; + int destLo = (opcode >> 12) & 0x0F; + int destHi = (opcode >> 16) & 0x0F; + uint32 rs = reg[(opcode >> 8) & 0x0F].I; + int64 m = (int32)reg[(opcode & 0x0F)].I; + int64 s = (int32)rs; + int64 sTemp = m*s; + reg[destLo].I = (uint32)sTemp; + reg[destHi].I = (uint32)(sTemp >> 32); + Z_FLAG = (sTemp) ? false : true; + N_FLAG = (sTemp < 0) ? true : false; + if(((int32)rs) < 0) + rs = ~rs; + if((rs & 0xFFFFFF00) == 0) + clockTicks += 0; + else if((rs & 0xFFFF0000) == 0) + clockTicks += 1; + else if((rs & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + clockTicks += codeTicksAccesint32(armNextPC) + 1; + } + break; + ARITHMETIC_DATA_OPCODE(OP_RSC, OP_RSC, 0x0e0); + ARITHMETIC_DATA_OPCODE(OP_RSCS, OP_RSC, 0x0f0); + case 0x0e9: + { + // SMLAL RdLo, RdHi, Rm, Rs + clockTicks = codeTicksAccesint32(armNextPC) + 4; + int destLo = (opcode >> 12) & 0x0F; + int destHi = (opcode >> 16) & 0x0F; + uint32 rs = reg[(opcode >> 8) & 0x0F].I; + int64 m = (int32)reg[(opcode & 0x0F)].I; + int64 s = (int32)rs; + int64 sTemp = (uint64)reg[destHi].I; + sTemp <<= 32; + sTemp |= (uint64)reg[destLo].I; + sTemp += m*s; + reg[destLo].I = (uint32)sTemp; + reg[destHi].I = (uint32)(sTemp >> 32); + if(((int32)rs) < 0) + rs = ~rs; + if((rs & 0xFFFFFF00) == 0) + clockTicks += 0; + else if((rs & 0xFFFF0000) == 0) + clockTicks += 1; + else if((rs & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + } + break; + case 0x0f9: + { + // SMLALS RdLo, RdHi, Rm, Rs + clockTicks = codeTicksAccesint32(armNextPC) + 4; + int destLo = (opcode >> 12) & 0x0F; + int destHi = (opcode >> 16) & 0x0F; + uint32 rs = reg[(opcode >> 8) & 0x0F].I; + int64 m = (int32)reg[(opcode & 0x0F)].I; + int64 s = (int32)rs; + int64 sTemp = (uint64)reg[destHi].I; + sTemp <<= 32; + sTemp |= (uint64)reg[destLo].I; + sTemp += m*s; + reg[destLo].I = (uint32)sTemp; + reg[destHi].I = (uint32)(sTemp >> 32); + Z_FLAG = (sTemp) ? false : true; + N_FLAG = (sTemp < 0) ? true : false; + if(((int32)rs) < 0) + rs = ~rs; + if((rs & 0xFFFFFF00) == 0) + clockTicks += 0; + else if((rs & 0xFFFF0000) == 0) + clockTicks += 1; + else if((rs & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + if (busPrefetchCount==0) + busPrefetchCount = (busPrefetchCount<>(8-clockTicks)); + } + break; + LOGICAL_DATA_OPCODE(OP_TST, OP_TST, 0x110); + case 0x100: + // MRS Rd, CPSR + // TODO: check if right instruction.... + CPUUpdateCPSR(); + reg[(opcode >> 12) & 0x0F].I = reg[16].I; + break; + case 0x109: + { + // SWP Rd, Rm, [Rn] + uint32 address = reg[(opcode >> 16) & 15].I; + uint32 temp = CPUReadMemory(address); + CPUWriteMemory(address, reg[opcode&15].I); + reg[(opcode >> 12) & 15].I = temp; + clockTicks = 4 + dataTicksAccesint32(address) + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + LOGICAL_DATA_OPCODE(OP_TEQ, OP_TEQ, 0x130); + case 0x120: + { + // MSR CPSR_fields, Rm + CPUUpdateCPSR(); + uint32 value = reg[opcode & 15].I; + uint32 newValue = reg[16].I; + if(armMode > 0x10) { + if(opcode & 0x00010000) + newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF); + if(opcode & 0x00020000) + newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00); + if(opcode & 0x00040000) + newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000); + } + if(opcode & 0x00080000) + newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000); + newValue |= 0x10; + CPUSwitchMode(newValue & 0x1f, false); + reg[16].I = newValue; + CPUUpdateFlags(); + if(!armState) { // this should not be allowed, but it seems to work + THUMB_PREFETCH; + reg[15].I = armNextPC + 2; + } + } + break; + case 0x121: + { + // BX Rm + // TODO: check if right instruction... + int base = opcode & 0x0F; + busPrefetchCount=0; + armState = reg[base].I & 1 ? false : true; + if(armState) { + reg[15].I = reg[base].I & 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks = codeTicksAccessSeq32(armNextPC) + + codeTicksAccessSeq32(armNextPC) + codeTicksAccesint32(armNextPC) + 3; + } else { + reg[15].I = reg[base].I & 0xFFFFFFFE; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + clockTicks = codeTicksAccessSeq16(armNextPC) + + codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC) + 3; + } + } + break; + ARITHMETIC_DATA_OPCODE(OP_CMP, OP_CMP, 0x150); + case 0x140: + // MRS Rd, SPSR + // TODO: check if right instruction... + reg[(opcode >> 12) & 0x0F].I = reg[17].I; + break; + case 0x149: + { + // SWPB Rd, Rm, [Rn] + uint32 address = reg[(opcode >> 16) & 15].I; + uint32 temp = CPUReadByte(address); + CPUWriteByte(address, reg[opcode&15].B.B0); + reg[(opcode>>12)&15].I = temp; + clockTicks = 4 + dataTicksAccesint32(address) + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + ARITHMETIC_DATA_OPCODE(OP_CMN, OP_CMN, 0x170); + case 0x160: + { + // MSR SPSR_fields, Rm + uint32 value = reg[opcode & 15].I; + if(armMode > 0x10 && armMode < 0x1f) { + if(opcode & 0x00010000) + reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF); + if(opcode & 0x00020000) + reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00); + if(opcode & 0x00040000) + reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000); + if(opcode & 0x00080000) + reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000); + } + } + break; + LOGICAL_DATA_OPCODE (OP_ORR, OP_ORR, 0x180); + LOGICAL_DATA_OPCODE (OP_ORRS, OP_ORR, 0x190); + LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOV, OP_MOV, 0x1a0); + LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOVS, OP_MOV, 0x1b0); + LOGICAL_DATA_OPCODE (OP_BIC, OP_BIC, 0x1c0); + LOGICAL_DATA_OPCODE (OP_BICS, OP_BIC, 0x1d0); + LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVN, OP_MVN, 0x1e0); + LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVNS, OP_MVN, 0x1f0); +#ifdef BKPT_SUPPORT + case 0x127: + case 0x7ff: // for GDB support + extern void (*dbgSignal)(int,int); + reg[15].I -= 4; + armNextPC -= 4; + dbgSignal(5, (opcode & 0x0f)|((opcode>>4) & 0xfff0)); + return; +#endif + case 0x320: + case 0x321: + case 0x322: + case 0x323: + case 0x324: + case 0x325: + case 0x326: + case 0x327: + case 0x328: + case 0x329: + case 0x32a: + case 0x32b: + case 0x32c: + case 0x32d: + case 0x32e: + case 0x32f: + { + // MSR CPSR_fields, # + CPUUpdateCPSR(); + uint32 value = opcode & 0xFF; + int shift = (opcode & 0xF00) >> 7; + if(shift) { + ROR_IMM_MSR; + } + uint32 newValue = reg[16].I; + if(armMode > 0x10) { + if(opcode & 0x00010000) + newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF); + if(opcode & 0x00020000) + newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00); + if(opcode & 0x00040000) + newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000); + } + if(opcode & 0x00080000) + newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000); + + newValue |= 0x10; + + CPUSwitchMode(newValue & 0x1f, false); + reg[16].I = newValue; + CPUUpdateFlags(); + if(!armState) { // this should not be allowed, but it seems to work + THUMB_PREFETCH; + reg[15].I = armNextPC + 2; + } + } + break; + case 0x360: + case 0x361: + case 0x362: + case 0x363: + case 0x364: + case 0x365: + case 0x366: + case 0x367: + case 0x368: + case 0x369: + case 0x36a: + case 0x36b: + case 0x36c: + case 0x36d: + case 0x36e: + case 0x36f: + { + // MSR SPSR_fields, # + if(armMode > 0x10 && armMode < 0x1f) { + uint32 value = opcode & 0xFF; + int shift = (opcode & 0xF00) >> 7; + if(shift) { + ROR_IMM_MSR; + } + if(opcode & 0x00010000) + reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF); + if(opcode & 0x00020000) + reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00); + if(opcode & 0x00040000) + reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000); + if(opcode & 0x00080000) + reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000); + } + } + break; + CASE_16(0x400) + // T versions shouldn't be different on GBA + CASE_16(0x420) + { + // STR Rd, [Rn], -# + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address - offset; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x480) + // T versions shouldn't be different on GBA + CASE_16(0x4a0) + { + // STR Rd, [Rn], # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address + offset; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x500) + { + // STR Rd, [Rn, -#] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x520) + { + // STR Rd, [Rn, -#]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x580) + { + // STR Rd, [Rn, #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x5a0) + { + // STR Rd, [Rn, #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x410) + { + // LDR Rd, [Rn], -# + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I -= offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x430) + { + // LDRT Rd, [Rn], -# + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I -= offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x490) + { + // LDR Rd, [Rn], # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I += offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x4b0) + { + // LDRT Rd, [Rn], # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I += offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x510) + { + // LDR Rd, [Rn, -#] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x530) + { + // LDR Rd, [Rn, -#]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x590) + { + // LDR Rd, [Rn, #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x5b0) + { + // LDR Rd, [Rn, #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x440) + // T versions shouldn't be different on GBA + CASE_16(0x460) + { + // STRB Rd, [Rn], -# + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address - offset; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x4c0) + // T versions shouldn't be different on GBA + CASE_16(0x4e0) + { + // STRB Rd, [Rn], # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address + offset; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x540) + { + // STRB Rd, [Rn, -#] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x560) + { + // STRB Rd, [Rn, -#]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[base].I = address; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x5c0) + { + // STRB Rd, [Rn, #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x5e0) + { + // STRB Rd, [Rn, #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[base].I = address; + CPUWriteByte(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x450) + // T versions shouldn't be different + CASE_16(0x470) + { + // LDRB Rd, [Rn], -# + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I -= offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x4d0) + CASE_16(0x4f0) // T versions should not be different + { + // LDRB Rd, [Rn], # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I += offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x550) + { + // LDRB Rd, [Rn, -#] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x570) + { + // LDRB Rd, [Rn, -#]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x5d0) + { + // LDRB Rd, [Rn, #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x5f0) + { + // LDRB Rd, [Rn, #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = opcode & 0xFFF; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x600: + case 0x608: + // T versions are the same + case 0x620: + case 0x628: + { + // STR Rd, [Rn], -Rm, LSL # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address - offset; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x602: + case 0x60a: + // T versions are the same + case 0x622: + case 0x62a: + { + // STR Rd, [Rn], -Rm, LSR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address - offset; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x604: + case 0x60c: + // T versions are the same + case 0x624: + case 0x62c: + { + // STR Rd, [Rn], -Rm, ASR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address - offset; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x606: + case 0x60e: + // T versions are the same + case 0x626: + case 0x62e: + { + // STR Rd, [Rn], -Rm, ROR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address - value; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x680: + case 0x688: + // T versions are the same + case 0x6a0: + case 0x6a8: + { + // STR Rd, [Rn], Rm, LSL # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address + offset; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x682: + case 0x68a: + // T versions are the same + case 0x6a2: + case 0x6aa: + { + // STR Rd, [Rn], Rm, LSR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address + offset; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x684: + case 0x68c: + // T versions are the same + case 0x6a4: + case 0x6ac: + { + // STR Rd, [Rn], Rm, ASR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address + offset; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x686: + case 0x68e: + // T versions are the same + case 0x6a6: + case 0x6ae: + { + // STR Rd, [Rn], Rm, ROR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteMemory(address, reg[dest].I); + reg[base].I = address + value; + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x700: + case 0x708: + { + // STR Rd, [Rn, -Rm, LSL #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x702: + case 0x70a: + { + // STR Rd, [Rn, -Rm, LSR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x704: + case 0x70c: + { + // STR Rd, [Rn, -Rm, ASR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x706: + case 0x70e: + { + // STR Rd, [Rn, -Rm, ROR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - value; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x720: + case 0x728: + { + // STR Rd, [Rn, -Rm, LSL #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x722: + case 0x72a: + { + // STR Rd, [Rn, -Rm, LSR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x724: + case 0x72c: + { + // STR Rd, [Rn, -Rm, ASR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x726: + case 0x72e: + { + // STR Rd, [Rn, -Rm, ROR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - value; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x780: + case 0x788: + { + // STR Rd, [Rn, Rm, LSL #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x782: + case 0x78a: + { + // STR Rd, [Rn, Rm, LSR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x784: + case 0x78c: + { + // STR Rd, [Rn, Rm, ASR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x786: + case 0x78e: + { + // STR Rd, [Rn, Rm, ROR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + value; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7a0: + case 0x7a8: + { + // STR Rd, [Rn, Rm, LSL #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7a2: + case 0x7aa: + { + // STR Rd, [Rn, Rm, LSR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7a4: + case 0x7ac: + { + // STR Rd, [Rn, Rm, ASR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7a6: + case 0x7ae: + { + // STR Rd, [Rn, Rm, ROR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + value; + reg[base].I = address; + CPUWriteMemory(address, reg[dest].I); + clockTicks = 2 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x610: + case 0x618: + // T versions are the same + case 0x630: + case 0x638: + { + // LDR Rd, [Rn], -Rm, LSL # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address - offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x612: + case 0x61a: + // T versions are the same + case 0x632: + case 0x63a: + { + // LDR Rd, [Rn], -Rm, LSR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address - offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x614: + case 0x61c: + // T versions are the same + case 0x634: + case 0x63c: + { + // LDR Rd, [Rn], -Rm, ASR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address - offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x616: + case 0x61e: + // T versions are the same + case 0x636: + case 0x63e: + { + // LDR Rd, [Rn], -Rm, ROR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address - value; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x690: + case 0x698: + // T versions are the same + case 0x6b0: + case 0x6b8: + { + // LDR Rd, [Rn], Rm, LSL # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address + offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x692: + case 0x69a: + // T versions are the same + case 0x6b2: + case 0x6ba: + { + // LDR Rd, [Rn], Rm, LSR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address + offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x694: + case 0x69c: + // T versions are the same + case 0x6b4: + case 0x6bc: + { + // LDR Rd, [Rn], Rm, ASR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address + offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x696: + case 0x69e: + // T versions are the same + case 0x6b6: + case 0x6be: + { + // LDR Rd, [Rn], Rm, ROR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address + value; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x710: + case 0x718: + { + // LDR Rd, [Rn, -Rm, LSL #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x712: + case 0x71a: + { + // LDR Rd, [Rn, -Rm, LSR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x714: + case 0x71c: + { + // LDR Rd, [Rn, -Rm, ASR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x716: + case 0x71e: + { + // LDR Rd, [Rn, -Rm, ROR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - value; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x730: + case 0x738: + { + // LDR Rd, [Rn, -Rm, LSL #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x732: + case 0x73a: + { + // LDR Rd, [Rn, -Rm, LSR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x734: + case 0x73c: + { + // LDR Rd, [Rn, -Rm, ASR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x736: + case 0x73e: + { + // LDR Rd, [Rn, -Rm, ROR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - value; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x790: + case 0x798: + { + // LDR Rd, [Rn, Rm, LSL #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x792: + case 0x79a: + { + // LDR Rd, [Rn, Rm, LSR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x794: + case 0x79c: + { + // LDR Rd, [Rn, Rm, ASR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x796: + case 0x79e: + { + // LDR Rd, [Rn, Rm, ROR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + value; + reg[dest].I = CPUReadMemory(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7b0: + case 0x7b8: + { + // LDR Rd, [Rn, Rm, LSL #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7b2: + case 0x7ba: + { + // LDR Rd, [Rn, Rm, LSR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7b4: + case 0x7bc: + { + // LDR Rd, [Rn, Rm, ASR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7b6: + case 0x7be: + { + // LDR Rd, [Rn, Rm, ROR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + value; + reg[dest].I = CPUReadMemory(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint32(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x640: + case 0x648: + // T versions are the same + case 0x660: + case 0x668: + { + // STRB Rd, [Rn], -Rm, LSL # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address - offset; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x642: + case 0x64a: + // T versions are the same + case 0x662: + case 0x66a: + { + // STRB Rd, [Rn], -Rm, LSR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address - offset; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x644: + case 0x64c: + // T versions are the same + case 0x664: + case 0x66c: + { + // STRB Rd, [Rn], -Rm, ASR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address - offset; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x646: + case 0x64e: + // T versions are the same + case 0x666: + case 0x66e: + { + // STRB Rd, [Rn], -Rm, ROR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address - value; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x6c0: + case 0x6c8: + // T versions are the same + case 0x6e0: + case 0x6e8: + { + // STRB Rd, [Rn], Rm, LSL # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address + offset; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x6c2: + case 0x6ca: + // T versions are the same + case 0x6e2: + case 0x6ea: + { + // STRB Rd, [Rn], Rm, LSR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address + offset; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x6c4: + case 0x6cc: + // T versions are the same + case 0x6e4: + case 0x6ec: + { + // STRB Rd, [Rn], Rm, ASR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address + offset; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x6c6: + case 0x6ce: + // T versions are the same + case 0x6e6: + case 0x6ee: + { + // STRB Rd, [Rn], Rm, ROR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + CPUWriteByte(address, reg[dest].B.B0); + reg[base].I = address + value; + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x740: + case 0x748: + { + // STRB Rd, [Rn, -Rm, LSL #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x742: + case 0x74a: + { + // STRB Rd, [Rn, -Rm, LSR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x744: + case 0x74c: + { + // STRB Rd, [Rn, -Rm, ASR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x746: + case 0x74e: + { + // STRB Rd, [Rn, -Rm, ROR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - value; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x760: + case 0x768: + { + // STRB Rd, [Rn, -Rm, LSL #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[base].I = address; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x762: + case 0x76a: + { + // STRB Rd, [Rn, -Rm, LSR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[base].I = address; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x764: + case 0x76c: + { + // STRB Rd, [Rn, -Rm, ASR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[base].I = address; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x766: + case 0x76e: + { + // STRB Rd, [Rn, -Rm, ROR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - value; + reg[base].I = address; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7c0: + case 0x7c8: + { + // STRB Rd, [Rn, Rm, LSL #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7c2: + case 0x7ca: + { + // STRB Rd, [Rn, Rm, LSR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7c4: + case 0x7cc: + { + // STRB Rd, [Rn, Rm, ASR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7c6: + case 0x7ce: + { + // STRB Rd, [Rn, Rm, ROR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + value; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7e0: + case 0x7e8: + { + // STRB Rd, [Rn, Rm, LSL #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[base].I = address; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7e2: + case 0x7ea: + { + // STRB Rd, [Rn, Rm, LSR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[base].I = address; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7e4: + case 0x7ec: + { + // STRB Rd, [Rn, Rm, ASR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[base].I = address; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7e6: + case 0x7ee: + { + // STRB Rd, [Rn, Rm, ROR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + value; + reg[base].I = address; + CPUWriteByte(address, reg[dest].B.B0); + clockTicks = 2 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x650: + case 0x658: + // T versions are the same + case 0x670: + case 0x678: + { + // LDRB Rd, [Rn], -Rm, LSL # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address - offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x652: + case 0x65a: + // T versions are the same + case 0x672: + case 0x67a: + { + // LDRB Rd, [Rn], -Rm, LSR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address - offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x654: + case 0x65c: + // T versions are the same + case 0x674: + case 0x67c: + { + // LDRB Rd, [Rn], -Rm, ASR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address - offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x656: + case 0x65e: + // T versions are the same + case 0x676: + case 0x67e: + { + // LDRB Rd, [Rn], -Rm, ROR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address - value; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x6d0: + case 0x6d8: + // T versions are the same + case 0x6f0: + case 0x6f8: + { + // LDRB Rd, [Rn], Rm, LSL # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address + offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x6d2: + case 0x6da: + // T versions are the same + case 0x6f2: + case 0x6fa: + { + // LDRB Rd, [Rn], Rm, LSR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address + offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x6d4: + case 0x6dc: + // T versions are the same + case 0x6f4: + case 0x6fc: + { + // LDRB Rd, [Rn], Rm, ASR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address + offset; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x6d6: + case 0x6de: + // T versions are the same + case 0x6f6: + case 0x6fe: + { + // LDRB Rd, [Rn], Rm, ROR # + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address + value; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x750: + case 0x758: + { + // LDRB Rd, [Rn, -Rm, LSL #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x752: + case 0x75a: + { + // LDRB Rd, [Rn, -Rm, LSR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x754: + case 0x75c: + { + // LDRB Rd, [Rn, -Rm, ASR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x756: + case 0x75e: + { + // LDRB Rd, [Rn, -Rm, ROR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - value; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x770: + case 0x778: + { + // LDRB Rd, [Rn, -Rm, LSL #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x772: + case 0x77a: + { + // LDRB Rd, [Rn, -Rm, LSR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x774: + case 0x77c: + { + // LDRB Rd, [Rn, -Rm, ASR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - offset; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x776: + case 0x77e: + { + // LDRB Rd, [Rn, -Rm, ROR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I - value; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7d0: + case 0x7d8: + { + // LDRB Rd, [Rn, Rm, LSL #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7d2: + case 0x7da: + { + // LDRB Rd, [Rn, Rm, LSR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7d4: + case 0x7dc: + { + // LDRB Rd, [Rn, Rm, ASR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7d6: + case 0x7de: + { + // LDRB Rd, [Rn, Rm, ROR #] + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + value; + reg[dest].I = CPUReadByte(address); + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7f0: + case 0x7f8: + { + // LDRB Rd, [Rn, Rm, LSL #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int offset = reg[opcode & 15].I << ((opcode>>7)& 31); + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7f2: + case 0x7fa: + { + // LDRB Rd, [Rn, Rm, LSR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset = shift ? reg[opcode & 15].I >> shift : 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7f4: + case 0x7fc: + { + // LDRB Rd, [Rn, Rm, ASR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + int offset; + if(shift) + offset = (int)((int32)reg[opcode & 15].I >> shift); + else if(reg[opcode & 15].I & 0x80000000) + offset = 0xFFFFFFFF; + else + offset = 0; + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + offset; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; + case 0x7f6: + case 0x7fe: + { + // LDRB Rd, [Rn, Rm, ROR #]! + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int shift = (opcode >> 7) & 31; + uint32 value = reg[opcode & 15].I; + if(shift) { + ROR_VALUE; + } else { + RCR_VALUE; + } + int dest = (opcode >> 12) & 15; + int base = (opcode >> 16) & 15; + uint32 address = reg[base].I + value; + reg[dest].I = CPUReadByte(address); + if(dest != base) + reg[base].I = address; + clockTicks = 0; + if(dest == 15) { + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks += 2 + dataTicksAccessSeq32(address) + dataTicksAccessSeq32(address); + } + clockTicks += 3 + dataTicksAccesint16(address) + + codeTicksAccesint32(armNextPC); + } + break; +#define STMW_REG(val,num) \ + if(opcode & (val)) {\ + CPUWriteMemory(address, reg[(num)].I);\ + if(!offset) {\ + reg[base].I = temp;\ + clockTicks += 1 + dataTicksAccesint32(address);\ + offset = 1;\ + } else {\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ + }\ + address += 4;\ + } +#define STM_REG(val,num) \ + if(opcode & (val)) {\ + CPUWriteMemory(address, reg[(num)].I);\ + if(!offset) {\ + clockTicks += 1 + dataTicksAccesint32(address);\ + offset = 1;\ + } else {\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ + }\ + address += 4;\ + } + + CASE_16(0x800) + { + // STMDA Rn, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (temp + 4) & 0xFFFFFFFC; + int offset = 0; + STM_REG(1, 0); + STM_REG(2, 1); + STM_REG(4, 2); + STM_REG(8, 3); + STM_REG(16, 4); + STM_REG(32, 5); + STM_REG(64, 6); + STM_REG(128, 7); + STM_REG(256, 8); + STM_REG(512, 9); + STM_REG(1024, 10); + STM_REG(2048, 11); + STM_REG(4096, 12); + STM_REG(8192, 13); + STM_REG(16384, 14); + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x820) + { + // STMDA Rn!, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (temp+4) & 0xFFFFFFFC; + int offset = 0; + + STMW_REG(1, 0); + STMW_REG(2, 1); + STMW_REG(4, 2); + STMW_REG(8, 3); + STMW_REG(16, 4); + STMW_REG(32, 5); + STMW_REG(64, 6); + STMW_REG(128, 7); + STMW_REG(256, 8); + STMW_REG(512, 9); + STMW_REG(1024, 10); + STMW_REG(2048, 11); + STMW_REG(4096, 12); + STMW_REG(8192, 13); + STMW_REG(16384, 14); + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + reg[base].I = temp; + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x840) + { + // STMDA Rn, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (temp+4) & 0xFFFFFFFC; + int offset = 0; + + STM_REG(1, 0); + STM_REG(2, 1); + STM_REG(4, 2); + STM_REG(8, 3); + STM_REG(16, 4); + STM_REG(32, 5); + STM_REG(64, 6); + STM_REG(128, 7); + + if(armMode == 0x11) { + STM_REG(256, R8_FIQ); + STM_REG(512, R9_FIQ); + STM_REG(1024, R10_FIQ); + STM_REG(2048, R11_FIQ); + STM_REG(4096, R12_FIQ); + } else { + STM_REG(256, 8); + STM_REG(512, 9); + STM_REG(1024, 10); + STM_REG(2048, 11); + STM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + STM_REG(8192, R13_USR); + STM_REG(16384, R14_USR); + } else { + STM_REG(8192, 13); + STM_REG(16384, 14); + } + + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x860) + { + // STMDA Rn!, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (temp+4) & 0xFFFFFFFC; + int offset = 0; + + STMW_REG(1, 0); + STMW_REG(2, 1); + STMW_REG(4, 2); + STMW_REG(8, 3); + STMW_REG(16, 4); + STMW_REG(32, 5); + STMW_REG(64, 6); + STMW_REG(128, 7); + + if(armMode == 0x11) { + STMW_REG(256, R8_FIQ); + STMW_REG(512, R9_FIQ); + STMW_REG(1024, R10_FIQ); + STMW_REG(2048, R11_FIQ); + STMW_REG(4096, R12_FIQ); + } else { + STMW_REG(256, 8); + STMW_REG(512, 9); + STMW_REG(1024, 10); + STMW_REG(2048, 11); + STMW_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + STMW_REG(8192, R13_USR); + STMW_REG(16384, R14_USR); + } else { + STMW_REG(8192, 13); + STMW_REG(16384, 14); + } + + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + reg[base].I = temp; + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + + CASE_16(0x880) + { + // STMIA Rn, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = reg[base].I & 0xFFFFFFFC; + int offset = 0; + STM_REG(1, 0); + STM_REG(2, 1); + STM_REG(4, 2); + STM_REG(8, 3); + STM_REG(16, 4); + STM_REG(32, 5); + STM_REG(64, 6); + STM_REG(128, 7); + STM_REG(256, 8); + STM_REG(512, 9); + STM_REG(1024, 10); + STM_REG(2048, 11); + STM_REG(4096, 12); + STM_REG(8192, 13); + STM_REG(16384, 14); + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x8a0) + { + // STMIA Rn!, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = reg[base].I & 0xFFFFFFFC; + int offset = 0; + uint32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] + + cpuBitsSet[(opcode >> 8) & 255]); + STMW_REG(1, 0); + STMW_REG(2, 1); + STMW_REG(4, 2); + STMW_REG(8, 3); + STMW_REG(16, 4); + STMW_REG(32, 5); + STMW_REG(64, 6); + STMW_REG(128, 7); + STMW_REG(256, 8); + STMW_REG(512, 9); + STMW_REG(1024, 10); + STMW_REG(2048, 11); + STMW_REG(4096, 12); + STMW_REG(8192, 13); + STMW_REG(16384, 14); + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) { + reg[base].I = temp; + clockTicks += 1 + dataTicksAccesint32(address); + } else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x8c0) + { + // STMIA Rn, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = reg[base].I & 0xFFFFFFFC; + int offset = 0; + STM_REG(1, 0); + STM_REG(2, 1); + STM_REG(4, 2); + STM_REG(8, 3); + STM_REG(16, 4); + STM_REG(32, 5); + STM_REG(64, 6); + STM_REG(128, 7); + if(armMode == 0x11) { + STM_REG(256, R8_FIQ); + STM_REG(512, R9_FIQ); + STM_REG(1024, R10_FIQ); + STM_REG(2048, R11_FIQ); + STM_REG(4096, R12_FIQ); + } else { + STM_REG(256, 8); + STM_REG(512, 9); + STM_REG(1024, 10); + STM_REG(2048, 11); + STM_REG(4096, 12); + } + if(armMode != 0x10 && armMode != 0x1f) { + STM_REG(8192, R13_USR); + STM_REG(16384, R14_USR); + } else { + STM_REG(8192, 13); + STM_REG(16384, 14); + } + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x8e0) + { + // STMIA Rn!, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = reg[base].I & 0xFFFFFFFC; + int offset = 0; + uint32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] + + cpuBitsSet[(opcode >> 8) & 255]); + STMW_REG(1, 0); + STMW_REG(2, 1); + STMW_REG(4, 2); + STMW_REG(8, 3); + STMW_REG(16, 4); + STMW_REG(32, 5); + STMW_REG(64, 6); + STMW_REG(128, 7); + if(armMode == 0x11) { + STMW_REG(256, R8_FIQ); + STMW_REG(512, R9_FIQ); + STMW_REG(1024, R10_FIQ); + STMW_REG(2048, R11_FIQ); + STMW_REG(4096, R12_FIQ); + } else { + STMW_REG(256, 8); + STMW_REG(512, 9); + STMW_REG(1024, 10); + STMW_REG(2048, 11); + STMW_REG(4096, 12); + } + if(armMode != 0x10 && armMode != 0x1f) { + STMW_REG(8192, R13_USR); + STMW_REG(16384, R14_USR); + } else { + STMW_REG(8192, 13); + STMW_REG(16384, 14); + } + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) { + reg[base].I = temp; + clockTicks += 1 + dataTicksAccesint32(address); + } else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + + CASE_16(0x900) + { + // STMDB Rn, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = temp & 0xFFFFFFFC; + int offset = 0; + STM_REG(1, 0); + STM_REG(2, 1); + STM_REG(4, 2); + STM_REG(8, 3); + STM_REG(16, 4); + STM_REG(32, 5); + STM_REG(64, 6); + STM_REG(128, 7); + STM_REG(256, 8); + STM_REG(512, 9); + STM_REG(1024, 10); + STM_REG(2048, 11); + STM_REG(4096, 12); + STM_REG(8192, 13); + STM_REG(16384, 14); + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x920) + { + // STMDB Rn!, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = temp & 0xFFFFFFFC; + int offset = 0; + + STMW_REG(1, 0); + STMW_REG(2, 1); + STMW_REG(4, 2); + STMW_REG(8, 3); + STMW_REG(16, 4); + STMW_REG(32, 5); + STMW_REG(64, 6); + STMW_REG(128, 7); + STMW_REG(256, 8); + STMW_REG(512, 9); + STMW_REG(1024, 10); + STMW_REG(2048, 11); + STMW_REG(4096, 12); + STMW_REG(8192, 13); + STMW_REG(16384, 14); + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + reg[base].I = temp; + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x940) + { + // STMDB Rn, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = temp & 0xFFFFFFFC; + int offset = 0; + + STM_REG(1, 0); + STM_REG(2, 1); + STM_REG(4, 2); + STM_REG(8, 3); + STM_REG(16, 4); + STM_REG(32, 5); + STM_REG(64, 6); + STM_REG(128, 7); + + if(armMode == 0x11) { + STM_REG(256, R8_FIQ); + STM_REG(512, R9_FIQ); + STM_REG(1024, R10_FIQ); + STM_REG(2048, R11_FIQ); + STM_REG(4096, R12_FIQ); + } else { + STM_REG(256, 8); + STM_REG(512, 9); + STM_REG(1024, 10); + STM_REG(2048, 11); + STM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + STM_REG(8192, R13_USR); + STM_REG(16384, R14_USR); + } else { + STM_REG(8192, 13); + STM_REG(16384, 14); + } + + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x960) + { + // STMDB Rn!, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = temp & 0xFFFFFFFC; + int offset = 0; + + STMW_REG(1, 0); + STMW_REG(2, 1); + STMW_REG(4, 2); + STMW_REG(8, 3); + STMW_REG(16, 4); + STMW_REG(32, 5); + STMW_REG(64, 6); + STMW_REG(128, 7); + + if(armMode == 0x11) { + STMW_REG(256, R8_FIQ); + STMW_REG(512, R9_FIQ); + STMW_REG(1024, R10_FIQ); + STMW_REG(2048, R11_FIQ); + STMW_REG(4096, R12_FIQ); + } else { + STMW_REG(256, 8); + STMW_REG(512, 9); + STMW_REG(1024, 10); + STMW_REG(2048, 11); + STMW_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + STMW_REG(8192, R13_USR); + STMW_REG(16384, R14_USR); + } else { + STMW_REG(8192, 13); + STMW_REG(16384, 14); + } + + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + reg[base].I = temp; + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + + CASE_16(0x980) + { + // STMIB Rn, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = (reg[base].I+4) & 0xFFFFFFFC; + int offset = 0; + STM_REG(1, 0); + STM_REG(2, 1); + STM_REG(4, 2); + STM_REG(8, 3); + STM_REG(16, 4); + STM_REG(32, 5); + STM_REG(64, 6); + STM_REG(128, 7); + STM_REG(256, 8); + STM_REG(512, 9); + STM_REG(1024, 10); + STM_REG(2048, 11); + STM_REG(4096, 12); + STM_REG(8192, 13); + STM_REG(16384, 14); + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x9a0) + { + // STMIB Rn!, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = (reg[base].I+4) & 0xFFFFFFFC; + int offset = 0; + uint32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] + + cpuBitsSet[(opcode >> 8) & 255]); + STMW_REG(1, 0); + STMW_REG(2, 1); + STMW_REG(4, 2); + STMW_REG(8, 3); + STMW_REG(16, 4); + STMW_REG(32, 5); + STMW_REG(64, 6); + STMW_REG(128, 7); + STMW_REG(256, 8); + STMW_REG(512, 9); + STMW_REG(1024, 10); + STMW_REG(2048, 11); + STMW_REG(4096, 12); + STMW_REG(8192, 13); + STMW_REG(16384, 14); + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) { + reg[base].I = temp; + clockTicks += 1 + dataTicksAccesint32(address); + } else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x9c0) + { + // STMIB Rn, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = (reg[base].I+4) & 0xFFFFFFFC; + int offset = 0; + STM_REG(1, 0); + STM_REG(2, 1); + STM_REG(4, 2); + STM_REG(8, 3); + STM_REG(16, 4); + STM_REG(32, 5); + STM_REG(64, 6); + STM_REG(128, 7); + if(armMode == 0x11) { + STM_REG(256, R8_FIQ); + STM_REG(512, R9_FIQ); + STM_REG(1024, R10_FIQ); + STM_REG(2048, R11_FIQ); + STM_REG(4096, R12_FIQ); + } else { + STM_REG(256, 8); + STM_REG(512, 9); + STM_REG(1024, 10); + STM_REG(2048, 11); + STM_REG(4096, 12); + } + if(armMode != 0x10 && armMode != 0x1f) { + STM_REG(8192, R13_USR); + STM_REG(16384, R14_USR); + } else { + STM_REG(8192, 13); + STM_REG(16384, 14); + } + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x9e0) + { + // STMIB Rn!, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = (reg[base].I+4) & 0xFFFFFFFC; + int offset = 0; + uint32 temp = reg[base].I + 4*(cpuBitsSet[opcode & 0xFF] + + cpuBitsSet[(opcode >> 8) & 255]); + STMW_REG(1, 0); + STMW_REG(2, 1); + STMW_REG(4, 2); + STMW_REG(8, 3); + STMW_REG(16, 4); + STMW_REG(32, 5); + STMW_REG(64, 6); + STMW_REG(128, 7); + if(armMode == 0x11) { + STMW_REG(256, R8_FIQ); + STMW_REG(512, R9_FIQ); + STMW_REG(1024, R10_FIQ); + STMW_REG(2048, R11_FIQ); + STMW_REG(4096, R12_FIQ); + } else { + STMW_REG(256, 8); + STMW_REG(512, 9); + STMW_REG(1024, 10); + STMW_REG(2048, 11); + STMW_REG(4096, 12); + } + if(armMode != 0x10 && armMode != 0x1f) { + STMW_REG(8192, R13_USR); + STMW_REG(16384, R14_USR); + } else { + STMW_REG(8192, 13); + STMW_REG(16384, 14); + } + if(opcode & 32768) { + CPUWriteMemory(address, reg[15].I+4); + if(!offset) { + reg[base].I = temp; + clockTicks += 1 + dataTicksAccesint32(address); + } else + clockTicks += 1 + dataTicksAccessSeq32(address); + } + clockTicks += 1 + codeTicksAccesint32(armNextPC); + } + break; + +#define LDM_REG(val,num) \ + if(opcode & (val)) {\ + reg[(num)].I = CPUReadMemory(address);\ + if(offset)\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ + else {\ + clockTicks += 1 + dataTicksAccesint32(address);\ + offset = 1;\ + }\ + address += 4;\ + } + + CASE_16(0x810) + { + // LDMDA Rn, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (temp + 4) & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + if(opcode & 32768) { + reg[15].I = CPUReadMemory(address); + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x830) + { + // LDMDA Rn!, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (temp + 4) & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + if(opcode & 32768) { + reg[15].I = CPUReadMemory(address); + + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + if(!(opcode & (1 << base))) + reg[base].I = temp; + } + break; + CASE_16(0x850) + { + // LDMDA Rn, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (temp + 4) & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + if(opcode & 0x8000) { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + + reg[15].I = CPUReadMemory(address); + + CPUSwitchMode(reg[17].I & 0x1f, false); + if(armState) { + armNextPC = reg[15].I & 0xFFFFFFFC; + reg[15].I = armNextPC + 4; + ARM_PREFETCH; + } else { + armNextPC = reg[15].I & 0xFFFFFFFE; + reg[15].I = armNextPC + 2; + THUMB_PREFETCH; + } + } else { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + + if(armMode == 0x11) { + LDM_REG(256, R8_FIQ); + LDM_REG(512, R9_FIQ); + LDM_REG(1024, R10_FIQ); + LDM_REG(2048, R11_FIQ); + LDM_REG(4096, R12_FIQ); + } else { + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + LDM_REG(8192, R13_USR); + LDM_REG(16384, R14_USR); + } else { + LDM_REG(8192, 13); + LDM_REG(16384, 14); + } + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x870) + { + // LDMDA Rn!, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (temp + 4) & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + if(opcode & 0x8000) { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + + reg[15].I = CPUReadMemory(address); + + if(!(opcode & (1 << base))) + reg[base].I = temp; + + CPUSwitchMode(reg[17].I & 0x1f, false); + if(armState) { + armNextPC = reg[15].I & 0xFFFFFFFC; + reg[15].I = armNextPC + 4; + ARM_PREFETCH; + } else { + armNextPC = reg[15].I & 0xFFFFFFFE; + reg[15].I = armNextPC + 2; + THUMB_PREFETCH; + } + } else { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + + if(armMode == 0x11) { + LDM_REG(256, R8_FIQ); + LDM_REG(512, R9_FIQ); + LDM_REG(1024, R10_FIQ); + LDM_REG(2048, R11_FIQ); + LDM_REG(4096, R12_FIQ); + } else { + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + LDM_REG(8192, R13_USR); + LDM_REG(16384, R14_USR); + } else { + LDM_REG(8192, 13); + LDM_REG(16384, 14); + } + + if(!(opcode & (1 << base))) + reg[base].I = temp; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + + CASE_16(0x890) + { + // LDMIA Rn, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = reg[base].I & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + if(opcode & 32768) { + reg[15].I = CPUReadMemory(address); + + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x8b0) + { + // LDMIA Rn!, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I + + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = reg[base].I & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + if(opcode & 32768) { + reg[15].I = CPUReadMemory(address); + + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + if(!(opcode & (1 << base))) + reg[base].I = temp; + } + break; + CASE_16(0x8d0) + { + // LDMIA Rn, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = reg[base].I & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + if(opcode & 0x8000) { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + + reg[15].I = CPUReadMemory(address); + + CPUSwitchMode(reg[17].I & 0x1f, false); + if(armState) { + armNextPC = reg[15].I & 0xFFFFFFFC; + reg[15].I = armNextPC + 4; + ARM_PREFETCH; + } else { + armNextPC = reg[15].I & 0xFFFFFFFE; + reg[15].I = armNextPC + 2; + THUMB_PREFETCH; + } + } else { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + + if(armMode == 0x11) { + LDM_REG(256, R8_FIQ); + LDM_REG(512, R9_FIQ); + LDM_REG(1024, R10_FIQ); + LDM_REG(2048, R11_FIQ); + LDM_REG(4096, R12_FIQ); + } else { + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + LDM_REG(8192, R13_USR); + LDM_REG(16384, R14_USR); + } else { + LDM_REG(8192, 13); + LDM_REG(16384, 14); + } + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x8f0) + { + // LDMIA Rn!, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I + + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = reg[base].I & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + if(opcode & 0x8000) { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + + reg[15].I = CPUReadMemory(address); + + if(!(opcode & (1 << base))) + reg[base].I = temp; + + CPUSwitchMode(reg[17].I & 0x1f, false); + if(armState) { + armNextPC = reg[15].I & 0xFFFFFFFC; + reg[15].I = armNextPC + 4; + ARM_PREFETCH; + } else { + armNextPC = reg[15].I & 0xFFFFFFFE; + reg[15].I = armNextPC + 2; + THUMB_PREFETCH; + } + } else { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + + if(armMode == 0x11) { + LDM_REG(256, R8_FIQ); + LDM_REG(512, R9_FIQ); + LDM_REG(1024, R10_FIQ); + LDM_REG(2048, R11_FIQ); + LDM_REG(4096, R12_FIQ); + } else { + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + LDM_REG(8192, R13_USR); + LDM_REG(16384, R14_USR); + } else { + LDM_REG(8192, 13); + LDM_REG(16384, 14); + } + + if(!(opcode & (1 << base))) + reg[base].I = temp; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + + CASE_16(0x910) + { + // LDMDB Rn, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = temp & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + if(opcode & 32768) { + reg[15].I = CPUReadMemory(address); + + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x930) + { + // LDMDB Rn!, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = temp & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + if(opcode & 32768) { + reg[15].I = CPUReadMemory(address); + + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + if(!(opcode & (1 << base))) + reg[base].I = temp; + } + break; + CASE_16(0x950) + { + // LDMDB Rn, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = temp & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + if(opcode & 0x8000) { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + + reg[15].I = CPUReadMemory(address); + + CPUSwitchMode(reg[17].I & 0x1f, false); + if(armState) { + armNextPC = reg[15].I & 0xFFFFFFFC; + reg[15].I = armNextPC + 4; + ARM_PREFETCH; + } else { + armNextPC = reg[15].I & 0xFFFFFFFE; + reg[15].I = armNextPC + 2; + THUMB_PREFETCH; + } + } else { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + + if(armMode == 0x11) { + LDM_REG(256, R8_FIQ); + LDM_REG(512, R9_FIQ); + LDM_REG(1024, R10_FIQ); + LDM_REG(2048, R11_FIQ); + LDM_REG(4096, R12_FIQ); + } else { + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + LDM_REG(8192, R13_USR); + LDM_REG(16384, R14_USR); + } else { + LDM_REG(8192, 13); + LDM_REG(16384, 14); + } + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x970) + { + // LDMDB Rn!, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I - + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = temp & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + if(opcode & 0x8000) { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + + reg[15].I = CPUReadMemory(address); + + if(!(opcode & (1 << base))) + reg[base].I = temp; + + CPUSwitchMode(reg[17].I & 0x1f, false); + if(armState) { + armNextPC = reg[15].I & 0xFFFFFFFC; + reg[15].I = armNextPC + 4; + ARM_PREFETCH; + } else { + armNextPC = reg[15].I & 0xFFFFFFFE; + reg[15].I = armNextPC + 2; + THUMB_PREFETCH; + } + } else { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + + if(armMode == 0x11) { + LDM_REG(256, R8_FIQ); + LDM_REG(512, R9_FIQ); + LDM_REG(1024, R10_FIQ); + LDM_REG(2048, R11_FIQ); + LDM_REG(4096, R12_FIQ); + } else { + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + LDM_REG(8192, R13_USR); + LDM_REG(16384, R14_USR); + } else { + LDM_REG(8192, 13); + LDM_REG(16384, 14); + } + + if(!(opcode & (1 << base))) + reg[base].I = temp; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + + CASE_16(0x990) + { + // LDMIB Rn, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = (reg[base].I+4) & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + if(opcode & 32768) { + reg[15].I = CPUReadMemory(address); + + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x9b0) + { + // LDMIB Rn!, {Rlist} + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I + + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (reg[base].I+4) & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + if(opcode & 32768) { + reg[15].I = CPUReadMemory(address); + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + dataTicksAccessSeq32(address); + + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + if(!(opcode & (1 << base))) + reg[base].I = temp; + } + break; + CASE_16(0x9d0) + { + // LDMIB Rn, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 address = (reg[base].I+4) & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + if(opcode & 0x8000) { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + + reg[15].I = CPUReadMemory(address); + + CPUSwitchMode(reg[17].I & 0x1f, false); + if(armState) { + armNextPC = reg[15].I & 0xFFFFFFFC; + reg[15].I = armNextPC + 4; + ARM_PREFETCH; + } else { + armNextPC = reg[15].I & 0xFFFFFFFE; + reg[15].I = armNextPC + 2; + THUMB_PREFETCH; + } + } else { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + + if(armMode == 0x11) { + LDM_REG(256, R8_FIQ); + LDM_REG(512, R9_FIQ); + LDM_REG(1024, R10_FIQ); + LDM_REG(2048, R11_FIQ); + LDM_REG(4096, R12_FIQ); + } else { + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + LDM_REG(8192, R13_USR); + LDM_REG(16384, R14_USR); + } else { + LDM_REG(8192, 13); + LDM_REG(16384, 14); + } + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + CASE_16(0x9f0) + { + // LDMIB Rn!, {Rlist}^ + if (busPrefetchCount==0) + busPrefetch = busPrefetchEnable; + int base = (opcode & 0x000F0000) >> 16; + uint32 temp = reg[base].I + + 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]); + uint32 address = (reg[base].I+4) & 0xFFFFFFFC; + clockTicks = 0; + int offset = 0; + if(opcode & 0x8000) { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + LDM_REG(8192, 13); + LDM_REG(16384, 14); + + reg[15].I = CPUReadMemory(address); + + if(!(opcode & (1 << base))) + reg[base].I = temp; + + CPUSwitchMode(reg[17].I & 0x1f, false); + if(armState) { + armNextPC = reg[15].I & 0xFFFFFFFC; + reg[15].I = armNextPC + 4; + ARM_PREFETCH; + } else { + armNextPC = reg[15].I & 0xFFFFFFFE; + reg[15].I = armNextPC + 2; + THUMB_PREFETCH; + } + } else { + LDM_REG(1, 0); + LDM_REG(2, 1); + LDM_REG(4, 2); + LDM_REG(8, 3); + LDM_REG(16, 4); + LDM_REG(32, 5); + LDM_REG(64, 6); + LDM_REG(128, 7); + + if(armMode == 0x11) { + LDM_REG(256, R8_FIQ); + LDM_REG(512, R9_FIQ); + LDM_REG(1024, R10_FIQ); + LDM_REG(2048, R11_FIQ); + LDM_REG(4096, R12_FIQ); + } else { + LDM_REG(256, 8); + LDM_REG(512, 9); + LDM_REG(1024, 10); + LDM_REG(2048, 11); + LDM_REG(4096, 12); + } + + if(armMode != 0x10 && armMode != 0x1f) { + LDM_REG(8192, R13_USR); + LDM_REG(16384, R14_USR); + } else { + LDM_REG(8192, 13); + LDM_REG(16384, 14); + } + + if(!(opcode & (1 << base))) + reg[base].I = temp; + if (!offset) + clockTicks += 1 + dataTicksAccesint32(address); + else + clockTicks += 1 + dataTicksAccessSeq32(address); + clockTicks += 1 + codeTicksAccessSeq32(armNextPC); + } + clockTicks += 2 + codeTicksAccesint32(armNextPC); + } + break; + CASE_256(0xa00) + { + // B + int offset = opcode & 0x00FFFFFF; + if(offset & 0x00800000) { + offset |= 0xFF000000; + } + offset <<= 2; + reg[15].I += offset; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks = codeTicksAccessSeq32(armNextPC) + 1; + clockTicks += 2 + codeTicksAccesint32(armNextPC) + + codeTicksAccessSeq32(armNextPC); + busPrefetchCount=0; + } + break; + CASE_256(0xb00) + { + // BL + int offset = opcode & 0x00FFFFFF; + if(offset & 0x00800000) { + offset |= 0xFF000000; + } + offset <<= 2; + reg[14].I = reg[15].I - 4; + reg[15].I += offset; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + clockTicks = codeTicksAccessSeq32(armNextPC) + 1; + clockTicks += 2 + codeTicksAccesint32(armNextPC) + + codeTicksAccessSeq32(armNextPC); + busPrefetchCount=0; + } + break; + CASE_256(0xf00) + // SWI + clockTicks = codeTicksAccessSeq32(armNextPC) + 1; + clockTicks += 2 + codeTicksAccesint32(armNextPC) + + codeTicksAccessSeq32(armNextPC); + busPrefetchCount=0; + CPUSoftwareInterrupt(opcode & 0x00FFFFFF); + + break; +#ifdef GP_SUPPORT + case 0xe11: + case 0xe13: + case 0xe15: + case 0xe17: + case 0xe19: + case 0xe1b: + case 0xe1d: + case 0xe1f: + // MRC + break; + case 0xe01: + case 0xe03: + case 0xe05: + case 0xe07: + case 0xe09: + case 0xe0b: + case 0xe0d: + case 0xe0f: + // MRC + break; +#endif + default: + CPUUndefinedException(); + break; + // END + } +} + + if (clockTicks == 0) + clockTicks = codeTicksAccessSeq32(oldArmNextPC) + 1; + + return(clockTicks); +} + +} diff --git a/mednafen/gba-09333/arm.h b/mednafen/gba-09333/arm.h new file mode 100644 index 0000000..da762d8 --- /dev/null +++ b/mednafen/gba-09333/arm.h @@ -0,0 +1,6 @@ +namespace MDFN_IEN_GBA +{ + +unsigned int RunARM(void); + +} diff --git a/mednafen/gba-09333/bios.cpp b/mednafen/gba-09333/bios.cpp new file mode 100644 index 0000000..0e0ba7b --- /dev/null +++ b/mednafen/gba-09333/bios.cpp @@ -0,0 +1,1165 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "bios.h" +#include "GBAinline.h" +#include "Globals.h" + +#include +#include + +namespace MDFN_IEN_GBA +{ + +static const int16 sineTable[256] = { + (int16)0x0000, (int16)0x0192, (int16)0x0323, (int16)0x04B5, (int16)0x0645, (int16)0x07D5, (int16)0x0964, (int16)0x0AF1, + (int16)0x0C7C, (int16)0x0E05, (int16)0x0F8C, (int16)0x1111, (int16)0x1294, (int16)0x1413, (int16)0x158F, (int16)0x1708, + (int16)0x187D, (int16)0x19EF, (int16)0x1B5D, (int16)0x1CC6, (int16)0x1E2B, (int16)0x1F8B, (int16)0x20E7, (int16)0x223D, + (int16)0x238E, (int16)0x24DA, (int16)0x261F, (int16)0x275F, (int16)0x2899, (int16)0x29CD, (int16)0x2AFA, (int16)0x2C21, + (int16)0x2D41, (int16)0x2E5A, (int16)0x2F6B, (int16)0x3076, (int16)0x3179, (int16)0x3274, (int16)0x3367, (int16)0x3453, + (int16)0x3536, (int16)0x3612, (int16)0x36E5, (int16)0x37AF, (int16)0x3871, (int16)0x392A, (int16)0x39DA, (int16)0x3A82, + (int16)0x3B20, (int16)0x3BB6, (int16)0x3C42, (int16)0x3CC5, (int16)0x3D3E, (int16)0x3DAE, (int16)0x3E14, (int16)0x3E71, + (int16)0x3EC5, (int16)0x3F0E, (int16)0x3F4E, (int16)0x3F84, (int16)0x3FB1, (int16)0x3FD3, (int16)0x3FEC, (int16)0x3FFB, + (int16)0x4000, (int16)0x3FFB, (int16)0x3FEC, (int16)0x3FD3, (int16)0x3FB1, (int16)0x3F84, (int16)0x3F4E, (int16)0x3F0E, + (int16)0x3EC5, (int16)0x3E71, (int16)0x3E14, (int16)0x3DAE, (int16)0x3D3E, (int16)0x3CC5, (int16)0x3C42, (int16)0x3BB6, + (int16)0x3B20, (int16)0x3A82, (int16)0x39DA, (int16)0x392A, (int16)0x3871, (int16)0x37AF, (int16)0x36E5, (int16)0x3612, + (int16)0x3536, (int16)0x3453, (int16)0x3367, (int16)0x3274, (int16)0x3179, (int16)0x3076, (int16)0x2F6B, (int16)0x2E5A, + (int16)0x2D41, (int16)0x2C21, (int16)0x2AFA, (int16)0x29CD, (int16)0x2899, (int16)0x275F, (int16)0x261F, (int16)0x24DA, + (int16)0x238E, (int16)0x223D, (int16)0x20E7, (int16)0x1F8B, (int16)0x1E2B, (int16)0x1CC6, (int16)0x1B5D, (int16)0x19EF, + (int16)0x187D, (int16)0x1708, (int16)0x158F, (int16)0x1413, (int16)0x1294, (int16)0x1111, (int16)0x0F8C, (int16)0x0E05, + (int16)0x0C7C, (int16)0x0AF1, (int16)0x0964, (int16)0x07D5, (int16)0x0645, (int16)0x04B5, (int16)0x0323, (int16)0x0192, + (int16)0x0000, (int16)0xFE6E, (int16)0xFCDD, (int16)0xFB4B, (int16)0xF9BB, (int16)0xF82B, (int16)0xF69C, (int16)0xF50F, + (int16)0xF384, (int16)0xF1FB, (int16)0xF074, (int16)0xEEEF, (int16)0xED6C, (int16)0xEBED, (int16)0xEA71, (int16)0xE8F8, + (int16)0xE783, (int16)0xE611, (int16)0xE4A3, (int16)0xE33A, (int16)0xE1D5, (int16)0xE075, (int16)0xDF19, (int16)0xDDC3, + (int16)0xDC72, (int16)0xDB26, (int16)0xD9E1, (int16)0xD8A1, (int16)0xD767, (int16)0xD633, (int16)0xD506, (int16)0xD3DF, + (int16)0xD2BF, (int16)0xD1A6, (int16)0xD095, (int16)0xCF8A, (int16)0xCE87, (int16)0xCD8C, (int16)0xCC99, (int16)0xCBAD, + (int16)0xCACA, (int16)0xC9EE, (int16)0xC91B, (int16)0xC851, (int16)0xC78F, (int16)0xC6D6, (int16)0xC626, (int16)0xC57E, + (int16)0xC4E0, (int16)0xC44A, (int16)0xC3BE, (int16)0xC33B, (int16)0xC2C2, (int16)0xC252, (int16)0xC1EC, (int16)0xC18F, + (int16)0xC13B, (int16)0xC0F2, (int16)0xC0B2, (int16)0xC07C, (int16)0xC04F, (int16)0xC02D, (int16)0xC014, (int16)0xC005, + (int16)0xC000, (int16)0xC005, (int16)0xC014, (int16)0xC02D, (int16)0xC04F, (int16)0xC07C, (int16)0xC0B2, (int16)0xC0F2, + (int16)0xC13B, (int16)0xC18F, (int16)0xC1EC, (int16)0xC252, (int16)0xC2C2, (int16)0xC33B, (int16)0xC3BE, (int16)0xC44A, + (int16)0xC4E0, (int16)0xC57E, (int16)0xC626, (int16)0xC6D6, (int16)0xC78F, (int16)0xC851, (int16)0xC91B, (int16)0xC9EE, + (int16)0xCACA, (int16)0xCBAD, (int16)0xCC99, (int16)0xCD8C, (int16)0xCE87, (int16)0xCF8A, (int16)0xD095, (int16)0xD1A6, + (int16)0xD2BF, (int16)0xD3DF, (int16)0xD506, (int16)0xD633, (int16)0xD767, (int16)0xD8A1, (int16)0xD9E1, (int16)0xDB26, + (int16)0xDC72, (int16)0xDDC3, (int16)0xDF19, (int16)0xE075, (int16)0xE1D5, (int16)0xE33A, (int16)0xE4A3, (int16)0xE611, + (int16)0xE783, (int16)0xE8F8, (int16)0xEA71, (int16)0xEBED, (int16)0xED6C, (int16)0xEEEF, (int16)0xF074, (int16)0xF1FB, + (int16)0xF384, (int16)0xF50F, (int16)0xF69C, (int16)0xF82B, (int16)0xF9BB, (int16)0xFB4B, (int16)0xFCDD, (int16)0xFE6E +}; + +void BIOS_ArcTan() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("ArcTan: %08x (VCOUNT=%2d)\n", + reg[0].I, + VCOUNT); + } +#endif + + int32 a = -(((int32)(reg[0].I*reg[0].I)) >> 14); + int32 b = ((0xA9 * a) >> 14) + 0x390; + b = ((b * a) >> 14) + 0x91C; + b = ((b * a) >> 14) + 0xFB6; + b = ((b * a) >> 14) + 0x16AA; + b = ((b * a) >> 14) + 0x2081; + b = ((b * a) >> 14) + 0x3651; + b = ((b * a) >> 14) + 0xA2F9; + a = ((int32)reg[0].I * b) >> 16; + reg[0].I = a; + +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("ArcTan: return=%08x\n", + reg[0].I); + } +#endif +} + +void BIOS_ArcTan2() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("ArcTan2: %08x,%08x (VCOUNT=%2d)\n", + reg[0].I, + reg[1].I, + VCOUNT); + } +#endif + + int32 x = reg[0].I; + int32 y = reg[1].I; + uint32 res = 0; + if (y == 0) { + res = ((x>>16) & 0x8000); + } else { + if (x == 0) { + res = ((y>>16) & 0x8000) + 0x4000; + } else { + if ((abs(x) > abs(y)) || ((abs(x) == abs(y)) && (!((x<0) && (y<0))))) { + reg[1].I = x; + reg[0].I = y << 14; + BIOS_Div(); + BIOS_ArcTan(); + if (x < 0) + res = 0x8000 + reg[0].I; + else + res = (((y>>16) & 0x8000)<<1) + reg[0].I; + } else { + reg[0].I = x << 14; + BIOS_Div(); + BIOS_ArcTan(); + res = (0x4000 + ((y>>16) & 0x8000)) - reg[0].I; + } + } + } + reg[0].I = res; + +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("ArcTan2: return=%08x\n", + reg[0].I); + } +#endif +} + +void BIOS_BitUnPack() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("BitUnPack: %08x,%08x,%08x (VCOUNT=%2d)\n", + reg[0].I, + reg[1].I, + reg[2].I, + VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + uint32 header = reg[2].I; + + int len = CPUReadHalfWord(header); + // check address + if(((source & 0xe000000) == 0) || ((source + len) & 0xe000000) == 0) + return; + int bits = CPUReadByte(header+2); + int revbits = 8 - bits; + // uint32 value = 0; + uint32 base = CPUReadMemory(header+4); + bool addBase = (base & 0x80000000) ? true : false; + base &= 0x7fffffff; + int dataSize = CPUReadByte(header+3); + + int data = 0; + int bitwritecount = 0; + while(1) { + len -= 1; + if(len < 0) + break; + int mask = 0xff >> revbits; + uint8 b = CPUReadByte(source); + source++; + int bitcount = 0; + while(1) { + if(bitcount >= 8) + break; + uint32 d = b & mask; + uint32 temp = d >> bitcount; + if(d || addBase) { + temp += base; + } + data |= temp << bitwritecount; + bitwritecount += dataSize; + if(bitwritecount >= 32) { + CPUWriteMemory(dest, data); + dest += 4; + data = 0; + bitwritecount = 0; + } + mask <<= bits; + bitcount += bits; + } + } +} + +void BIOS_BgAffineSet() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("BgAffineSet: %08x,%08x,%08x (VCOUNT=%2d)\n", + reg[0].I, + reg[1].I, + reg[2].I, + VCOUNT); + } +#endif + + uint32 src = reg[0].I; + uint32 dest = reg[1].I; + int num = reg[2].I; + + for(int i = 0; i < num; i++) { + int32 cx = CPUReadMemory(src); + src+=4; + int32 cy = CPUReadMemory(src); + src+=4; + int16 dispx = CPUReadHalfWord(src); + src+=2; + int16 dispy = CPUReadHalfWord(src); + src+=2; + int16 rx = CPUReadHalfWord(src); + src+=2; + int16 ry = CPUReadHalfWord(src); + src+=2; + uint16 theta = CPUReadHalfWord(src)>>8; + src+=4; // keep structure alignment + int32 a = sineTable[(theta+0x40)&255]; + int32 b = sineTable[theta]; + + int16 dx = (rx * a)>>14; + int16 dmx = (rx * b)>>14; + int16 dy = (ry * b)>>14; + int16 dmy = (ry * a)>>14; + + CPUWriteHalfWord(dest, dx); + dest += 2; + CPUWriteHalfWord(dest, -dmx); + dest += 2; + CPUWriteHalfWord(dest, dy); + dest += 2; + CPUWriteHalfWord(dest, dmy); + dest += 2; + + int32 startx = cx - dx * dispx + dmx * dispy; + int32 starty = cy - dy * dispx - dmy * dispy; + + CPUWriteMemory(dest, startx); + dest += 4; + CPUWriteMemory(dest, starty); + dest += 4; + } +} + +void BIOS_CpuSet() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("CpuSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I, + reg[2].I, VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + uint32 cnt = reg[2].I; + + if(((source & 0xe000000) == 0) || + ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0) + return; + + int count = cnt & 0x1FFFFF; + + // 32-bit ? + if((cnt >> 26) & 1) { + // needed for 32-bit mode! + source &= 0xFFFFFFFC; + dest &= 0xFFFFFFFC; + // fill ? + if((cnt >> 24) & 1) { + uint32 value = (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source)); + while(count) { + CPUWriteMemory(dest, value); + dest += 4; + count--; + } + } else { + // copy + while(count) { + CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0x1CAD1CAD : CPUReadMemory(source))); + source += 4; + dest += 4; + count--; + } + } + } else { + // 16-bit fill? + if((cnt >> 24) & 1) { + uint16 value = (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source)); + while(count) { + CPUWriteHalfWord(dest, value); + dest += 2; + count--; + } + } else { + // copy + while(count) { + CPUWriteHalfWord(dest, (source>0x0EFFFFFF ? 0x1CAD : CPUReadHalfWord(source))); + source += 2; + dest += 2; + count--; + } + } + } +} + +void BIOS_CpuFastSet() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("CpuFastSet: 0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I, + reg[2].I, VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + uint32 cnt = reg[2].I; + + if(((source & 0xe000000) == 0) || + ((source + (((cnt << 11)>>9) & 0x1fffff)) & 0xe000000) == 0) + return; + + // needed for 32-bit mode! + source &= 0xFFFFFFFC; + dest &= 0xFFFFFFFC; + + int count = cnt & 0x1FFFFF; + + // fill? + if((cnt >> 24) & 1) { + while(count > 0) { + // BIOS always transfers 32 bytes at a time + uint32 value = (source>0x0EFFFFFF ? 0xBAFFFFFB : CPUReadMemory(source)); + for(int i = 0; i < 8; i++) { + CPUWriteMemory(dest, value); + dest += 4; + } + count -= 8; + } + } else { + // copy + while(count > 0) { + // BIOS always transfers 32 bytes at a time + for(int i = 0; i < 8; i++) { + CPUWriteMemory(dest, (source>0x0EFFFFFF ? 0xBAFFFFFB :CPUReadMemory(source))); + source += 4; + dest += 4; + } + count -= 8; + } + } +} + +void BIOS_Diff8bitUnFilterWram() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("Diff8bitUnFilterWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, + reg[1].I, VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + + uint32 header = CPUReadMemory(source); + source += 4; + + if(((source & 0xe000000) == 0) || + (((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)) + return; + + int len = header >> 8; + + uint8 data = CPUReadByte(source++); + CPUWriteByte(dest++, data); + len--; + + while(len > 0) { + uint8 diff = CPUReadByte(source++); + data += diff; + CPUWriteByte(dest++, data); + len--; + } +} + +void BIOS_Diff8bitUnFilterVram() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("Diff8bitUnFilterVram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, + reg[1].I, VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + + uint32 header = CPUReadMemory(source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return; + + int len = header >> 8; + + uint8 data = CPUReadByte(source++); + uint16 writeData = data; + int shift = 8; + int bytes = 1; + + while(len >= 2) { + uint8 diff = CPUReadByte(source++); + data += diff; + writeData |= (data << shift); + bytes++; + shift += 8; + if(bytes == 2) { + CPUWriteHalfWord(dest, writeData); + dest += 2; + len -= 2; + bytes = 0; + writeData = 0; + shift = 0; + } + } +} + +void BIOS_Diff16bitUnFilter() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("Diff16bitUnFilter: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, + reg[1].I, VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + + uint32 header = CPUReadMemory(source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return; + + int len = header >> 8; + + uint16 data = CPUReadHalfWord(source); + source += 2; + CPUWriteHalfWord(dest, data); + dest += 2; + len -= 2; + + while(len >= 2) { + uint16 diff = CPUReadHalfWord(source); + source += 2; + data += diff; + CPUWriteHalfWord(dest, data); + dest += 2; + len -= 2; + } +} + +void BIOS_Div() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("Div: 0x%08x,0x%08x (VCOUNT=%d)\n", + reg[0].I, + reg[1].I, + VCOUNT); + } +#endif + + int number = reg[0].I; + int denom = reg[1].I; + + if(denom != 0) { + reg[0].I = number / denom; + reg[1].I = number % denom; + int32 temp = (int32)reg[0].I; + reg[3].I = temp < 0 ? (uint32)-temp : (uint32)temp; + } +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("Div: return=0x%08x,0x%08x,0x%08x\n", + reg[0].I, + reg[1].I, + reg[3].I); + } +#endif +} + +void BIOS_DivARM() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("DivARM: 0x%08x, (VCOUNT=%d)\n", + reg[0].I, + VCOUNT); + } +#endif + + uint32 temp = reg[0].I; + reg[0].I = reg[1].I; + reg[1].I = temp; + BIOS_Div(); +} + +void BIOS_HuffUnComp() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("HuffUnComp: 0x%08x,0x%08x (VCOUNT=%d)\n", + reg[0].I, + reg[1].I, + VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + + uint32 header = CPUReadMemory(source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return; + + uint8 treeSize = CPUReadByte(source++); + + uint32 treeStart = source; + + source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte + + int len = header >> 8; + + uint32 mask = 0x80000000; + uint32 data = CPUReadMemory(source); + source += 4; + + int pos = 0; + uint8 rootNode = CPUReadByte(treeStart); + uint8 currentNode = rootNode; + bool writeData = false; + int byteShift = 0; + int byteCount = 0; + uint32 writeValue = 0; + + if((header & 0x0F) == 8) { + while(len > 0) { + // take left + if(pos == 0) + pos++; + else + pos += (((currentNode & 0x3F)+1)<<1); + + if(data & mask) { + // right + if(currentNode & 0x40) + writeData = true; + currentNode = CPUReadByte(treeStart+pos+1); + } else { + // left + if(currentNode & 0x80) + writeData = true; + currentNode = CPUReadByte(treeStart+pos); + } + + if(writeData) { + writeValue |= (currentNode << byteShift); + byteCount++; + byteShift += 8; + + pos = 0; + currentNode = rootNode; + writeData = false; + + if(byteCount == 4) { + byteCount = 0; + byteShift = 0; + CPUWriteMemory(dest, writeValue); + writeValue = 0; + dest += 4; + len -= 4; + } + } + mask >>= 1; + if(mask == 0) { + mask = 0x80000000; + data = CPUReadMemory(source); + source += 4; + } + } + } else { + int halfLen = 0; + int value = 0; + while(len > 0) { + // take left + if(pos == 0) + pos++; + else + pos += (((currentNode & 0x3F)+1)<<1); + + if((data & mask)) { + // right + if(currentNode & 0x40) + writeData = true; + currentNode = CPUReadByte(treeStart+pos+1); + } else { + // left + if(currentNode & 0x80) + writeData = true; + currentNode = CPUReadByte(treeStart+pos); + } + + if(writeData) { + if(halfLen == 0) + value |= currentNode; + else + value |= (currentNode<<4); + + halfLen += 4; + if(halfLen == 8) { + writeValue |= (value << byteShift); + byteCount++; + byteShift += 8; + + halfLen = 0; + value = 0; + + if(byteCount == 4) { + byteCount = 0; + byteShift = 0; + CPUWriteMemory(dest, writeValue); + dest += 4; + writeValue = 0; + len -= 4; + } + } + pos = 0; + currentNode = rootNode; + writeData = false; + } + mask >>= 1; + if(mask == 0) { + mask = 0x80000000; + data = CPUReadMemory(source); + source += 4; + } + } + } +} + +void BIOS_LZ77UnCompVram() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("LZ77UnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n", + reg[0].I, + reg[1].I, + VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + + uint32 header = CPUReadMemory(source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return; + + int byteCount = 0; + int byteShift = 0; + uint32 writeValue = 0; + + int len = header >> 8; + + while(len > 0) { + uint8 d = CPUReadByte(source++); + + if(d) { + for(int i = 0; i < 8; i++) { + if(d & 0x80) { + uint16 data = CPUReadByte(source++) << 8; + data |= CPUReadByte(source++); + int length = (data >> 12) + 3; + int offset = (data & 0x0FFF); + uint32 windowOffset = dest + byteCount - offset - 1; + + for(int j = 0; j < length; j++) { + writeValue |= (CPUReadByte(windowOffset++) << byteShift); + byteShift += 8; + byteCount++; + + if(byteCount == 2) { + CPUWriteHalfWord(dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return; + } + } else { + writeValue |= (CPUReadByte(source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + CPUWriteHalfWord(dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return; + } + d <<= 1; + } + } else { + for(int i = 0; i < 8; i++) { + writeValue |= (CPUReadByte(source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + CPUWriteHalfWord(dest, writeValue); + dest += 2; + byteShift = 0; + byteCount = 0; + writeValue = 0; + } + len--; + if(len == 0) + return; + } + } + } +} + +void BIOS_LZ77UnCompWram() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("LZ77UnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n", reg[0].I, reg[1].I, + VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + + uint32 header = CPUReadMemory(source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return; + + int len = header >> 8; + + while(len > 0) { + uint8 d = CPUReadByte(source++); + + if(d) { + for(int i = 0; i < 8; i++) { + if(d & 0x80) { + uint16 data = CPUReadByte(source++) << 8; + data |= CPUReadByte(source++); + int length = (data >> 12) + 3; + int offset = (data & 0x0FFF); + uint32 windowOffset = dest - offset - 1; + for(int j = 0; j < length; j++) { + CPUWriteByte(dest++, CPUReadByte(windowOffset++)); + len--; + if(len == 0) + return; + } + } else { + CPUWriteByte(dest++, CPUReadByte(source++)); + len--; + if(len == 0) + return; + } + d <<= 1; + } + } else { + for(int i = 0; i < 8; i++) { + CPUWriteByte(dest++, CPUReadByte(source++)); + len--; + if(len == 0) + return; + } + } + } +} + +void BIOS_ObjAffineSet() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("ObjAffineSet: 0x%08x,0x%08x,0x%08x,0x%08x (VCOUNT=%d)\n", + reg[0].I, + reg[1].I, + reg[2].I, + reg[3].I, + VCOUNT); + } +#endif + + uint32 src = reg[0].I; + uint32 dest = reg[1].I; + int num = reg[2].I; + int offset = reg[3].I; + + for(int i = 0; i < num; i++) { + int16 rx = CPUReadHalfWord(src); + src+=2; + int16 ry = CPUReadHalfWord(src); + src+=2; + uint16 theta = CPUReadHalfWord(src)>>8; + src+=4; // keep structure alignment + + int32 a = (int32)sineTable[(theta+0x40)&255]; + int32 b = (int32)sineTable[theta]; + + int16 dx = ((int32)rx * a)>>14; + int16 dmx = ((int32)rx * b)>>14; + int16 dy = ((int32)ry * b)>>14; + int16 dmy = ((int32)ry * a)>>14; + + CPUWriteHalfWord(dest, dx); + dest += offset; + CPUWriteHalfWord(dest, -dmx); + dest += offset; + CPUWriteHalfWord(dest, dy); + dest += offset; + CPUWriteHalfWord(dest, dmy); + dest += offset; + } +} + +void BIOS_RegisterRamReset(uint32 flags) +{ + // no need to trace here. this is only called directly from GBA.cpp + // to emulate bios initialization + + CPUUpdateRegister(0x0, 0x80); + + if(flags) { + if(flags & 0x01) { + // clear work RAM + memset(workRAM, 0, 0x40000); + } + if(flags & 0x02) { + // clear internal RAM + memset(internalRAM, 0, 0x7e00); // don't clear 0x7e00-0x7fff + } + if(flags & 0x04) { + // clear palette RAM + memset(paletteRAM, 0, 0x400); + } + if(flags & 0x08) { + // clear VRAM + memset(vram, 0, 0x18000); + } + if(flags & 0x10) { + // clean OAM + memset(oam, 0, 0x400); + } + + if(flags & 0x80) { + int i; + for(i = 0; i < 0x10; i++) + CPUUpdateRegister(0x200+i*2, 0); + + for(i = 0; i < 0xF; i++) + CPUUpdateRegister(0x4+i*2, 0); + + for(i = 0; i < 0x20; i++) + CPUUpdateRegister(0x20+i*2, 0); + + for(i = 0; i < 0x18; i++) + CPUUpdateRegister(0xb0+i*2, 0); + + CPUUpdateRegister(0x130, 0); + CPUUpdateRegister(0x20, 0x100); + CPUUpdateRegister(0x30, 0x100); + CPUUpdateRegister(0x26, 0x100); + CPUUpdateRegister(0x36, 0x100); + } + + if(flags & 0x20) { + int i; + for(i = 0; i < 8; i++) + CPUUpdateRegister(0x110+i*2, 0); + CPUUpdateRegister(0x134, 0x8000); + for(i = 0; i < 7; i++) + CPUUpdateRegister(0x140+i*2, 0); + } + + if(flags & 0x40) { + int i; + CPUWriteByte(0x4000084, 0); + CPUWriteByte(0x4000084, 0x80); + CPUWriteMemory(0x4000080, 0x880e0000); + CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff); + CPUWriteByte(0x4000070, 0x70); + for(i = 0; i < 8; i++) + CPUUpdateRegister(0x90+i*2, 0); + CPUWriteByte(0x4000070, 0); + for(i = 0; i < 8; i++) + CPUUpdateRegister(0x90+i*2, 0); + CPUWriteByte(0x4000084, 0); + } + } +} + +void BIOS_RegisterRamReset() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("RegisterRamReset: 0x%08x (VCOUNT=%d)\n", + reg[0].I, + VCOUNT); + } +#endif + + BIOS_RegisterRamReset(reg[0].I); +} + +void BIOS_RLUnCompVram() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("RLUnCompVram: 0x%08x,0x%08x (VCOUNT=%d)\n", + reg[0].I, + reg[1].I, + VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + + uint32 header = CPUReadMemory(source & 0xFFFFFFFC); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return; + + int len = header >> 8; + int byteCount = 0; + int byteShift = 0; + uint32 writeValue = 0; + + while(len > 0) { + uint8 d = CPUReadByte(source++); + int l = d & 0x7F; + if(d & 0x80) { + uint8 data = CPUReadByte(source++); + l += 3; + for(int i = 0;i < l; i++) { + writeValue |= (data << byteShift); + byteShift += 8; + byteCount++; + + if(byteCount == 2) { + CPUWriteHalfWord(dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return; + } + } else { + l++; + for(int i = 0; i < l; i++) { + writeValue |= (CPUReadByte(source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + CPUWriteHalfWord(dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return; + } + } + } +} + +void BIOS_RLUnCompWram() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("RLUnCompWram: 0x%08x,0x%08x (VCOUNT=%d)\n", + reg[0].I, + reg[1].I, + VCOUNT); + } +#endif + + uint32 source = reg[0].I; + uint32 dest = reg[1].I; + + uint32 header = CPUReadMemory(source & 0xFFFFFFFC); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return; + + int len = header >> 8; + + while(len > 0) { + uint8 d = CPUReadByte(source++); + int l = d & 0x7F; + if(d & 0x80) { + uint8 data = CPUReadByte(source++); + l += 3; + for(int i = 0;i < l; i++) { + CPUWriteByte(dest++, data); + len--; + if(len == 0) + return; + } + } else { + l++; + for(int i = 0; i < l; i++) { + CPUWriteByte(dest++, CPUReadByte(source++)); + len--; + if(len == 0) + return; + } + } + } +} + +void BIOS_SoftReset() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("SoftReset: (VCOUNT=%d)\n", VCOUNT); + } +#endif + + armState = true; + armMode = 0x1F; + armIrqEnable = false; + C_FLAG = V_FLAG = Z_FLAG = false; + N_FLAG = 0; + + reg[13].I = 0x03007F00; + reg[14].I = 0x00000000; + reg[16].I = 0x00000000; + reg[R13_IRQ].I = 0x03007FA0; + reg[R14_IRQ].I = 0x00000000; + reg[SPSR_IRQ].I = 0x00000000; + reg[R13_SVC].I = 0x03007FE0; + reg[R14_SVC].I = 0x00000000; + reg[SPSR_SVC].I = 0x00000000; + uint8 b = internalRAM[0x7ffa]; + + memset(&internalRAM[0x7e00], 0, 0x200); + + if(b) { + armNextPC = 0x02000000; + reg[15].I = 0x02000004; + } else { + armNextPC = 0x08000000; + reg[15].I = 0x08000004; + } +} + +void BIOS_Sqrt() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("Sqrt: %08x (VCOUNT=%2d)\n", + reg[0].I, + VCOUNT); + } +#endif + reg[0].I = (uint32)sqrt((double)reg[0].I); +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("Sqrt: return=%08x\n", + reg[0].I); + } +#endif +} + +void BIOS_MidiKey2Freq() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("MidiKey2Freq: WaveData=%08x mk=%08x fp=%08x\n", + reg[0].I, + reg[1].I, + reg[2].I); + } +#endif + int freq = CPUReadMemory(reg[0].I+4); + double tmp; + tmp = ((double)(180 - reg[1].I)) - ((double)reg[2].I / 256.f); + tmp = pow((double)2.f, tmp / 12.f); + reg[0].I = (int)((double)freq / tmp); + +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("MidiKey2Freq: return %08x\n", + reg[0].I); + } +#endif +} + +void BIOS_SndDriverJmpTableCopy() +{ +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_SWI) { + log("SndDriverJmpTableCopy: dest=%08x\n", + reg[0].I); + } +#endif + for(int i = 0; i < 0x24; i++) { + CPUWriteMemory(reg[0].I, 0x9c); + reg[0].I += 4; + } +} + +} diff --git a/mednafen/gba-09333/bios.h b/mednafen/gba-09333/bios.h new file mode 100644 index 0000000..2c0d9fe --- /dev/null +++ b/mednafen/gba-09333/bios.h @@ -0,0 +1,52 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_BIOS_H +#define VBA_BIOS_H + +namespace MDFN_IEN_GBA +{ + +extern void BIOS_ArcTan(); +extern void BIOS_ArcTan2(); +extern void BIOS_BitUnPack(); +extern void BIOS_BgAffineSet(); +extern void BIOS_CpuSet(); +extern void BIOS_CpuFastSet(); +extern void BIOS_Diff8bitUnFilterWram(); +extern void BIOS_Diff8bitUnFilterVram(); +extern void BIOS_Diff16bitUnFilter(); +extern void BIOS_Div(); +extern void BIOS_DivARM(); +extern void BIOS_HuffUnComp(); +extern void BIOS_LZ77UnCompVram(); +extern void BIOS_LZ77UnCompWram(); +extern void BIOS_ObjAffineSet(); +extern void BIOS_RegisterRamReset(); +extern void BIOS_RegisterRamReset(uint32); +extern void BIOS_RLUnCompVram(); +extern void BIOS_RLUnCompWram(); +extern void BIOS_SoftReset(); +extern void BIOS_Sqrt(); +extern void BIOS_MidiKey2Freq(); +extern void BIOS_SndDriverJmpTableCopy(); + +} + +#endif // VBA_BIOS_H diff --git a/mednafen/gba-09333/eeprom.cpp b/mednafen/gba-09333/eeprom.cpp new file mode 100644 index 0000000..3ac15e8 --- /dev/null +++ b/mednafen/gba-09333/eeprom.cpp @@ -0,0 +1,223 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include +#include "eeprom.h" + +namespace MDFN_IEN_GBA +{ + +extern int cpuDmaCount; + +int eepromMode = EEPROM_IDLE; +int eepromByte = 0; +int eepromBits = 0; +int eepromAddress = 0; +uint8 eepromData[0x2000]; +static uint8 eepromBuffer[16]; +bool eepromInUse = false; +int eepromSize = 512; + +#include "../state.h" + +SFORMAT eepromSaveData[] = +{ + SFVAR(eepromMode), + SFVAR(eepromByte), + SFVAR(eepromBits), + SFVAR(eepromAddress), + SFVAR(eepromInUse), + SFVAR(eepromSize), + SFARRAYN(eepromData, 0x2000, "eepromData"), + SFARRAYN(eepromBuffer, 16, "eepromBuffer"), + SFEND +}; + +bool GBA_EEPROM_SaveFile(const char *filename) +{ + if(eepromInUse) + { + if(!MDFN_DumpToFile(filename, 0, eepromData, eepromSize)) + return(0); + } + + return(1); +} + +bool GBA_EEPROM_LoadFile(const char *filename) +{ + FILE *fp = fopen(filename, "rb"); + + if(fp) + { + long size; + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if(size == 512 || size == 0x2000) + { + if((long)fread(eepromData, 1, size, fp) == size) + { + eepromInUse = TRUE; + eepromSize = size; + fclose(fp); + return(1); + } + } + fclose(fp); + } + + return(0); +} + + +void eepromInit(void) +{ + memset(eepromData, 0xFF, sizeof(eepromData)); +} + +void eepromReset(void) +{ + eepromMode = EEPROM_IDLE; + eepromByte = 0; + eepromBits = 0; + eepromAddress = 0; + eepromInUse = false; + eepromSize = 512; +} + +int eepromRead(uint32 /* address */) +{ + switch(eepromMode) { + case EEPROM_IDLE: + case EEPROM_READADDRESS: + case EEPROM_WRITEDATA: + return 1; + case EEPROM_READDATA: + { + eepromBits++; + if(eepromBits == 4) { + eepromMode = EEPROM_READDATA2; + eepromBits = 0; + eepromByte = 0; + } + return 0; + } + case EEPROM_READDATA2: + { + int data = 0; + int address = eepromAddress << 3; + int mask = 1 << (7 - (eepromBits & 7)); + data = (eepromData[address+eepromByte] & mask) ? 1 : 0; + eepromBits++; + if((eepromBits & 7) == 0) + eepromByte++; + if(eepromBits == 0x40) + eepromMode = EEPROM_IDLE; + return data; + } + default: + return 0; + } + return 1; +} + +void eepromWrite(uint32 /* address */, uint8 value) +{ + if(cpuDmaCount == 0) + return; + int bit = value & 1; + switch(eepromMode) { + case EEPROM_IDLE: + eepromByte = 0; + eepromBits = 1; + eepromBuffer[eepromByte] = bit; + eepromMode = EEPROM_READADDRESS; + break; + case EEPROM_READADDRESS: + eepromBuffer[eepromByte] <<= 1; + eepromBuffer[eepromByte] |= bit; + eepromBits++; + if((eepromBits & 7) == 0) { + eepromByte++; + } + if(cpuDmaCount == 0x11 || cpuDmaCount == 0x51) { + if(eepromBits == 0x11) { + eepromInUse = true; + eepromSize = 0x2000; + eepromAddress = ((eepromBuffer[0] & 0x3F) << 8) | + ((eepromBuffer[1] & 0xFF)); + if(!(eepromBuffer[0] & 0x40)) { + eepromBuffer[0] = bit; + eepromBits = 1; + eepromByte = 0; + eepromMode = EEPROM_WRITEDATA; + } else { + eepromMode = EEPROM_READDATA; + eepromByte = 0; + eepromBits = 0; + } + } + } else { + if(eepromBits == 9) { + eepromInUse = true; + eepromAddress = (eepromBuffer[0] & 0x3F); + if(!(eepromBuffer[0] & 0x40)) { + eepromBuffer[0] = bit; + eepromBits = 1; + eepromByte = 0; + eepromMode = EEPROM_WRITEDATA; + } else { + eepromMode = EEPROM_READDATA; + eepromByte = 0; + eepromBits = 0; + } + } + } + break; + case EEPROM_READDATA: + case EEPROM_READDATA2: + // should we reset here? + eepromMode = EEPROM_IDLE; + break; + case EEPROM_WRITEDATA: + eepromBuffer[eepromByte] <<= 1; + eepromBuffer[eepromByte] |= bit; + eepromBits++; + if((eepromBits & 7) == 0) { + eepromByte++; + } + if(eepromBits == 0x40) { + eepromInUse = true; + // write data; + for(int i = 0; i < 8; i++) { + eepromData[(eepromAddress << 3) + i] = eepromBuffer[i]; + } + } else if(eepromBits == 0x41) { + eepromMode = EEPROM_IDLE; + eepromByte = 0; + eepromBits = 0; + } + break; + } +} + +} diff --git a/mednafen/gba-09333/eeprom.h b/mednafen/gba-09333/eeprom.h new file mode 100644 index 0000000..3483b2d --- /dev/null +++ b/mednafen/gba-09333/eeprom.h @@ -0,0 +1,46 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_EEPROM_H +#define VBA_EEPROM_H + +namespace MDFN_IEN_GBA +{ + +bool GBA_EEPROM_SaveFile(const char *filename) MDFN_COLD; +bool GBA_EEPROM_LoadFile(const char *filename) MDFN_COLD; + + +int eepromRead(uint32 address); +void eepromWrite(uint32 address, uint8 value); +void eepromInit(void) MDFN_COLD; +void eepromReset(void) MDFN_COLD; +extern bool eepromInUse; +extern int eepromSize; +extern uint8 eepromData[0x2000]; + +#define EEPROM_IDLE 0 +#define EEPROM_READADDRESS 1 +#define EEPROM_READDATA 2 +#define EEPROM_READDATA2 3 +#define EEPROM_WRITEDATA 4 + +} + +#endif // VBA_EEPROM_H diff --git a/mednafen/gba-09333/flash.cpp b/mednafen/gba-09333/flash.cpp new file mode 100644 index 0000000..f128b1f --- /dev/null +++ b/mednafen/gba-09333/flash.cpp @@ -0,0 +1,229 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Globals.h" +#include "flash.h" +#include "sram.h" + +#include + +namespace MDFN_IEN_GBA +{ + +#define FLASH_READ_ARRAY 0 +#define FLASH_CMD_1 1 +#define FLASH_CMD_2 2 +#define FLASH_AUTOSELECT 3 +#define FLASH_CMD_3 4 +#define FLASH_CMD_4 5 +#define FLASH_CMD_5 6 +#define FLASH_ERASE_COMPLETE 7 +#define FLASH_PROGRAM 8 +#define FLASH_SETBANK 9 + +uint8 *flashSaveMemory = NULL; +int flashState = FLASH_READ_ARRAY; +int flashReadState = FLASH_READ_ARRAY; +int flashSize = 0x10000; +static int flashDeviceID = 0x1b; +static int flashManufacturerID = 0x32; +static int flashBank = 0; + +int GBA_Flash_StateAction(StateMem *sm, int load, int data_only) +{ + SFORMAT flashSaveData[] = + { + SFVAR(flashState), + SFVAR(flashReadState), + SFVAR(flashSize), + SFVAR(flashBank), + SFARRAYN(flashSaveMemory, 0x20000, "flashSaveMemory"), + SFEND + }; + + int ret = MDFNSS_StateAction(sm, load, data_only, flashSaveData, "FLSH"); + + return(ret); +}; + +bool GBA_Flash_Init(void) +{ + if(!(flashSaveMemory = (uint8 *)MDFN_malloc(0x20000, _("flash memory")))) + return(0); + + memset(flashSaveMemory, 0x00, 0x20000); + return(1); +} + +void GBA_Flash_Kill(void) +{ + if(flashSaveMemory) + { + free(flashSaveMemory); + flashSaveMemory = NULL; + } +} + +void GBA_Flash_Reset(void) +{ + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + flashBank = 0; +} + +void flashSetSize(int size) +{ + //printf("Setting flash size to %d\n", size); + flashSize = size; + if(size == 0x10000) { + flashDeviceID = 0x1b; + flashManufacturerID = 0x32; + } else { + flashDeviceID = 0x13; //0x09; + flashManufacturerID = 0x62; //0xc2; + } +} + +uint8 flashRead(uint32 address) +{ + // log("Reading %08x from %08x\n", address, reg[15].I); + // log("Current read state is %d\n", flashReadState); + address &= 0xFFFF; + + //printf("Read: %04x\n", address); + switch(flashReadState) { + case FLASH_READ_ARRAY: + return flashSaveMemory[(flashBank << 16) + address]; + case FLASH_AUTOSELECT: + switch(address & 0xFF) { + case 0: + // manufacturer ID + return flashManufacturerID; + case 1: + // device ID + return flashDeviceID; + } + break; + case FLASH_ERASE_COMPLETE: + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + return 0xFF; + }; + return 0; +} + +void flashWrite(uint32 address, uint8 byte) +{ + + //printf("Writing %02x at %08x\n", byte, address); + // log("Current state is %d\n", flashState); + address &= 0xFFFF; + switch(flashState) { + case FLASH_READ_ARRAY: + if(address == 0x5555 && byte == 0xAA) + flashState = FLASH_CMD_1; + break; + case FLASH_CMD_1: + if(address == 0x2AAA && byte == 0x55) + flashState = FLASH_CMD_2; + else + flashState = FLASH_READ_ARRAY; + break; + case FLASH_CMD_2: + if(address == 0x5555) { + if(byte == 0x90) { + flashState = FLASH_AUTOSELECT; + flashReadState = FLASH_AUTOSELECT; + } else if(byte == 0x80) { + flashState = FLASH_CMD_3; + } else if(byte == 0xF0) { + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + } else if(byte == 0xA0) { + flashState = FLASH_PROGRAM; + } else if(byte == 0xB0 && flashSize == 0x20000) { + flashState = FLASH_SETBANK; + } else { + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + } + } else { + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + } + break; + case FLASH_CMD_3: + if(address == 0x5555 && byte == 0xAA) { + flashState = FLASH_CMD_4; + } else { + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + } + break; + case FLASH_CMD_4: + if(address == 0x2AAA && byte == 0x55) { + flashState = FLASH_CMD_5; + } else { + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + } + break; + case FLASH_CMD_5: + if(byte == 0x30) { + // SECTOR ERASE + memset(&flashSaveMemory[(flashBank << 16) + (address & 0xF000)], + 0x00, + 0x1000); + flashReadState = FLASH_ERASE_COMPLETE; + } else if(byte == 0x10) { + // CHIP ERASE + memset(flashSaveMemory, 0, flashSize); + flashReadState = FLASH_ERASE_COMPLETE; + } else { + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + } + break; + case FLASH_AUTOSELECT: + if(byte == 0xF0) { + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + } else if(address == 0x5555 && byte == 0xAA) + flashState = FLASH_CMD_1; + else { + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + } + break; + case FLASH_PROGRAM: + flashSaveMemory[(flashBank<<16)+address] = byte; + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + break; + case FLASH_SETBANK: + if(address == 0) { + flashBank = (byte & 1); + } + flashState = FLASH_READ_ARRAY; + flashReadState = FLASH_READ_ARRAY; + break; + } +} + +} diff --git a/mednafen/gba-09333/flash.h b/mednafen/gba-09333/flash.h new file mode 100644 index 0000000..4e72e0e --- /dev/null +++ b/mednafen/gba-09333/flash.h @@ -0,0 +1,43 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_FLASH_H +#define VBA_FLASH_H + +namespace MDFN_IEN_GBA +{ + +bool GBA_Flash_Init(void) MDFN_COLD; +void GBA_Flash_Kill(void) MDFN_COLD; +void GBA_Flash_Reset(void) MDFN_COLD; + +extern void flashSaveGame(FILE *gzFile) MDFN_COLD; +extern void flashReadGame(FILE *gzFile, int version) MDFN_COLD; +extern uint8 flashRead(uint32 address); +extern void flashWrite(uint32 address, uint8 byte); +extern uint8 *flashSaveMemory; +extern void flashSetSize(int size); + +extern int flashSize; + +int GBA_Flash_StateAction(StateMem *sm, int load, int data_only); + +} + +#endif // VBA_FLASH_H diff --git a/mednafen/gba-09333/gfx-draw.h b/mednafen/gba-09333/gfx-draw.h new file mode 100644 index 0000000..e0b6350 --- /dev/null +++ b/mednafen/gba-09333/gfx-draw.h @@ -0,0 +1,233 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_GFX_DRAW_H +#define VBA_GFX_DRAW_H + +#include "Gfx.h" + +namespace MDFN_IEN_GBA +{ + +//#define SPRITE_DEBUG + +void gfxDrawTextScreen(uint16, uint16, uint16, uint32 *); +void gfxDrawRotScreen(uint16, + uint16, uint16, + uint16, uint16, + uint16, uint16, + uint16, uint16, + int&, int&, + int, + uint32*); +void gfxDrawRotScreen16Bit(uint16, + uint16, uint16, + uint16, uint16, + uint16, uint16, + uint16, uint16, + int&, int&, + int, + uint32*); +void gfxDrawRotScreen256(uint16, + uint16, uint16, + uint16, uint16, + uint16, uint16, + uint16, uint16, + int&, int&, + int, + uint32*); +void gfxDrawRotScreen16Bit160(uint16, + uint16, uint16, + uint16, uint16, + uint16, uint16, + uint16, uint16, + int&, int&, + int, + uint32*); +void gfxDrawSprites(void); + +void gfxDrawOBJWin(void); + + + +//void gfxIncreaseBrightness(uint32 *line, int coeff); +//void gfxDecreaseBrightness(uint32 *line, int coeff); +//void gfxAlphaBlend(uint32 *ta, uint32 *tb, int ca, int cb); + +extern uint32 AlphaClampLUT[64]; +extern MDFN_ALIGN(16) uint32 line0[512]; +extern MDFN_ALIGN(16) uint32 line1[512]; +extern MDFN_ALIGN(16) uint32 line2[512]; +extern MDFN_ALIGN(16) uint32 line3[512]; +extern MDFN_ALIGN(16) uint32 lineOBJ[512]; +extern MDFN_ALIGN(16) uint32 lineOBJWin[512]; +extern MDFN_ALIGN(16) uint32 lineMix[512]; +extern bool gfxInWin0[512]; +extern bool gfxInWin1[512]; + +extern int gfxBG2Changed; +extern int gfxBG3Changed; + +extern int gfxBG2X; +extern int gfxBG2Y; +extern int gfxBG2LastX; +extern int gfxBG2LastY; +extern int gfxBG3X; +extern int gfxBG3Y; +extern int gfxBG3LastX; +extern int gfxBG3LastY; +extern int gfxLastVCOUNT; + +static INLINE void gfxClearArray(uint32 *array) +{ + MDFN_FastU32MemsetM8(array, 0x80000000, 240); + // for(int i = 0; i < 240; i++) { + // *array++ = 0x80000000; + // } +} + +// Max coefficient is 16, so... +static INLINE uint32 gfxIncreaseBrightness(uint32 color, int coeff) +{ + int r = (color & 0x1F); + int g = ((color >> 5) & 0x1F); + int b = ((color >> 10) & 0x1F); + + r = r + (((31 - r) * coeff) >> 4); + g = g + (((31 - g) * coeff) >> 4); + b = b + (((31 - b) * coeff) >> 4); + //if(r > 31) + // r = 31; + //if(g > 31) + // g = 31; + //if(b > 31) + // b = 31; + color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; + return color; +} + +static INLINE void gfxIncreaseBrightness(uint32 *line, int coeff) +{ + for(int x = 0; x < 240; x++) { + uint32 color = *line; + int r = (color & 0x1F); + int g = ((color >> 5) & 0x1F); + int b = ((color >> 10) & 0x1F); + + r = r + (((31 - r) * coeff) >> 4); + g = g + (((31 - g) * coeff) >> 4); + b = b + (((31 - b) * coeff) >> 4); + //if(r > 31) + // r = 31; + //if(g > 31) + // g = 31; + //if(b > 31) + // b = 31; + *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; + } +} + +static INLINE uint32 gfxDecreaseBrightness(uint32 color, int coeff) +{ + int r = (color & 0x1F); + int g = ((color >> 5) & 0x1F); + int b = ((color >> 10) & 0x1F); + + r = r - ((r * coeff) >> 4); + g = g - ((g * coeff) >> 4); + b = b - ((b * coeff) >> 4); + //if(r < 0) + // r = 0; + //if(g < 0) + // g = 0; + //if(b < 0) + // b = 0; + color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; + + return color; +} + +static INLINE void gfxDecreaseBrightness(uint32 *line, int coeff) +{ + for(int x = 0; x < 240; x++) { + uint32 color = *line; + int r = (color & 0x1F); + int g = ((color >> 5) & 0x1F); + int b = ((color >> 10) & 0x1F); + + r = r - ((r * coeff) >> 4); + g = g - ((g * coeff) >> 4); + b = b - ((b * coeff) >> 4); + //if(r < 0) + // r = 0; + //if(g < 0) + // g = 0; + //if(b < 0) + // b = 0; + *line++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; + } +} + +static INLINE uint32 gfxAlphaBlend(uint32 color, uint32 color2, int ca, int cb) +{ + if(color < 0x80000000) { + int r = (color & 0x1F); + int g = ((color >> 5) & 0x1F); + int b = ((color >> 10) & 0x1F); + int r0 = (color2 & 0x1F); + int g0 = ((color2 >> 5) & 0x1F); + int b0 = ((color2 >> 10) & 0x1F); + + r = AlphaClampLUT[((r * ca) >> 4) + ((r0 * cb) >> 4)]; + g = AlphaClampLUT[((g * ca) >> 4) + ((g0 * cb) >> 4)]; + b = AlphaClampLUT[((b * ca) >> 4) + ((b0 * cb) >> 4)]; + + return (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; + } + return color; +} + +static INLINE void gfxAlphaBlend(uint32 *ta, uint32 *tb, int ca, int cb) +{ + for(int x = 0; x < 240; x++) { + uint32 color = *ta; + if(color < 0x80000000) { + int r = (color & 0x1F); + int g = ((color >> 5) & 0x1F); + int b = ((color >> 10) & 0x1F); + uint32 color2 = (*tb++); + int r0 = (color2 & 0x1F); + int g0 = ((color2 >> 5) & 0x1F); + int b0 = ((color2 >> 10) & 0x1F); + + r = AlphaClampLUT[((r * ca) >> 4) + ((r0 * cb) >> 4)]; + g = AlphaClampLUT[((g * ca) >> 4) + ((g0 * cb) >> 4)]; + b = AlphaClampLUT[((b * ca) >> 4) + ((b0 * cb) >> 4)]; + + *ta++ = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r; + } else { + ta++; + tb++; + } + } +} + +} + +#endif // VBA_GFX_DRAW_H diff --git a/mednafen/gba-09333/myrom.h b/mednafen/gba-09333/myrom.h new file mode 100644 index 0000000..28b51ce --- /dev/null +++ b/mednafen/gba-09333/myrom.h @@ -0,0 +1,174 @@ +0xEA000006, +0xEA000093, +0xEA000006, +0x00000000, +0x00000000, +0x00000000, +0xEA000088, +0x00000000, +0xE3A00302, +0xE1A0F000, +0xE92D5800, +0xE55EC002, +0xE28FB03C, +0xE79BC10C, +0xE14FB000, +0xE92D0800, +0xE20BB080, +0xE38BB01F, +0xE129F00B, +0xE92D4004, +0xE1A0E00F, +0xE12FFF1C, +0xE8BD4004, +0xE3A0C0D3, +0xE129F00C, +0xE8BD0800, +0xE169F00B, +0xE8BD5800, +0xE1B0F00E, +0x0000009C, +0x0000009C, +0x0000009C, +0x0000009C, +0x000001F8, +0x000001F0, +0x000000AC, +0x000000A0, +0x000000FC, +0x00000168, +0xE12FFF1E, +0xE1A03000, +0xE1A00001, +0xE1A01003, +0xE2113102, +0x42611000, +0xE033C040, +0x22600000, +0xE1B02001, +0xE15200A0, +0x91A02082, +0x3AFFFFFC, +0xE1500002, +0xE0A33003, +0x20400002, +0xE1320001, +0x11A020A2, +0x1AFFFFF9, +0xE1A01000, +0xE1A00003, +0xE1B0C08C, +0x22600000, +0x42611000, +0xE12FFF1E, +0xE92D0010, +0xE1A0C000, +0xE3A01001, +0xE1500001, +0x81A000A0, +0x81A01081, +0x8AFFFFFB, +0xE1A0000C, +0xE1A04001, +0xE3A03000, +0xE1A02001, +0xE15200A0, +0x91A02082, +0x3AFFFFFC, +0xE1500002, +0xE0A33003, +0x20400002, +0xE1320001, +0x11A020A2, +0x1AFFFFF9, +0xE0811003, +0xE1B010A1, +0xE1510004, +0x3AFFFFEE, +0xE1A00004, +0xE8BD0010, +0xE12FFF1E, +0xE0010090, +0xE1A01741, +0xE2611000, +0xE3A030A9, +0xE0030391, +0xE1A03743, +0xE2833E39, +0xE0030391, +0xE1A03743, +0xE2833C09, +0xE283301C, +0xE0030391, +0xE1A03743, +0xE2833C0F, +0xE28330B6, +0xE0030391, +0xE1A03743, +0xE2833C16, +0xE28330AA, +0xE0030391, +0xE1A03743, +0xE2833A02, +0xE2833081, +0xE0030391, +0xE1A03743, +0xE2833C36, +0xE2833051, +0xE0030391, +0xE1A03743, +0xE2833CA2, +0xE28330F9, +0xE0000093, +0xE1A00840, +0xE12FFF1E, +0xE3A00001, +0xE3A01001, +0xE92D4010, +0xE3A03000, +0xE3A04001, +0xE3500000, +0x1B000004, +0xE5CC3301, +0xEB000002, +0x0AFFFFFC, +0xE8BD4010, +0xE12FFF1E, +0xE3A0C301, +0xE5CC3208, +0xE15C20B8, +0xE0110002, +0x10222000, +0x114C20B8, +0xE5CC4208, +0xE12FFF1E, +0xE92D500F, +0xE3A00301, +0xE1A0E00F, +0xE510F004, +0xE8BD500F, +0xE25EF004, +0xE59FD044, +0xE92D5000, +0xE14FC000, +0xE10FE000, +0xE92D5000, +0xE3A0C302, +0xE5DCE09C, +0xE35E00A5, +0x1A000004, +0x05DCE0B4, +0x021EE080, +0xE28FE004, +0x159FF018, +0x059FF018, +0xE59FD018, +0xE8BD5000, +0xE169F00C, +0xE8BD5000, +0xE25EF004, +0x03007FF0, +0x09FE2000, +0x09FFC000, +0x03007FE0 + diff --git a/mednafen/gba-09333/sram.cpp b/mednafen/gba-09333/sram.cpp new file mode 100644 index 0000000..20d1adf --- /dev/null +++ b/mednafen/gba-09333/sram.cpp @@ -0,0 +1,37 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "Globals.h" +#include "flash.h" +#include "sram.h" + +namespace MDFN_IEN_GBA +{ + +uint8 sramRead(uint32 address) +{ + return flashSaveMemory[address & 0xFFFF]; +} + +void sramWrite(uint32 address, uint8 byte) +{ + flashSaveMemory[address & 0xFFFF] = byte; +} + +} diff --git a/mednafen/gba-09333/sram.h b/mednafen/gba-09333/sram.h new file mode 100644 index 0000000..b4d9dfc --- /dev/null +++ b/mednafen/gba-09333/sram.h @@ -0,0 +1,31 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef VBA_SRAM_H +#define VBA_SRAM_H + +namespace MDFN_IEN_GBA +{ + +extern uint8 sramRead(uint32 address); +extern void sramWrite(uint32 address, uint8 byte); + +} + +#endif // VBA_SRAM_H diff --git a/mednafen/gba-09333/thumb.cpp b/mednafen/gba-09333/thumb.cpp new file mode 100644 index 0000000..e333e64 --- /dev/null +++ b/mednafen/gba-09333/thumb.cpp @@ -0,0 +1,2115 @@ +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "GBA.h" +#include "GBAinline.h" +#include "Globals.h" + +namespace MDFN_IEN_GBA +{ + +unsigned int RunTHUMB(void) +{ +#define NEG(i) ((i) >> 31) +#define POS(i) ((~(i)) >> 31) +#define ADDCARRY(a, b, c) \ + C_FLAG = ((NEG(a) & NEG(b)) |\ + (NEG(a) & POS(c)) |\ + (NEG(b) & POS(c))) ? true : false; +#define ADDOVERFLOW(a, b, c) \ + V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\ + (POS(a) & POS(b) & NEG(c))) ? true : false; +#define SUBCARRY(a, b, c) \ + C_FLAG = ((NEG(a) & POS(b)) |\ + (NEG(a) & POS(c)) |\ + (POS(b) & POS(c))) ? true : false; +#define SUBOVERFLOW(a, b, c)\ + V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\ + (POS(a) & NEG(b) & NEG(c))) ? true : false; +#define ADD_RD_RS_RN \ + {\ + uint32 lhs = reg[source].I;\ + uint32 rhs = value;\ + uint32 res = lhs + rhs;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + ADDCARRY(lhs, rhs, res);\ + ADDOVERFLOW(lhs, rhs, res);\ + } +#define ADD_RD_RS_O3 \ + {\ + uint32 lhs = reg[source].I;\ + uint32 rhs = value;\ + uint32 res = lhs + rhs;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + ADDCARRY(lhs, rhs, res);\ + ADDOVERFLOW(lhs, rhs, res);\ + } +#define ADD_RN_O8(d) \ + {\ + uint32 lhs = reg[(d)].I;\ + uint32 rhs = (opcode & 255);\ + uint32 res = lhs + rhs;\ + reg[(d)].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + ADDCARRY(lhs, rhs, res);\ + ADDOVERFLOW(lhs, rhs, res);\ + } +#define CMN_RD_RS \ + {\ + uint32 lhs = reg[dest].I;\ + uint32 rhs = value;\ + uint32 res = lhs + rhs;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + ADDCARRY(lhs, rhs, res);\ + ADDOVERFLOW(lhs, rhs, res);\ + } +#define ADC_RD_RS \ + {\ + uint32 lhs = reg[dest].I;\ + uint32 rhs = value;\ + uint32 res = lhs + rhs + (uint32)C_FLAG;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + ADDCARRY(lhs, rhs, res);\ + ADDOVERFLOW(lhs, rhs, res);\ + } +#define SUB_RD_RS_RN \ + {\ + uint32 lhs = reg[source].I;\ + uint32 rhs = value;\ + uint32 res = lhs - rhs;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(lhs, rhs, res);\ + SUBOVERFLOW(lhs, rhs, res);\ + } +#define SUB_RD_RS_O3 \ + {\ + uint32 lhs = reg[source].I;\ + uint32 rhs = value;\ + uint32 res = lhs - rhs;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(lhs, rhs, res);\ + SUBOVERFLOW(lhs, rhs, res);\ + } +#define SUB_RN_O8(d) \ + {\ + uint32 lhs = reg[(d)].I;\ + uint32 rhs = (opcode & 255);\ + uint32 res = lhs - rhs;\ + reg[(d)].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(lhs, rhs, res);\ + SUBOVERFLOW(lhs, rhs, res);\ + } +#define CMP_RN_O8(d) \ + {\ + uint32 lhs = reg[(d)].I;\ + uint32 rhs = (opcode & 255);\ + uint32 res = lhs - rhs;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(lhs, rhs, res);\ + SUBOVERFLOW(lhs, rhs, res);\ + } +#define SBC_RD_RS \ + {\ + uint32 lhs = reg[dest].I;\ + uint32 rhs = value;\ + uint32 res = lhs - rhs - !((uint32)C_FLAG);\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(lhs, rhs, res);\ + SUBOVERFLOW(lhs, rhs, res);\ + } +#define LSL_RD_RM_I5 \ + {\ + C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false;\ + value = reg[source].I << shift;\ + } +#define LSL_RD_RS \ + {\ + C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false;\ + value = reg[dest].I << value;\ + } +#define LSR_RD_RM_I5 \ + {\ + C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false;\ + value = reg[source].I >> shift;\ + } +#define LSR_RD_RS \ + {\ + C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\ + value = reg[dest].I >> value;\ + } +#define ASR_RD_RM_I5 \ + {\ + C_FLAG = ((int32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\ + value = (int32)reg[source].I >> (int)shift;\ + } +#define ASR_RD_RS \ + {\ + C_FLAG = ((int32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\ + value = (int32)reg[dest].I >> (int)value;\ + } +#define ROR_RD_RS \ + {\ + C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false;\ + value = ((reg[dest].I << (32 - value)) |\ + (reg[dest].I >> value));\ + } +#define NEG_RD_RS \ + {\ + uint32 lhs = reg[source].I;\ + uint32 rhs = 0;\ + uint32 res = rhs - lhs;\ + reg[dest].I = res;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(rhs, lhs, res);\ + SUBOVERFLOW(rhs, lhs, res);\ + } +#define CMP_RD_RS \ + {\ + uint32 lhs = reg[dest].I;\ + uint32 rhs = value;\ + uint32 res = lhs - rhs;\ + Z_FLAG = (res == 0) ? true : false;\ + N_FLAG = NEG(res) ? true : false;\ + SUBCARRY(lhs, rhs, res);\ + SUBOVERFLOW(lhs, rhs, res);\ + } + +uint32 opcode = cpuPrefetch[0]; +cpuPrefetch[0] = cpuPrefetch[1]; + +busPrefetch = false; + if (busPrefetchCount<0) + busPrefetchCount=0; + if (busPrefetchCount>16) + busPrefetchCount=8; + +unsigned int clockTicks = codeTicksAccessSeq16(armNextPC)+1; + +armNextPC = reg[15].I; +reg[15].I += 2; +THUMB_PREFETCH_NEXT; + +switch(opcode >> 8) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + { + // LSL Rd, Rm, #Imm 5 + int dest = opcode & 0x07; + int source = (opcode >> 3) & 0x07; + int shift = (opcode >> 6) & 0x1f; + uint32 value; + + if(shift) { + LSL_RD_RM_I5; + } else { + value = reg[source].I; + } + reg[dest].I = value; + // C_FLAG set above + N_FLAG = (value & 0x80000000 ? true : false); + Z_FLAG = (value ? false : true); + } + break; + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + { + // LSR Rd, Rm, #Imm 5 + int dest = opcode & 0x07; + int source = (opcode >> 3) & 0x07; + int shift = (opcode >> 6) & 0x1f; + uint32 value; + + if(shift) { + LSR_RD_RM_I5; + } else { + C_FLAG = reg[source].I & 0x80000000 ? true : false; + value = 0; + } + reg[dest].I = value; + // C_FLAG set above + N_FLAG = (value & 0x80000000 ? true : false); + Z_FLAG = (value ? false : true); + } + break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + { + // ASR Rd, Rm, #Imm 5 + int dest = opcode & 0x07; + int source = (opcode >> 3) & 0x07; + int shift = (opcode >> 6) & 0x1f; + uint32 value; + + if(shift) { + ASR_RD_RM_I5; + } else { + if(reg[source].I & 0x80000000) { + value = 0xFFFFFFFF; + C_FLAG = true; + } else { + value = 0; + C_FLAG = false; + } + } + reg[dest].I = value; + // C_FLAG set above + N_FLAG = (value & 0x80000000 ? true : false); + Z_FLAG = (value ? false :true); + } + break; + case 0x18: + case 0x19: + { + // ADD Rd, Rs, Rn + int dest = opcode & 0x07; + int source = (opcode >> 3) & 0x07; + uint32 value = reg[(opcode>>6)& 0x07].I; + ADD_RD_RS_RN; + } + break; + case 0x1a: + case 0x1b: + { + // SUB Rd, Rs, Rn + int dest = opcode & 0x07; + int source = (opcode >> 3) & 0x07; + uint32 value = reg[(opcode>>6)& 0x07].I; + SUB_RD_RS_RN; + } + break; + case 0x1c: + case 0x1d: + { + // ADD Rd, Rs, #Offset3 + int dest = opcode & 0x07; + int source = (opcode >> 3) & 0x07; + uint32 value = (opcode >> 6) & 7; + ADD_RD_RS_O3; + } + break; + case 0x1e: + case 0x1f: + { + // SUB Rd, Rs, #Offset3 + int dest = opcode & 0x07; + int source = (opcode >> 3) & 0x07; + uint32 value = (opcode >> 6) & 7; + SUB_RD_RS_O3; + } + break; + case 0x20: + // MOV R0, #Offset8 + reg[0].I = opcode & 255; + N_FLAG = false; + Z_FLAG = (reg[0].I ? false : true); + break; + case 0x21: + // MOV R1, #Offset8 + reg[1].I = opcode & 255; + N_FLAG = false; + Z_FLAG = (reg[1].I ? false : true); + break; + case 0x22: + // MOV R2, #Offset8 + reg[2].I = opcode & 255; + N_FLAG = false; + Z_FLAG = (reg[2].I ? false : true); + break; + case 0x23: + // MOV R3, #Offset8 + reg[3].I = opcode & 255; + N_FLAG = false; + Z_FLAG = (reg[3].I ? false : true); + break; + case 0x24: + // MOV R4, #Offset8 + reg[4].I = opcode & 255; + N_FLAG = false; + Z_FLAG = (reg[4].I ? false : true); + break; + case 0x25: + // MOV R5, #Offset8 + reg[5].I = opcode & 255; + N_FLAG = false; + Z_FLAG = (reg[5].I ? false : true); + break; + case 0x26: + // MOV R6, #Offset8 + reg[6].I = opcode & 255; + N_FLAG = false; + Z_FLAG = (reg[6].I ? false : true); + break; + case 0x27: + // MOV R7, #Offset8 + reg[7].I = opcode & 255; + N_FLAG = false; + Z_FLAG = (reg[7].I ? false : true); + break; + case 0x28: + // CMP R0, #Offset8 + CMP_RN_O8(0); + break; + case 0x29: + // CMP R1, #Offset8 + CMP_RN_O8(1); + break; + case 0x2a: + // CMP R2, #Offset8 + CMP_RN_O8(2); + break; + case 0x2b: + // CMP R3, #Offset8 + CMP_RN_O8(3); + break; + case 0x2c: + // CMP R4, #Offset8 + CMP_RN_O8(4); + break; + case 0x2d: + // CMP R5, #Offset8 + CMP_RN_O8(5); + break; + case 0x2e: + // CMP R6, #Offset8 + CMP_RN_O8(6); + break; + case 0x2f: + // CMP R7, #Offset8 + CMP_RN_O8(7); + break; + case 0x30: + // ADD R0,#Offset8 + ADD_RN_O8(0); + break; + case 0x31: + // ADD R1,#Offset8 + ADD_RN_O8(1); + break; + case 0x32: + // ADD R2,#Offset8 + ADD_RN_O8(2); + break; + case 0x33: + // ADD R3,#Offset8 + ADD_RN_O8(3); + break; + case 0x34: + // ADD R4,#Offset8 + ADD_RN_O8(4); + break; + case 0x35: + // ADD R5,#Offset8 + ADD_RN_O8(5); + break; + case 0x36: + // ADD R6,#Offset8 + ADD_RN_O8(6); + break; + case 0x37: + // ADD R7,#Offset8 + ADD_RN_O8(7); + break; + case 0x38: + // SUB R0,#Offset8 + SUB_RN_O8(0); + break; + case 0x39: + // SUB R1,#Offset8 + SUB_RN_O8(1); + break; + case 0x3a: + // SUB R2,#Offset8 + SUB_RN_O8(2); + break; + case 0x3b: + // SUB R3,#Offset8 + SUB_RN_O8(3); + break; + case 0x3c: + // SUB R4,#Offset8 + SUB_RN_O8(4); + break; + case 0x3d: + // SUB R5,#Offset8 + SUB_RN_O8(5); + break; + case 0x3e: + // SUB R6,#Offset8 + SUB_RN_O8(6); + break; + case 0x3f: + // SUB R7,#Offset8 + SUB_RN_O8(7); + break; + case 0x40: + switch((opcode >> 6) & 3) { + case 0x00: + { + // AND Rd, Rs + int dest = opcode & 7; + reg[dest].I &= reg[(opcode >> 3)&7].I; + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + Z_FLAG = reg[dest].I ? false : true; +#ifdef BKPT_SUPPORT +#define THUMB_CONSOLE_OUTPUT(a,b) \ + if((opcode == 0x4000) && (reg[0].I == 0xC0DED00D)) {\ + extern void (*dbgOutput)(char *, uint32);\ + dbgOutput((a), (b));\ + } +#else +#define THUMB_CONSOLE_OUTPUT(a,b) +#endif + THUMB_CONSOLE_OUTPUT(NULL, reg[2].I); + } + break; + case 0x01: + // EOR Rd, Rs + { + int dest = opcode & 7; + reg[dest].I ^= reg[(opcode >> 3)&7].I; + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + Z_FLAG = reg[dest].I ? false : true; + } + break; + case 0x02: + // LSL Rd, Rs + { + int dest = opcode & 7; + uint32 value = reg[(opcode >> 3)&7].B.B0; + if(value) { + if(value == 32) { + value = 0; + C_FLAG = (reg[dest].I & 1 ? true : false); + } else if(value < 32) { + LSL_RD_RS; + } else { + value = 0; + C_FLAG = false; + } + reg[dest].I = value; + } + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + Z_FLAG = reg[dest].I ? false : true; + clockTicks = codeTicksAccesint16(armNextPC)+2; + } + break; + case 0x03: + { + // LSR Rd, Rs + int dest = opcode & 7; + uint32 value = reg[(opcode >> 3)&7].B.B0; + if(value) { + if(value == 32) { + value = 0; + C_FLAG = (reg[dest].I & 0x80000000 ? true : false); + } else if(value < 32) { + LSR_RD_RS; + } else { + value = 0; + C_FLAG = false; + } + reg[dest].I = value; + } + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + Z_FLAG = reg[dest].I ? false : true; + clockTicks = codeTicksAccesint16(armNextPC)+2; + } + break; + } + break; + case 0x41: + switch((opcode >> 6) & 3) { + case 0x00: + { + // ASR Rd, Rs + int dest = opcode & 7; + uint32 value = reg[(opcode >> 3)&7].B.B0; + // ASR + if(value) { + if(value < 32) { + ASR_RD_RS; + reg[dest].I = value; + } else { + if(reg[dest].I & 0x80000000){ + reg[dest].I = 0xFFFFFFFF; + C_FLAG = true; + } else { + reg[dest].I = 0x00000000; + C_FLAG = false; + } + } + } + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + Z_FLAG = reg[dest].I ? false : true; + clockTicks = codeTicksAccesint16(armNextPC)+2; + } + break; + case 0x01: + { + // ADC Rd, Rs + int dest = opcode & 0x07; + uint32 value = reg[(opcode >> 3)&7].I; + // ADC + ADC_RD_RS; + } + break; + case 0x02: + { + // SBC Rd, Rs + int dest = opcode & 0x07; + uint32 value = reg[(opcode >> 3)&7].I; + + // SBC + SBC_RD_RS; + } + break; + case 0x03: + // ROR Rd, Rs + { + int dest = opcode & 7; + uint32 value = reg[(opcode >> 3)&7].B.B0; + + if(value) { + value = value & 0x1f; + if(value == 0) { + C_FLAG = (reg[dest].I & 0x80000000 ? true : false); + } else { + ROR_RD_RS; + reg[dest].I = value; + } + } + clockTicks = codeTicksAccesint16(armNextPC)+2; + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + Z_FLAG = reg[dest].I ? false : true; + } + break; + } + break; + case 0x42: + switch((opcode >> 6) & 3) { + case 0x00: + { + // TST Rd, Rs + uint32 value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I; + N_FLAG = value & 0x80000000 ? true : false; + Z_FLAG = value ? false : true; + } + break; + case 0x01: + { + // NEG Rd, Rs + int dest = opcode & 7; + int source = (opcode >> 3) & 7; + NEG_RD_RS; + } + break; + case 0x02: + { + // CMP Rd, Rs + int dest = opcode & 7; + uint32 value = reg[(opcode >> 3)&7].I; + CMP_RD_RS; + } + break; + case 0x03: + { + // CMN Rd, Rs + int dest = opcode & 7; + uint32 value = reg[(opcode >> 3)&7].I; + // CMN + CMN_RD_RS; + } + break; + } + break; + case 0x43: + switch((opcode >> 6) & 3) { + case 0x00: + { + // ORR Rd, Rs + int dest = opcode & 7; + reg[dest].I |= reg[(opcode >> 3) & 7].I; + Z_FLAG = reg[dest].I ? false : true; + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + } + break; + case 0x01: + { + // MUL Rd, Rs + clockTicks = codeTicksAccesint16(armNextPC)+2; + int dest = opcode & 7; + uint32 rm = reg[dest].I; + reg[dest].I = reg[(opcode >> 3) & 7].I * rm; + if (((int32)rm) < 0) + rm = ~rm; + if ((rm & 0xFFFFFF00) == 0) + clockTicks += 0; + else if ((rm & 0xFFFF0000) == 0) + clockTicks += 1; + else if ((rm & 0xFF000000) == 0) + clockTicks += 2; + else + clockTicks += 3; + busPrefetchCount += clockTicks - codeTicksAccesint16(armNextPC) -1; + Z_FLAG = reg[dest].I ? false : true; + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + } + break; + case 0x02: + { + // BIC Rd, Rs + int dest = opcode & 7; + reg[dest].I &= (~reg[(opcode >> 3) & 7].I); + Z_FLAG = reg[dest].I ? false : true; + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + } + break; + case 0x03: + { + // MVN Rd, Rs + int dest = opcode & 7; + reg[dest].I = ~reg[(opcode >> 3) & 7].I; + Z_FLAG = reg[dest].I ? false : true; + N_FLAG = reg[dest].I & 0x80000000 ? true : false; + } + break; + } + break; + case 0x44: + { + int dest = opcode & 7; + int base = (opcode >> 3) & 7; + switch((opcode >> 6)& 3) { + default: + goto unknown_thumb; + case 1: + // ADD Rd, Hs + reg[dest].I += reg[base+8].I; + break; + case 2: + // ADD Hd, Rs + reg[dest+8].I += reg[base].I; + if(dest == 7) { + reg[15].I &= 0xFFFFFFFE; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + clockTicks += clockTicks+codeTicksAccesint16(armNextPC)+1; + } + break; + case 3: + // ADD Hd, Hs + reg[dest+8].I += reg[base+8].I; + if(dest == 7) { + reg[15].I &= 0xFFFFFFFE; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + clockTicks += clockTicks+codeTicksAccesint16(armNextPC)+1; + } + break; + } + } + break; + case 0x45: + { + int dest = opcode & 7; + int base = (opcode >> 3) & 7; + uint32 value; + switch((opcode >> 6) & 3) { + case 0: + // CMP Rd, Hs + value = reg[base].I; + CMP_RD_RS; + break; + case 1: + // CMP Rd, Hs + value = reg[base+8].I; + CMP_RD_RS; + break; + case 2: + // CMP Hd, Rs + value = reg[base].I; + dest += 8; + CMP_RD_RS; + break; + case 3: + // CMP Hd, Hs + value = reg[base+8].I; + dest += 8; + CMP_RD_RS; + break; + } + } + break; + case 0x46: + { + int dest = opcode & 7; + int base = (opcode >> 3) & 7; + switch((opcode >> 6) & 3) { + case 0: + // this form should not be used... + // MOV Rd, Rs + reg[dest].I = reg[base].I; + break; + case 1: + // MOV Rd, Hs + reg[dest].I = reg[base+8].I; + break; + case 2: + // MOV Hd, Rs + reg[dest+8].I = reg[base].I; + if(dest == 7) { + reg[15].I &= 0xFFFFFFFE; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + clockTicks += clockTicks+codeTicksAccesint16(armNextPC)+1; + } + break; + case 3: + // MOV Hd, Hs + reg[dest+8].I = reg[base+8].I; + if(dest == 7) { + reg[15].I &= 0xFFFFFFFE; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + clockTicks += clockTicks+codeTicksAccesint16(armNextPC)+1; + } + break; + } + } + break; + case 0x47: + { + int base = (opcode >> 3) & 7; + switch((opcode >>6) & 3) { + case 0: + // BX Rs + reg[15].I = (reg[base].I) & 0xFFFFFFFE; + if(reg[base].I & 1) { + armState = false; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + } else { + armState = true; + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + } + busPrefetchCount=0; + clockTicks += clockTicks+codeTicksAccesint16(armNextPC)+1; + break; + case 1: + // BX Hs + reg[15].I = (reg[8+base].I) & 0xFFFFFFFE; + if(reg[8+base].I & 1) { + armState = false; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + } else { + armState = true; + reg[15].I &= 0xFFFFFFFC; + armNextPC = reg[15].I; + reg[15].I += 4; + ARM_PREFETCH; + } + busPrefetchCount=0; + clockTicks += clockTicks+codeTicksAccesint16(armNextPC)+1; + break; + default: + goto unknown_thumb; + } + } + break; + case 0x48: + // LDR R0,[PC, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); + reg[0].I = CPUReadMemoryQuick(address); + busPrefetchCount=0; + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x49: + // LDR R1,[PC, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); + reg[1].I = CPUReadMemoryQuick(address); + busPrefetchCount=0; + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x4a: + // LDR R2,[PC, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); + reg[2].I = CPUReadMemoryQuick(address); + busPrefetchCount=0; + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x4b: + // LDR R3,[PC, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); + reg[3].I = CPUReadMemoryQuick(address); + busPrefetchCount=0; + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x4c: + // LDR R4,[PC, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); + reg[4].I = CPUReadMemoryQuick(address); + busPrefetchCount=0; + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x4d: + // LDR R5,[PC, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); + reg[5].I = CPUReadMemoryQuick(address); + busPrefetchCount=0; + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x4e: + // LDR R6,[PC, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); + reg[6].I = CPUReadMemoryQuick(address); + busPrefetchCount=0; + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x4f: + // LDR R7,[PC, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); + reg[7].I = CPUReadMemoryQuick(address); + busPrefetchCount=0; + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x50: + case 0x51: + // STR Rd, [Rs, Rn] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; + CPUWriteMemory(address, + reg[opcode & 7].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address) +2; + } + break; + case 0x52: + case 0x53: + // STRH Rd, [Rs, Rn] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; + CPUWriteHalfWord(address, + reg[opcode&7].W.W0); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint16(address) +2; + } + break; + case 0x54: + case 0x55: + // STRB Rd, [Rs, Rn] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + reg[(opcode >>6)&7].I; + CPUWriteByte(address, + reg[opcode & 7].B.B0); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint16(address) +2; + } + break; + case 0x56: + case 0x57: + // LDSB Rd, [Rs, Rn] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; + reg[opcode&7].I = (int8)CPUReadByte(address); + clockTicks = 3 + dataTicksAccesint16(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x58: + case 0x59: + // LDR Rd, [Rs, Rn] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; + reg[opcode&7].I = CPUReadMemory(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x5a: + case 0x5b: + // LDRH Rd, [Rs, Rn] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; + reg[opcode&7].I = CPUReadHalfWord(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x5c: + case 0x5d: + // LDRB Rd, [Rs, Rn] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; + reg[opcode&7].I = CPUReadByte(address); + clockTicks = 3 + dataTicksAccesint16(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x5e: + case 0x5f: + // LDSH Rd, [Rs, Rn] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; + reg[opcode&7].I = (int16)CPUReadHalfWordSigned(address); + clockTicks = 3 + dataTicksAccesint16(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + // STR Rd, [Rs, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2); + CPUWriteMemory(address, + reg[opcode&7].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address)+2; + } + break; + case 0x68: + case 0x69: + case 0x6a: + case 0x6b: + case 0x6c: + case 0x6d: + case 0x6e: + case 0x6f: + // LDR Rd, [Rs, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2); + reg[opcode&7].I = CPUReadMemory(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + // STRB Rd, [Rs, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)); + CPUWriteByte(address, + reg[opcode&7].B.B0); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint16(address)+2; + } + break; + case 0x78: + case 0x79: + case 0x7a: + case 0x7b: + case 0x7c: + case 0x7d: + case 0x7e: + case 0x7f: + // LDRB Rd, [Rs, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)); + reg[opcode&7].I = CPUReadByte(address); + clockTicks = 3 + dataTicksAccesint16(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + // STRH Rd, [Rs, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1); + CPUWriteHalfWord(address, + reg[opcode&7].W.W0); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint16(address)+2; + } + break; + case 0x88: + case 0x89: + case 0x8a: + case 0x8b: + case 0x8c: + case 0x8d: + case 0x8e: + case 0x8f: + // LDRH Rd, [Rs, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1); + reg[opcode&7].I = CPUReadHalfWord(address); + clockTicks = 3 + dataTicksAccesint16(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x90: + // STR R0, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + CPUWriteMemory(address, reg[0].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address)+2; + } + break; + case 0x91: + // STR R1, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + CPUWriteMemory(address, reg[1].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address)+2; + } + break; + case 0x92: + // STR R2, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + CPUWriteMemory(address, reg[2].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address)+2; + } + break; + case 0x93: + // STR R3, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + CPUWriteMemory(address, reg[3].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address)+2; + } + break; + case 0x94: + // STR R4, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + CPUWriteMemory(address, reg[4].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address)+2; + } + break; + case 0x95: + // STR R5, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + CPUWriteMemory(address, reg[5].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address)+2; + } + break; + case 0x96: + // STR R6, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + CPUWriteMemory(address, reg[6].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address)+2; + } + break; + case 0x97: + // STR R7, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + CPUWriteMemory(address, reg[7].I); + clockTicks = codeTicksAccesint16(armNextPC) + + dataTicksAccesint32(address)+2; + } + break; + case 0x98: + // LDR R0, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + reg[0].I = CPUReadMemoryQuick(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x99: + // LDR R1, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + reg[1].I = CPUReadMemoryQuick(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x9a: + // LDR R2, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + reg[2].I = CPUReadMemoryQuick(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x9b: + // LDR R3, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + reg[3].I = CPUReadMemoryQuick(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x9c: + // LDR R4, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + reg[4].I = CPUReadMemoryQuick(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x9d: + // LDR R5, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + reg[5].I = CPUReadMemoryQuick(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x9e: + // LDR R6, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + reg[6].I = CPUReadMemoryQuick(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0x9f: + // LDR R7, [SP, #Imm] + { + busPrefetch = busPrefetchEnable; + uint32 address = reg[13].I + ((opcode&255)<<2); + reg[7].I = CPUReadMemoryQuick(address); + clockTicks = 3 + dataTicksAccesint32(address) + + codeTicksAccesint16(armNextPC); + } + break; + case 0xa0: + // ADD R0, PC, Imm + reg[0].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + break; + case 0xa1: + // ADD R1, PC, Imm + reg[1].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + break; + case 0xa2: + // ADD R2, PC, Imm + reg[2].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + break; + case 0xa3: + // ADD R3, PC, Imm + reg[3].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + break; + case 0xa4: + // ADD R4, PC, Imm + reg[4].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + break; + case 0xa5: + // ADD R5, PC, Imm + reg[5].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + break; + case 0xa6: + // ADD R6, PC, Imm + reg[6].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + break; + case 0xa7: + // ADD R7, PC, Imm + reg[7].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); + break; + case 0xa8: + // ADD R0, SP, Imm + reg[0].I = reg[13].I + ((opcode&255)<<2); + break; + case 0xa9: + // ADD R1, SP, Imm + reg[1].I = reg[13].I + ((opcode&255)<<2); + break; + case 0xaa: + // ADD R2, SP, Imm + reg[2].I = reg[13].I + ((opcode&255)<<2); + break; + case 0xab: + // ADD R3, SP, Imm + reg[3].I = reg[13].I + ((opcode&255)<<2); + break; + case 0xac: + // ADD R4, SP, Imm + reg[4].I = reg[13].I + ((opcode&255)<<2); + break; + case 0xad: + // ADD R5, SP, Imm + reg[5].I = reg[13].I + ((opcode&255)<<2); + break; + case 0xae: + // ADD R6, SP, Imm + reg[6].I = reg[13].I + ((opcode&255)<<2); + break; + case 0xaf: + // ADD R7, SP, Imm + reg[7].I = reg[13].I + ((opcode&255)<<2); + break; + case 0xb0: + { + // ADD SP, Imm + int offset = (opcode & 127) << 2; + if(opcode & 0x80) + offset = -offset; + reg[13].I += offset; + } + break; +#define PUSH_REG(val, r) \ + if(opcode & (val)) {\ + CPUWriteMemory(address, reg[(r)].I);\ + if(offset)\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ + else\ + clockTicks += 1 + dataTicksAccesint32(address);\ + offset = 1;\ + address += 4;\ + } + case 0xb4: + // PUSH {Rlist} + { + busPrefetch = busPrefetchEnable; + int offset = 0; + uint32 temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff]; + uint32 address = temp & 0xFFFFFFFC; + clockTicks = codeTicksAccesint16(armNextPC)+1; + PUSH_REG(1, 0); + PUSH_REG(2, 1); + PUSH_REG(4, 2); + PUSH_REG(8, 3); + PUSH_REG(16, 4); + PUSH_REG(32, 5); + PUSH_REG(64, 6); + PUSH_REG(128, 7); + reg[13].I = temp; + } + break; + case 0xb5: + // PUSH {Rlist, LR} + { + busPrefetch = busPrefetchEnable; + int offset = 0; + uint32 temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff]; + uint32 address = temp & 0xFFFFFFFC; + clockTicks = codeTicksAccesint16(armNextPC)+1; + PUSH_REG(1, 0); + PUSH_REG(2, 1); + PUSH_REG(4, 2); + PUSH_REG(8, 3); + PUSH_REG(16, 4); + PUSH_REG(32, 5); + PUSH_REG(64, 6); + PUSH_REG(128, 7); + PUSH_REG(256, 14); + reg[13].I = temp; + } + break; +#define POP_REG(val, r) \ + if(opcode & (val)) {\ + reg[(r)].I = CPUReadMemory(address);\ + if(offset)\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ + else\ + clockTicks += 1 + dataTicksAccesint32(address);\ + offset = 1;\ + address += 4;\ + } + case 0xbc: + // POP {Rlist} + { + busPrefetch = busPrefetchEnable; + int offset = 0; + uint32 address = reg[13].I & 0xFFFFFFFC; + uint32 temp = reg[13].I + 4*cpuBitsSet[opcode & 0xFF]; + clockTicks = 0; + POP_REG(1, 0); + POP_REG(2, 1); + POP_REG(4, 2); + POP_REG(8, 3); + POP_REG(16, 4); + POP_REG(32, 5); + POP_REG(64, 6); + POP_REG(128, 7); + reg[13].I = temp; + clockTicks += codeTicksAccesint16(armNextPC)+2; + } + break; + case 0xbd: + // POP {Rlist, PC} + { + busPrefetch = busPrefetchEnable; + int offset = 0; + uint32 address = reg[13].I & 0xFFFFFFFC; + uint32 temp = reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF]; + clockTicks = 0; + POP_REG(1, 0); + POP_REG(2, 1); + POP_REG(4, 2); + POP_REG(8, 3); + POP_REG(16, 4); + POP_REG(32, 5); + POP_REG(64, 6); + POP_REG(128, 7); + reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE); + if(offset) + clockTicks += 1 + dataTicksAccessSeq32(address); + else + clockTicks += 1 + dataTicksAccesint32(address); + armNextPC = reg[15].I; + reg[15].I += 2; + reg[13].I = temp; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks += 2*(codeTicksAccesint16(armNextPC))+3; + } + break; +#define THUMB_STM_REG(val,r,b) \ + if(opcode & (val)) {\ + CPUWriteMemory(address, reg[(r)].I);\ + if(!offset) {\ + reg[(b)].I = temp;\ + clockTicks += 1 + dataTicksAccesint32(address);\ + } else \ + clockTicks += 1 + dataTicksAccessSeq32(address);\ + offset = 1;\ + address += 4;\ + } + case 0xc0: + { + // STM R0!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[0].I & 0xFFFFFFFC; + uint32 temp = reg[0].I + 4*cpuBitsSet[opcode & 0xff]; + int offset = 0; + clockTicks = codeTicksAccesint16(armNextPC)+1; + // store + THUMB_STM_REG(1, 0, 0); + THUMB_STM_REG(2, 1, 0); + THUMB_STM_REG(4, 2, 0); + THUMB_STM_REG(8, 3, 0); + THUMB_STM_REG(16, 4, 0); + THUMB_STM_REG(32, 5, 0); + THUMB_STM_REG(64, 6, 0); + THUMB_STM_REG(128, 7, 0); + } + break; + case 0xc1: + { + // STM R1!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[1].I & 0xFFFFFFFC; + uint32 temp = reg[1].I + 4*cpuBitsSet[opcode & 0xff]; + int offset = 0; + clockTicks = codeTicksAccesint16(armNextPC)+1; + // store + THUMB_STM_REG(1, 0, 1); + THUMB_STM_REG(2, 1, 1); + THUMB_STM_REG(4, 2, 1); + THUMB_STM_REG(8, 3, 1); + THUMB_STM_REG(16, 4, 1); + THUMB_STM_REG(32, 5, 1); + THUMB_STM_REG(64, 6, 1); + THUMB_STM_REG(128, 7, 1); + } + break; + case 0xc2: + { + // STM R2!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[2].I & 0xFFFFFFFC; + uint32 temp = reg[2].I + 4*cpuBitsSet[opcode & 0xff]; + int offset = 0; + clockTicks = codeTicksAccesint16(armNextPC)+1; + // store + THUMB_STM_REG(1, 0, 2); + THUMB_STM_REG(2, 1, 2); + THUMB_STM_REG(4, 2, 2); + THUMB_STM_REG(8, 3, 2); + THUMB_STM_REG(16, 4, 2); + THUMB_STM_REG(32, 5, 2); + THUMB_STM_REG(64, 6, 2); + THUMB_STM_REG(128, 7, 2); + } + break; + case 0xc3: + { + // STM R3!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[3].I & 0xFFFFFFFC; + uint32 temp = reg[3].I + 4*cpuBitsSet[opcode & 0xff]; + int offset = 0; + clockTicks = codeTicksAccesint16(armNextPC)+1; + // store + THUMB_STM_REG(1, 0, 3); + THUMB_STM_REG(2, 1, 3); + THUMB_STM_REG(4, 2, 3); + THUMB_STM_REG(8, 3, 3); + THUMB_STM_REG(16, 4, 3); + THUMB_STM_REG(32, 5, 3); + THUMB_STM_REG(64, 6, 3); + THUMB_STM_REG(128, 7, 3); + } + break; + case 0xc4: + { + // STM R4!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[4].I & 0xFFFFFFFC; + uint32 temp = reg[4].I + 4*cpuBitsSet[opcode & 0xff]; + int offset = 0; + clockTicks = codeTicksAccesint16(armNextPC)+1; + // store + THUMB_STM_REG(1, 0, 4); + THUMB_STM_REG(2, 1, 4); + THUMB_STM_REG(4, 2, 4); + THUMB_STM_REG(8, 3, 4); + THUMB_STM_REG(16, 4, 4); + THUMB_STM_REG(32, 5, 4); + THUMB_STM_REG(64, 6, 4); + THUMB_STM_REG(128, 7, 4); + } + break; + case 0xc5: + { + // STM R5!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[5].I & 0xFFFFFFFC; + uint32 temp = reg[5].I + 4*cpuBitsSet[opcode & 0xff]; + int offset = 0; + clockTicks = codeTicksAccesint16(armNextPC)+1; + // store + THUMB_STM_REG(1, 0, 5); + THUMB_STM_REG(2, 1, 5); + THUMB_STM_REG(4, 2, 5); + THUMB_STM_REG(8, 3, 5); + THUMB_STM_REG(16, 4, 5); + THUMB_STM_REG(32, 5, 5); + THUMB_STM_REG(64, 6, 5); + THUMB_STM_REG(128, 7, 5); + } + break; + case 0xc6: + { + // STM R6!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[6].I & 0xFFFFFFFC; + uint32 temp = reg[6].I + 4*cpuBitsSet[opcode & 0xff]; + int offset = 0; + clockTicks = codeTicksAccesint16(armNextPC)+1; + // store + THUMB_STM_REG(1, 0, 6); + THUMB_STM_REG(2, 1, 6); + THUMB_STM_REG(4, 2, 6); + THUMB_STM_REG(8, 3, 6); + THUMB_STM_REG(16, 4, 6); + THUMB_STM_REG(32, 5, 6); + THUMB_STM_REG(64, 6, 6); + THUMB_STM_REG(128, 7, 6); + } + break; + case 0xc7: + { + // STM R7!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[7].I & 0xFFFFFFFC; + uint32 temp = reg[7].I + 4*cpuBitsSet[opcode & 0xff]; + int offset = 0; + clockTicks = codeTicksAccesint16(armNextPC)+1; + // store + THUMB_STM_REG(1, 0, 7); + THUMB_STM_REG(2, 1, 7); + THUMB_STM_REG(4, 2, 7); + THUMB_STM_REG(8, 3, 7); + THUMB_STM_REG(16, 4, 7); + THUMB_STM_REG(32, 5, 7); + THUMB_STM_REG(64, 6, 7); + THUMB_STM_REG(128, 7, 7); + } + break; +#define THUMB_LDM_REG(val,r) \ + if(opcode & (val)) {\ + reg[(r)].I = CPUReadMemory(address);\ + if(offset)\ + clockTicks += 1 + dataTicksAccessSeq32(address);\ + else \ + clockTicks += 1 + dataTicksAccesint32(address);\ + offset = 1;\ + address += 4;\ + } + case 0xc8: + { + // LDM R0!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[0].I & 0xFFFFFFFC; + uint32 temp = reg[0].I + 4*cpuBitsSet[opcode & 0xFF]; + int offset = 0; + clockTicks = 0; + // load + THUMB_LDM_REG(1, 0); + THUMB_LDM_REG(2, 1); + THUMB_LDM_REG(4, 2); + THUMB_LDM_REG(8, 3); + THUMB_LDM_REG(16, 4); + THUMB_LDM_REG(32, 5); + THUMB_LDM_REG(64, 6); + THUMB_LDM_REG(128, 7); + clockTicks += codeTicksAccesint16(armNextPC)+2; + if(!(opcode & 1)) + reg[0].I = temp; + } + break; + case 0xc9: + { + // LDM R1!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[1].I & 0xFFFFFFFC; + uint32 temp = reg[1].I + 4*cpuBitsSet[opcode & 0xFF]; + int offset = 0; + clockTicks = 0; + // load + THUMB_LDM_REG(1, 0); + THUMB_LDM_REG(2, 1); + THUMB_LDM_REG(4, 2); + THUMB_LDM_REG(8, 3); + THUMB_LDM_REG(16, 4); + THUMB_LDM_REG(32, 5); + THUMB_LDM_REG(64, 6); + THUMB_LDM_REG(128, 7); + clockTicks += codeTicksAccesint16(armNextPC)+2; + if(!(opcode & 2)) + reg[1].I = temp; + } + break; + case 0xca: + { + // LDM R2!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[2].I & 0xFFFFFFFC; + uint32 temp = reg[2].I + 4*cpuBitsSet[opcode & 0xFF]; + int offset = 0; + clockTicks = 0; + // load + THUMB_LDM_REG(1, 0); + THUMB_LDM_REG(2, 1); + THUMB_LDM_REG(4, 2); + THUMB_LDM_REG(8, 3); + THUMB_LDM_REG(16, 4); + THUMB_LDM_REG(32, 5); + THUMB_LDM_REG(64, 6); + THUMB_LDM_REG(128, 7); + clockTicks += codeTicksAccesint16(armNextPC)+2; + if(!(opcode & 4)) + reg[2].I = temp; + } + break; + case 0xcb: + { + // LDM R3!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[3].I & 0xFFFFFFFC; + uint32 temp = reg[3].I + 4*cpuBitsSet[opcode & 0xFF]; + int offset = 0; + clockTicks = 0; + // load + THUMB_LDM_REG(1, 0); + THUMB_LDM_REG(2, 1); + THUMB_LDM_REG(4, 2); + THUMB_LDM_REG(8, 3); + THUMB_LDM_REG(16, 4); + THUMB_LDM_REG(32, 5); + THUMB_LDM_REG(64, 6); + THUMB_LDM_REG(128, 7); + clockTicks += codeTicksAccesint16(armNextPC)+2; + if(!(opcode & 8)) + reg[3].I = temp; + } + break; + case 0xcc: + { + // LDM R4!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[4].I & 0xFFFFFFFC; + uint32 temp = reg[4].I + 4*cpuBitsSet[opcode & 0xFF]; + int offset = 0; + clockTicks = 0; + // load + THUMB_LDM_REG(1, 0); + THUMB_LDM_REG(2, 1); + THUMB_LDM_REG(4, 2); + THUMB_LDM_REG(8, 3); + THUMB_LDM_REG(16, 4); + THUMB_LDM_REG(32, 5); + THUMB_LDM_REG(64, 6); + THUMB_LDM_REG(128, 7); + clockTicks += codeTicksAccesint16(armNextPC)+2; + if(!(opcode & 16)) + reg[4].I = temp; + } + break; + case 0xcd: + { + // LDM R5!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[5].I & 0xFFFFFFFC; + uint32 temp = reg[5].I + 4*cpuBitsSet[opcode & 0xFF]; + int offset = 0; + clockTicks = 0; + // load + THUMB_LDM_REG(1, 0); + THUMB_LDM_REG(2, 1); + THUMB_LDM_REG(4, 2); + THUMB_LDM_REG(8, 3); + THUMB_LDM_REG(16, 4); + THUMB_LDM_REG(32, 5); + THUMB_LDM_REG(64, 6); + THUMB_LDM_REG(128, 7); + clockTicks += codeTicksAccesint16(armNextPC)+2; + if(!(opcode & 32)) + reg[5].I = temp; + } + break; + case 0xce: + { + // LDM R6!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[6].I & 0xFFFFFFFC; + uint32 temp = reg[6].I + 4*cpuBitsSet[opcode & 0xFF]; + int offset = 0; + clockTicks = 0; + // load + THUMB_LDM_REG(1, 0); + THUMB_LDM_REG(2, 1); + THUMB_LDM_REG(4, 2); + THUMB_LDM_REG(8, 3); + THUMB_LDM_REG(16, 4); + THUMB_LDM_REG(32, 5); + THUMB_LDM_REG(64, 6); + THUMB_LDM_REG(128, 7); + clockTicks += codeTicksAccesint16(armNextPC)+2; + if(!(opcode & 64)) + reg[6].I = temp; + } + break; + case 0xcf: + { + // LDM R7!, {Rlist} + busPrefetch = busPrefetchEnable; + uint32 address = reg[7].I & 0xFFFFFFFC; + uint32 temp = reg[7].I + 4*cpuBitsSet[opcode & 0xFF]; + int offset = 0; + clockTicks = 0; + // load + THUMB_LDM_REG(1, 0); + THUMB_LDM_REG(2, 1); + THUMB_LDM_REG(4, 2); + THUMB_LDM_REG(8, 3); + THUMB_LDM_REG(16, 4); + THUMB_LDM_REG(32, 5); + THUMB_LDM_REG(64, 6); + THUMB_LDM_REG(128, 7); + clockTicks += codeTicksAccesint16(armNextPC)+2; + if(!(opcode & 128)) + reg[7].I = temp; + } + break; + case 0xd0: + // BEQ offset + if(Z_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xd1: + // BNE offset + if(!Z_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xd2: + // BCS offset + if(C_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xd3: + // BCC offset + if(!C_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xd4: + // BMI offset + if(N_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xd5: + // BPL offset + if(!N_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xd6: + // BVS offset + if(V_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xd7: + // BVC offset + if(!V_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xd8: + // BHI offset + if(C_FLAG && !Z_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xd9: + // BLS offset + if(!C_FLAG || Z_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xda: + // BGE offset + if(N_FLAG == V_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xdb: + // BLT offset + if(N_FLAG != V_FLAG) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xdc: + // BGT offset + if(!Z_FLAG && (N_FLAG == V_FLAG)) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xdd: + // BLE offset + if(Z_FLAG || (N_FLAG != V_FLAG)) { + reg[15].I += ((int8)(opcode & 0xFF)) << 1; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; + case 0xdf: + { + // SWI #comment + uint32 address = 0; + busPrefetchCount=0; + clockTicks = 2*codeTicksAccessSeq16(address) + codeTicksAccesint16(address)+3; + CPUSoftwareInterrupt(opcode & 0xFF); + break; + } + case 0xe0: + case 0xe1: + case 0xe2: + case 0xe3: + case 0xe4: + case 0xe5: + case 0xe6: + case 0xe7: + { + // B offset + int offset = (opcode & 0x3FF) << 1; + if(opcode & 0x0400) + offset |= 0xFFFFF800; + reg[15].I += offset; + armNextPC = reg[15].I; + reg[15].I += 2; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks += clockTicks + codeTicksAccesint16(armNextPC)+1; + } + break; + case 0xf0: + case 0xf1: + case 0xf2: + case 0xf3: + { + // BLL #offset + int offset = (opcode & 0x7FF); + reg[14].I = reg[15].I + (offset << 12); + } + break; + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + { + // BLL #offset + int offset = (opcode & 0x7FF); + reg[14].I = reg[15].I + ((offset << 12) | 0xFF800000); + } + break; + case 0xf8: + case 0xf9: + case 0xfa: + case 0xfb: + case 0xfc: + case 0xfd: + case 0xfe: + case 0xff: + { + // BLH #offset + int offset = (opcode & 0x7FF); + uint32 temp = reg[15].I-2; + reg[15].I = (reg[14].I + (offset<<1))&0xFFFFFFFE; + armNextPC = reg[15].I; + reg[15].I += 2; + reg[14].I = temp|1; + THUMB_PREFETCH; + busPrefetchCount=0; + clockTicks += 2*codeTicksAccessSeq16(armNextPC) + codeTicksAccesint16(armNextPC)+3; + } + break; +#ifdef BKPT_SUPPORT + case 0xbe: + // BKPT #comment + extern void (*dbgSignal)(int,int); + reg[15].I -= 2; + armNextPC -= 2; + dbgSignal(5, opcode & 255); + return; +#endif + case 0xb1: + case 0xb2: + case 0xb3: + case 0xb6: + case 0xb7: + case 0xb8: + case 0xb9: + case 0xba: + case 0xbb: +#ifndef BKPT_SUPPORT + case 0xbe: +#endif + case 0xbf: + case 0xde: + default: + unknown_thumb: +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_UNDEFINED) + log("Undefined THUMB instruction %04x at %08x\n", opcode, armNextPC-2); +#endif + CPUUndefinedException(); + break; +} + return(clockTicks); +} + +} diff --git a/mednafen/gba-09333/thumb.h b/mednafen/gba-09333/thumb.h new file mode 100644 index 0000000..3dede69 --- /dev/null +++ b/mednafen/gba-09333/thumb.h @@ -0,0 +1,6 @@ +namespace MDFN_IEN_GBA +{ + +unsigned int RunTHUMB(void); + +} diff --git a/mednafen/mednafen.h b/mednafen/mednafen.h index 761006b..312cb7b 100644 --- a/mednafen/mednafen.h +++ b/mednafen/mednafen.h @@ -25,6 +25,8 @@ #define gzopen(a, b) fopen(a, b) #define gzread(a, b, c) fread(b, c, 1, a) #define gzclose(a) fclose(a) +#define gzgetc(a) fgetc(a) +#define gzseek(a,b,c) fseek(a,b,c) #else #define GET_FDATA(fp) (fp.Data()) #define GET_FSIZE(fp) (fp.Size()) @@ -33,6 +35,8 @@ #define GET_FEXTS_PTR(fp) (fp->ext) #define gzread(a, b, c) gzread(a, b, c) #define gzclose(a) gzclose(a) +#define gzgetc(a) gzgetc(a) +#define gzseek(a,b,c) gzseek(a,b,c) #endif #ifndef gettext_noop diff --git a/mednafen/psx-09333/psx.h b/mednafen/psx-09333/psx.h index 540c2ac..9e7bee1 100644 --- a/mednafen/psx-09333/psx.h +++ b/mednafen/psx-09333/psx.h @@ -38,14 +38,10 @@ namespace MDFN_IEN_PSX #define PSX_WARNING(format, ...) { PSX_DBG(PSX_DBG_WARNING, format "\n", ## __VA_ARGS__); } #define PSX_DBGINFO(format, ...) { } -#elif defined(_WIN32) - static INLINE void PSX_DBG(unsigned level, const char* format, ...) { } - static INLINE void PSX_WARNING(const char* format, ...) { } - static INLINE void PSX_DBGINFO(const char* format, ...) { } #else - void PSX_DBG(unsigned level, const char *format, ...) throw() MDFN_COLD MDFN_FORMATSTR(printf, 2, 3); - #define PSX_WARNING(format, ...) { } - #define PSX_DBGINFO(format, ...) { } + static void PSX_DBG(unsigned level, const char* format, ...) { } + static void PSX_WARNING(const char* format, ...) { } + static void PSX_DBGINFO(const char* format, ...) { } #endif typedef int32 pscpu_timestamp_t;