aboutsummaryrefslogtreecommitdiff
path: root/source/cpuops.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/cpuops.c')
-rw-r--r--source/cpuops.c211
1 files changed, 207 insertions, 4 deletions
diff --git a/source/cpuops.c b/source/cpuops.c
index d7f90e6..977f97e 100644
--- a/source/cpuops.c
+++ b/source/cpuops.c
@@ -3424,6 +3424,31 @@ static inline void CPUShutdown()
#define CPUShutdown()
#endif
+// From the speed-hacks branch of CatSFC
+static inline void ForceShutdown()
+{
+#ifdef CPU_SHUTDOWN
+#ifndef SA1_OPCODES
+ CPU.WaitAddress = NULL;
+ if (Settings.SA1)
+ S9xSA1ExecuteDuringSleep ();
+ CPU.Cycles = CPU.NextEvent;
+ if (IAPU.APUExecuting)
+ {
+ ICPU.CPUExecuting = false;
+ do
+ {
+ APU_EXECUTE1();
+ } while (APU.Cycles < CPU.NextEvent);
+ ICPU.CPUExecuting = true;
+ }
+#else
+ SA1.Executing = false;
+ SA1.CPUExecuting = false;
+#endif
+#endif
+}
+
/* BCC */
static void Op90(void)
{
@@ -5008,16 +5033,194 @@ static void OpCB(void)
#endif // SA1_OPCODES
}
-// STP
+// Usually an STP opcode
+// SNESAdvance speed hack, not implemented in Snes9xTYL | Snes9x-Euphoria (from the speed-hacks branch of CatSFC)
static void OpDB(void)
{
- CPU.PC--;
- CPU.Flags |= DEBUG_MODE_FLAG;
+#if !defined NO_SPEEDHACKS && defined CPU_SHUTDOWN
+ uint8_t NextByte = *CPU.PC++;
+
+ ForceShutdown();
+
+ int8_t BranchOffset = (NextByte & 0x7F) | ((NextByte & 0x40) << 1);
+ // ^ -64 .. +63, sign extend bit 6 into 7 for unpacking
+ long TargetAddress = ((int) (CPU.PC - CPU.PCBase) + BranchOffset) & 0xffff;
+
+ switch (NextByte & 0x80)
+ {
+ case 0x00: // BNE
+ BranchCheck1 ();
+ if (!CheckZero ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ case 0x80: // BEQ
+ BranchCheck2 ();
+ if (CheckZero ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ }
+#else
+ CPU.PC--;
+ CPU.Flags |= DEBUG_MODE_FLAG;
+#endif
}
-// Reserved S9xOpcode
+// SNESAdvance speed hack, as implemented in Snes9xTYL / Snes9x-Euphoria (from the speed-hacks branch of CatSFC)
static void Op42(void)
{
+#if !defined NO_SPEEDHACKS && defined CPU_SHUTDOWN
+ uint8_t NextByte = *CPU.PC++;
+
+ ForceShutdown();
+
+ int8_t BranchOffset = 0xF0 | (NextByte & 0xF); // always negative
+ long TargetAddress = ((int) (CPU.PC - CPU.PCBase) + BranchOffset) & 0xffff;
+
+ switch (NextByte & 0xF0)
+ {
+ case 0x10: // BPL
+ BranchCheck1 ();
+ if (!CheckNegative ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ case 0x30: // BMI
+ BranchCheck1 ();
+ if (CheckNegative ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ case 0x50: // BVC
+ BranchCheck0 ();
+ if (!CheckOverflow ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ case 0x70: // BVS
+ BranchCheck0 ();
+ if (CheckOverflow ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ case 0x80: // BRA
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ return;
+ case 0x90: // BCC
+ BranchCheck0 ();
+ if (!CheckCarry ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ case 0xB0: // BCS
+ BranchCheck0 ();
+ if (CheckCarry ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ case 0xD0: // BNE
+ BranchCheck1 ();
+ if (!CheckZero ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ case 0xF0: // BEQ
+ BranchCheck2 ();
+ if (CheckZero ()) {
+ CPU.PC = CPU.PCBase + TargetAddress;
+#ifdef VAR_CYCLES
+ CPU.Cycles += ONE_CYCLE;
+#else
+#ifndef SA1_OPCODES
+ CPU.Cycles++;
+#endif
+#endif
+ CPUShutdown ();
+ }
+ return;
+ }
+#endif
}
/*****************************************************************************/