summaryrefslogtreecommitdiff
path: root/src/spc700
diff options
context:
space:
mode:
authorToad King2012-06-14 03:21:06 -0400
committerToad King2012-06-14 03:21:06 -0400
commit6fb0c7a7a53e1eba7a0f5dc5b1ade312a0d76119 (patch)
tree885cf7f507139b795ba7b2a6fb829dc044da39dd /src/spc700
downloadsnes9x2002-6fb0c7a7a53e1eba7a0f5dc5b1ade312a0d76119.tar.gz
snes9x2002-6fb0c7a7a53e1eba7a0f5dc5b1ade312a0d76119.tar.bz2
snes9x2002-6fb0c7a7a53e1eba7a0f5dc5b1ade312a0d76119.zip
initial pocketsnes commit
Diffstat (limited to 'src/spc700')
-rw-r--r--src/spc700/Makefile13
-rw-r--r--src/spc700/Makefile.win15
-rw-r--r--src/spc700/debug/apu.h195
-rw-r--r--src/spc700/debug/apumem.h222
-rw-r--r--src/spc700/debug/port.h497
-rw-r--r--src/spc700/debug/spc700.cpp2600
-rw-r--r--src/spc700/debug/spc700.h172
-rw-r--r--src/spc700/spcgen.c2164
-rw-r--r--src/spc700/spcgen.dsp88
-rw-r--r--src/spc700/spcgen.dsw29
-rw-r--r--src/spc700/spcgen.ncbbin0 -> 41984 bytes
-rw-r--r--src/spc700/spcgen.optbin0 -> 53760 bytes
-rw-r--r--src/spc700/spcgen.plg32
13 files changed, 6027 insertions, 0 deletions
diff --git a/src/spc700/Makefile b/src/spc700/Makefile
new file mode 100644
index 0000000..e412de9
--- /dev/null
+++ b/src/spc700/Makefile
@@ -0,0 +1,13 @@
+CFLAGS = -Wall
+
+all : spc700a.s
+
+spc700a.s : spcgen
+ ./spcgen
+
+spcgen : spcgen.o
+
+
+clean :
+ $(RM) spc700a.s spcgen spcgen.o
+
diff --git a/src/spc700/Makefile.win b/src/spc700/Makefile.win
new file mode 100644
index 0000000..06095b0
--- /dev/null
+++ b/src/spc700/Makefile.win
@@ -0,0 +1,15 @@
+# Makefile for MS Visual C
+
+ALL : spc700a.s
+
+spc700a.s : spcgen.exe
+ spcgen.exe
+
+spcgen.exe :
+ cl /W3 spcgen.c
+
+
+CLEAN :
+ -@erase spc700a.s
+ -@erase spcgen.exe
+ -@erase spcgen.obj
diff --git a/src/spc700/debug/apu.h b/src/spc700/debug/apu.h
new file mode 100644
index 0000000..dd0451c
--- /dev/null
+++ b/src/spc700/debug/apu.h
@@ -0,0 +1,195 @@
+/*
+ * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
+ *
+ * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
+ * Jerremy Koot (jkoot@snes9x.com)
+ *
+ * Super FX C emulator code
+ * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
+ * Gary Henderson.
+ * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
+ *
+ * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
+ * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
+ * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
+ *
+ * DOS port code contains the works of other authors. See headers in
+ * individual files.
+ *
+ * Snes9x homepage: http://www.snes9x.com
+ *
+ * Permission to use, copy, modify and distribute Snes9x in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Snes9x is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Snes9x or software derived from Snes9x.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so everyone can benefit from the modifications
+ * in future versions.
+ *
+ * Super NES and Super Nintendo Entertainment System are trademarks of
+ * Nintendo Co., Limited and its subsidiary companies.
+ */
+#ifndef _apu_h_
+#define _apu_h_
+
+#include "spc700.h"
+
+/*
+typedef union
+{
+ struct { uint8 A, Y; } B;
+ uint16 W;
+} YAndA;
+*/
+
+struct SIAPU
+{
+ uint8 *DirectPage; // 0x00
+ uint32 Address; // 0x04 c core only
+ uint8 *WaitAddress1; // 0x08
+ uint8 *WaitAddress2; // 0x0C
+ uint32 WaitCounter; // 0x10
+ uint8 *ShadowRAM; // 0x14
+ uint8 *CachedSamples; // 0x18
+ uint8 _Carry; // 0x1C c core only
+ uint8 _Overflow; // 0x1D c core only
+ uint8 Bit; // 0x1E c core only
+ uint8 pad0;
+ uint32 TimerErrorCounter; // 0x20
+ uint32 Scanline; // 0x24
+ int32 OneCycle; // 0x28
+ int32 TwoCycles; // 0x2C
+ // notaz: reordered and moved everything here, for faster context load/save
+ uint32 *asmJumpTab; // 0x30
+ uint8 *PC; // 0x34
+ YAndA YA; // 0x38 0x0000YYAA
+ uint8 P; // 0x3C flags: NODBHIZC
+ uint8 pad1;
+ uint8 pad2;
+ uint8 _Zero; // 0x3F Z=0, when this!=0; also stores neg flag in &0x80
+ uint8 X; // 0x40
+ uint8 S; // 0x41 stack pointer, default: 0xff
+ uint16 pad3;
+ uint8 *RAM; // 0x44
+ uint8 *ExtraRAM; // 0x48 shortcut to APU.ExtraRAM
+
+ uint16 memread_addr;
+ uint8 memread_data;
+ uint16 memwrite_addr;
+ uint8 memwrite_data;
+ int icount;
+ uint8 opcode;
+ uint16 ya_prev;
+ uint8 x_prev;
+};
+
+struct SAPU
+{
+ int32 Cycles;
+ bool8 ShowROM;
+ uint8 Flags;
+ uint8 KeyedChannels;
+ uint8 OutPorts [4];
+ uint8 DSP [0x80];
+ uint8 ExtraRAM [64];
+ uint16 Timer [3];
+ uint16 TimerTarget [3];
+ bool8 TimerEnabled [3];
+ bool8 TimerValueWritten [3];
+};
+
+EXTERN_C struct SAPU APU;
+EXTERN_C struct SIAPU IAPU;
+EXTERN_C struct SIAPU IAPU2;
+EXTERN_C struct SIAPU *pIAPU;
+
+STATIC inline void S9xAPUUnpackStatus()
+{
+ IAPU._Zero =((IAPU.P & Zero) == 0) | (IAPU.P & Negative);
+ IAPU._Carry = (IAPU.P & Carry);
+ IAPU._Overflow = (IAPU.P & Overflow);
+}
+
+STATIC inline void S9xAPUPackStatus()
+{
+ IAPU.P &= ~(Zero | Negative | Carry | Overflow);
+ if(IAPU._Carry) IAPU.P |= Carry;
+ if(!IAPU._Zero) IAPU.P |= Zero;
+ if(IAPU._Overflow) IAPU.P |= Overflow;
+ if(IAPU._Zero & 0x80) IAPU.P |= Negative;
+}
+
+START_EXTERN_C
+void S9xResetAPU (void);
+bool8 S9xInitAPU ();
+void S9xDeinitAPU ();
+void S9xDecacheSamples ();
+int S9xTraceAPU ();
+int S9xAPUOPrint (char *buffer, uint16 Address);
+void S9xSetAPUControl (uint8 byte);
+void S9xSetAPUDSP (uint8 byte);
+uint8 S9xGetAPUDSP ();
+void S9xSetAPUTimer (uint16 Address, uint8 byte);
+bool8 S9xInitSound (int quality, bool8 stereo, int buffer_size);
+void S9xOpenCloseSoundTracingFile (bool8);
+void S9xPrintAPUState ();
+extern int32 S9xAPUCycles [256]; // Scaled cycle lengths
+extern int32 S9xAPUCycleLengths [256]; // Raw data.
+extern void (*S9xApuOpcodes [256]) (void);
+extern void (*S9xApuOpcodesReal [256]) (void);
+void APUCompare();
+END_EXTERN_C
+
+
+#define APU_VOL_LEFT 0x00
+#define APU_VOL_RIGHT 0x01
+#define APU_P_LOW 0x02
+#define APU_P_HIGH 0x03
+#define APU_SRCN 0x04
+#define APU_ADSR1 0x05
+#define APU_ADSR2 0x06
+#define APU_GAIN 0x07
+#define APU_ENVX 0x08
+#define APU_OUTX 0x09
+
+#define APU_MVOL_LEFT 0x0c
+#define APU_MVOL_RIGHT 0x1c
+#define APU_EVOL_LEFT 0x2c
+#define APU_EVOL_RIGHT 0x3c
+#define APU_KON 0x4c
+#define APU_KOFF 0x5c
+#define APU_FLG 0x6c
+#define APU_ENDX 0x7c
+
+#define APU_EFB 0x0d
+#define APU_PMON 0x2d
+#define APU_NON 0x3d
+#define APU_EON 0x4d
+#define APU_DIR 0x5d
+#define APU_ESA 0x6d
+#define APU_EDL 0x7d
+
+#define APU_C0 0x0f
+#define APU_C1 0x1f
+#define APU_C2 0x2f
+#define APU_C3 0x3f
+#define APU_C4 0x4f
+#define APU_C5 0x5f
+#define APU_C6 0x6f
+#define APU_C7 0x7f
+
+#define APU_SOFT_RESET 0x80
+#define APU_MUTE 0x40
+#define APU_ECHO_DISABLED 0x20
+
+#define FREQUENCY_MASK 0x3fff
+#endif
diff --git a/src/spc700/debug/apumem.h b/src/spc700/debug/apumem.h
new file mode 100644
index 0000000..b1b5f65
--- /dev/null
+++ b/src/spc700/debug/apumem.h
@@ -0,0 +1,222 @@
+/*
+ * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
+ *
+ * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
+ * Jerremy Koot (jkoot@snes9x.com)
+ *
+ * Super FX C emulator code
+ * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
+ * Gary Henderson.
+ * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
+ *
+ * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
+ * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
+ * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
+ *
+ * DOS port code contains the works of other authors. See headers in
+ * individual files.
+ *
+ * Snes9x homepage: http://www.snes9x.com
+ *
+ * Permission to use, copy, modify and distribute Snes9x in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Snes9x is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Snes9x or software derived from Snes9x.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so everyone can benefit from the modifications
+ * in future versions.
+ *
+ * Super NES and Super Nintendo Entertainment System are trademarks of
+ * Nintendo Co., Limited and its subsidiary companies.
+ */
+#ifndef _apumemory_h_
+#define _apumemory_h_
+
+START_EXTERN_C
+extern uint8 W4;
+extern uint8 APUROM[64];
+END_EXTERN_C
+
+// TODO: restore nondebug version
+
+INLINE uint8 S9xAPUGetByteZ (uint8 Address)
+{
+ uint8 res = 0;
+ pIAPU->memread_addr = Address;
+
+ if (Address >= 0xf0 && pIAPU->DirectPage == pIAPU->RAM)
+ {
+ if (Address >= 0xf4 && Address <= 0xf7)
+ {
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitAddress2 = pIAPU->WaitAddress1;
+ pIAPU->WaitAddress1 = pIAPU->PC;
+#endif
+ res = (pIAPU->RAM [Address]);
+ }
+ else if (Address >= 0xfd)
+ {
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitAddress2 = pIAPU->WaitAddress1;
+ pIAPU->WaitAddress1 = pIAPU->PC;
+#endif
+ uint8 t = pIAPU->RAM [Address];
+ if(pIAPU != &IAPU)
+ pIAPU->RAM [Address] = 0;
+ res = (t);
+ }
+ else if (Address == 0xf3) {
+ res = (S9xGetAPUDSP ());
+ }
+ else res = (pIAPU->RAM [Address]);
+ }
+ else
+ res = (pIAPU->DirectPage [Address]);
+
+ pIAPU->memread_data = res;
+ return res;
+}
+
+INLINE void S9xAPUSetByteZ (uint8 val, uint8 Address)
+{
+ pIAPU->memwrite_addr = Address;
+ pIAPU->memwrite_data = val;
+
+ if(pIAPU == &IAPU) return;
+
+ if (Address >= 0xf0 && pIAPU->DirectPage == pIAPU->RAM)
+ {
+ if (Address == 0xf3)
+ S9xSetAPUDSP (val);
+ else
+ if (Address >= 0xf4 && Address <= 0xf7)
+ APU.OutPorts [Address - 0xf4] = val;
+ else
+ if (Address == 0xf1)
+ S9xSetAPUControl (val);
+ else
+ if (Address < 0xfd)
+ {
+ pIAPU->RAM [Address] = val;
+ if (Address >= 0xfa)
+ {
+ if (val == 0)
+ APU.TimerTarget [Address - 0xfa] = 0x100;
+ else
+ APU.TimerTarget [Address - 0xfa] = val;
+ }
+ }
+ }
+ else
+ pIAPU->DirectPage [Address] = val;
+}
+
+INLINE uint8 S9xAPUGetByte (uint32 Address)
+{
+ Address &= 0xffff;
+ uint8 res = 0;
+ pIAPU->memread_addr = Address;
+
+ if (Address <= 0xff && Address >= 0xf0)
+ {
+ if (Address >= 0xf4 && Address <= 0xf7)
+ {
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitAddress2 = pIAPU->WaitAddress1;
+ pIAPU->WaitAddress1 = pIAPU->PC;
+#endif
+ res = (pIAPU->RAM [Address]);
+ }
+ else if (Address == 0xf3) {
+ res = (S9xGetAPUDSP ());
+ }
+ else if (Address >= 0xfd)
+ {
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitAddress2 = pIAPU->WaitAddress1;
+ pIAPU->WaitAddress1 = pIAPU->PC;
+#endif
+ uint8 t = pIAPU->RAM [Address];
+ if(pIAPU != &IAPU)
+ pIAPU->RAM [Address] = 0;
+ res = (t);
+ }
+ else res = (pIAPU->RAM [Address]);
+ }
+ else
+ res = (pIAPU->RAM [Address]);
+
+ pIAPU->memread_data = res;
+ return res;
+}
+
+INLINE void S9xAPUSetByte (uint8 val, uint32 Address)
+{
+ Address &= 0xffff;
+ pIAPU->memwrite_addr = Address;
+ pIAPU->memwrite_data = val;
+
+ if(pIAPU == &IAPU) return;
+
+ if (Address <= 0xff && Address >= 0xf0)
+ {
+ if (Address == 0xf3)
+ S9xSetAPUDSP (val);
+ else
+ if (Address >= 0xf4 && Address <= 0xf7)
+ APU.OutPorts [Address - 0xf4] = val;
+ else
+ if (Address == 0xf1)
+ S9xSetAPUControl (val);
+ else
+ if (Address < 0xfd)
+ {
+ pIAPU->RAM [Address] = val;
+ if (Address >= 0xfa)
+ {
+ if (val == 0)
+ APU.TimerTarget [Address - 0xfa] = 0x100;
+ else
+ APU.TimerTarget [Address - 0xfa] = val;
+ }
+ }
+ }
+ else
+ {
+#if 0
+if (Address >= 0x2500 && Address <= 0x2504)
+printf ("%06d %04x <- %02x\n", ICPU.Scanline, Address, val);
+if (Address == 0x26c6)
+{
+ extern FILE *apu_trace;
+ extern FILE *trace;
+ APU.Flags |= TRACE_FLAG;
+ CPU.Flags |= TRACE_FLAG;
+ if (apu_trace == NULL)
+ apu_trace = fopen ("aputrace.log", "wb");
+ if (trace == NULL)
+ trace = fopen ("trace.log", "wb");
+ printf ("TRACING SWITCHED ON\n");
+}
+#endif
+ if (Address < 0xffc0)
+ pIAPU->RAM [Address] = val;
+ else
+ {
+ APU.ExtraRAM [Address - 0xffc0] = val;
+ if (!APU.ShowROM)
+ pIAPU->RAM [Address] = val;
+ }
+ }
+}
+
+#endif
diff --git a/src/spc700/debug/port.h b/src/spc700/debug/port.h
new file mode 100644
index 0000000..4d7eede
--- /dev/null
+++ b/src/spc700/debug/port.h
@@ -0,0 +1,497 @@
+/*
+ * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
+ *
+ * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
+ * Jerremy Koot (jkoot@snes9x.com)
+ *
+ * Super FX C emulator code
+ * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
+ * Gary Henderson.
+ * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
+ *
+ * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
+ * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
+ * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
+ *
+ * DOS port code contains the works of other authors. See headers in
+ * individual files.
+ *
+ * Snes9x homepage: http://www.snes9x.com
+ *
+ * Permission to use, copy, modify and distribute Snes9x in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Snes9x is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Snes9x or software derived from Snes9x.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so everyone can benefit from the modifications
+ * in future versions.
+ *
+ * Super NES and Super Nintendo Entertainment System are trademarks of
+ * Nintendo Co., Limited and its subsidiary companies.
+ */
+#ifndef _PORT_H_
+#define _PORT_H_
+
+
+// horrible mess here
+
+int yo_rand(void);
+
+#ifdef __SYMBIAN32__
+
+// debug
+#ifdef __DEBUG_PRINT
+#undef printf
+extern "C" void dprintf(char *format, ...);
+#define printf dprintf
+#else
+#define printf(x...)
+#define dprintf(x...)
+#endif
+
+#include <string.h>
+
+#define PIXEL_FORMAT RGB565
+#undef GFX_MULTI_FORMAT
+
+#ifndef snes9x_types_defined
+#define snes9x_types_defined
+
+typedef unsigned char bool8;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed int int32;
+typedef unsigned int uint32;
+typedef long long int64; // correct?
+#endif
+
+#include "pixform.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+#define EXTERN_C extern "C"
+#define START_EXTERN_C extern "C" {
+#define END_EXTERN_C }
+#else
+#define EXTERN_C extern
+#define START_EXTERN_C
+#define END_EXTERN_C
+#endif
+
+
+#ifndef PATH_MAX
+#define PATH_MAX 0x100 // == KMaxFileName
+#endif
+
+/*
+#define _MAX_DIR PATH_MAX
+#define _MAX_DRIVE 1
+#define _MAX_FNAME PATH_MAX
+#define _MAX_EXT 3
+*/
+#define _MAX_PATH PATH_MAX
+
+
+#define ZeroMemory(a,b) memset((a),0,(b))
+
+EXTERN_C void S9xGenerateSound ();
+
+#define SLASH_STR "\\"
+#define SLASH_CHAR '\\'
+
+#define LSB_FIRST
+#define STATIC static
+#define FASTCALL
+#define INLINE inline
+#define VOID void
+#define PACKING __attribute__ ((packed))
+#define ALIGN_BY_ONE __attribute__ ((aligned (1), packed))
+#define gp32_pause()
+#define gm_memset memset
+#define CHECK_SOUND()
+#define CPU_SHUTDOWN
+#define VAR_CYCLES
+#define SPC700_C
+#define EXECUTE_SUPERFX_PER_LINE
+#define OLD_COLOUR_BLENDING
+#define _NEWPPU_
+#define gp32_atoi atoi
+//#define SPC700_SHUTDOWN // incompatible with ASM_SPC700
+// notaz
+//#define ASM_SPC700
+#define SUPER_FX
+
+#ifndef TITLE
+#define TITLE "Snes9x"
+#endif
+
+
+#else // __SYMBIAN32__
+
+
+//#include <limits.h>
+
+#ifdef __GP32__
+
+
+//#define __GP32_APUCACHE__
+
+#define CHECK_SOUND()
+
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 3
+
+long *gp32_fopen (char *fname,char *mode);
+void gp32_fclose (long *s);
+long gp32_fread (unsigned char *ptr,long lg,long *s);
+long gp32_fwrite (unsigned char *ptr,long lg,long *s);
+void gp32_fseek (long position,int ref,long *s);
+
+
+//#undef ZLIB
+//#define ZLIB
+#define UNZIP_SUPPORT
+
+
+#define SPC700_SHUTDOWN
+#define CPU_SHUTDOWN
+#define VAR_CYCLES
+#define SPC700_C
+//#define ZSNES_C4
+//#define ZSNES_FX
+#define EXECUTE_SUPERFX_PER_LINE
+//#define THREADCPU
+
+
+//#define USE_GLIDE
+//#define USE_OPENGL
+//#define NETPLAY_SUPPORT
+//#define FMOD_SUPPORT
+#define OLD_COLOUR_BLENDING
+
+#endif // __GP32__
+
+#ifndef STORM
+#ifdef __GP32__
+
+extern "C"
+{
+#include "gpdef.h"
+#include "gpstdlib.h"
+#include "gpgraphic.h"
+#include "gpfont.h"
+#include "gpmm.h"
+#include "gpmem.h"
+#include "gpstdio.h"
+}
+
+#undef byte
+#undef word
+#undef dword
+#undef qword
+
+/*typedef unsigned long bool8_32;
+typedef unsigned long uint8_32;
+typedef unsigned long uint16_32;
+typedef long int8_32;
+typedef long int16_32;*/
+
+#undef time_t
+#define time_t long
+
+char *gp32_strrchr(char *s, char c);
+char gp32_toupper(char c);
+char *gp32_strupr(char *s);
+char *gp32_strlwr(char *s);
+int gp32_memcmp(char *s1,char *s2, int lg);
+int gp32_strncmp(char *s1,char *s2, int lg);
+int gp32_strcasecmp(const char *s1, const char *s2 );
+int gp32_strncasecmp(const char *s1, const char *s2, unsigned n);
+long gp32_time(void);
+int gp32_pause(void);
+int gp32_atoi(char *s);
+
+#define malloc gm_malloc
+#define free gm_free
+#define memcpy gm_memcpy
+
+#define strcpy gm_strcpy
+#define strncpy gm_strncpy
+#define strcat gm_strcat
+#define memset gm_memset
+#define memmove gm_memcpy
+#define strlen gm_lstrlen
+#define strcmp gm_compare
+#define memcmp(a,b,c) gp32_memcmp((char*)a,(char*)b,c)
+#define strrchr(a,b) gp32_strrchr((char*)a,(char)b)
+#define strncmp(a,b,c) gp32_strncmp((char*)a,(char*)b,(int)c)
+#define strlwr gp32_strlwr
+//#define atoi gp32_atoi
+
+#define islower(a) ((a>='a')&&(a<='z'))
+#define isdigit(a) ((a>='0')&&(a<='9'))
+#define isalpha(a) (((a>='0')&&(a<='9'))||((a>='0')&&(a<='9'))||((a>='A')&&(a<='Z')))
+#define toupper(a) (islower(a)?a+'A'-'a':a)
+
+#define sprintf gm_sprintf
+
+
+
+void gp32_printf(char *a);
+void gp32_GpTextOut(unsigned char *buffer,int X,int Y,char *A,int col,int bold);
+void gp32_GpTextOutBig(unsigned char *buffer,int X,int Y,char *A,int col,int bold);
+#define printf //(a) gp32_printf(a)
+
+#define strcasecmp gp32_strcasecmp
+#define strncasecmp gp32_strncasecmp
+
+#define time(a) gp32_time()
+
+#define _NEWPPU_
+
+//#define PROFILING
+
+#ifdef PROFILING
+void gp32_profile_start(int a);
+void gp32_profile_end(int a);
+#define PROF_START(a) gp32_profile_start(a)
+#define PROF_END(a) gp32_profile_end(a)
+#endif
+
+#elif defined(__SYMBIAN32__) // /__GP32__
+#include <string.h>
+#else
+#include <memory.h>
+#include <string.h>
+#endif
+#else // #ifndef STORM
+#include <strings.h>
+#include <clib/powerpc_protos.h>
+#endif
+
+//#include <sys/types.h>
+
+#define PIXEL_FORMAT RGB565
+#undef GFX_MULTI_FORMAT
+
+#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
+
+#include "zlib.h"
+#define ZLIB
+#define EXECUTE_SUPERFX_PER_LINE
+#define SOUND
+#define VAR_CYCLES
+#define CPU_SHUTDOWN
+#define SPC700_SHUTDOWN
+#define PIXEL_FORMAT RGB555
+#define CHECK_SOUND()
+#define M_PI 3.14159265359
+#undef _MAX_PATH
+
+#undef DEBUGGER // Apple Universal Headers sometimes #define DEBUGGER
+#undef GFX_MULTI_FORMAT
+
+int strncasecmp(const char *s1, const char *s2, unsigned n);
+int strcasecmp(const char *s1, const char *s2 );
+
+#endif
+
+#ifndef snes9x_types_defined
+#define snes9x_types_defined
+
+typedef unsigned char bool8;
+
+#ifndef __WIN32kk__
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed int int32;
+typedef unsigned int uint32;
+#ifdef __GP32__
+typedef signed __int64 int64;
+//typedef signed long int64;
+#else
+typedef long long int64;
+#endif
+#else // __WIN32kk__
+
+#ifdef __BORLANDC__
+#include <systypes.h>
+#else
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef signed char int8;
+typedef short int16;
+
+#ifndef WSAAPI
+// winsock2.h typedefs int32 as well.
+typedef long int32;
+#endif
+
+typedef unsigned int uint32;
+
+#endif // __BORLANDC__
+
+typedef __int64 int64;
+
+#endif // __WIN32kk__
+#endif // snes9x_types_defined
+#include "pixform.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifdef STORM
+#define EXTERN_C
+#define START_EXTERN_C
+#define END_EXTERN_C
+#else
+#if defined(__cplusplus) || defined(c_plusplus)
+#define EXTERN_C extern "C"
+#define START_EXTERN_C extern "C" {
+#define END_EXTERN_C }
+#else
+#define EXTERN_C extern
+#define START_EXTERN_C
+#define END_EXTERN_C
+#endif
+#endif
+
+#ifndef __WIN32kk__
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#define _MAX_DIR PATH_MAX
+#define _MAX_DRIVE 1
+#define _MAX_FNAME PATH_MAX
+#define _MAX_EXT PATH_MAX
+#define _MAX_PATH PATH_MAX
+
+#define ZeroMemory(a,b) memset((a),0,(b))
+
+#ifndef __WIN32__
+void _makepath (char *path, const char *drive, const char *dir, const char *fname, const char *ext);
+void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext);
+#endif
+
+#else // __WIN32kk__
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+#endif
+
+EXTERN_C void S9xGenerateSound ();
+
+#ifdef STORM
+EXTERN_C int soundsignal;
+EXTERN_C void MixSound(void);
+//Yes, CHECK_SOUND is getting defined correctly!
+#define CHECK_SOUND if (Settings.APUEnabled) if(SetSignalPPC(0L, soundsignal) & soundsignal) MixSound
+#else
+#ifndef __GP32__
+#define CHECK_SOUND()
+#endif
+#endif
+
+#if defined (__DJGPP)||defined(__GP32__)
+#define SLASH_STR "\\"
+#define SLASH_CHAR '\\'
+#else
+#define SLASH_STR "/"
+#define SLASH_CHAR '/'
+#endif
+
+#ifdef __linux
+typedef void (*SignalHandler)(int);
+#define SIG_PF SignalHandler
+#endif
+
+#if defined(__i386__) || defined(__i486__) || defined(__i586__) || \
+ defined(__WIN32kk__) || defined(__alpha__)
+#define LSB_FIRST
+#define FAST_LSB_WORD_ACCESS
+#define PACKING
+#define ALIGN_BY_ONE
+
+#else
+
+#ifdef __GP32__
+#define LSB_FIRST
+#define STATIC static
+#define FASTCALL
+#define INLINE inline
+#define VOID void
+#else
+// must be gp2x
+#define LSB_FIRST
+#define STATIC static
+#define FASTCALL
+#define INLINE inline
+#define VOID void
+#define PACKING __attribute__ ((packed))
+#define ALIGN_BY_ONE __attribute__ ((aligned (1), packed))
+#define gp32_pause()
+#define gm_memset memset
+#define CHECK_SOUND()
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 3
+#define SPC700_SHUTDOWN
+#define CPU_SHUTDOWN
+#define VAR_CYCLES
+#define SPC700_C
+#define EXECUTE_SUPERFX_PER_LINE
+#define OLD_COLOUR_BLENDING
+#define _NEWPPU_
+#define gp32_atoi atoi
+#endif
+
+#endif
+
+#ifdef __sun
+#define TITLE "Snes9X: Solaris"
+#endif
+
+#ifdef __linux
+#define TITLE "Snes9X: Linux"
+#endif
+
+#ifndef TITLE
+#define TITLE "Snes9x"
+#endif
+
+#ifdef STORM
+#define STATIC
+#define strncasecmp strnicmp
+#else
+#define STATIC static
+#endif
+
+#endif // !defined(__SYMBIAN32__)
+
+#endif // _PORT_H_
diff --git a/src/spc700/debug/spc700.cpp b/src/spc700/debug/spc700.cpp
new file mode 100644
index 0000000..5ab21ab
--- /dev/null
+++ b/src/spc700/debug/spc700.cpp
@@ -0,0 +1,2600 @@
+/*
+ * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
+ *
+ * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
+ * Jerremy Koot (jkoot@snes9x.com)
+ *
+ * Super FX C emulator code
+ * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
+ * Gary Henderson.
+ * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
+ *
+ * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
+ * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
+ * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
+ *
+ * DOS port code contains the works of other authors. See headers in
+ * individual files.
+ *
+ * Snes9x homepage: http://www.snes9x.com
+ *
+ * Permission to use, copy, modify and distribute Snes9x in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Snes9x is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Snes9x or software derived from Snes9x.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so everyone can benefit from the modifications
+ * in future versions.
+ *
+ * Super NES and Super Nintendo Entertainment System are trademarks of
+ * Nintendo Co., Limited and its subsidiary companies.
+ */
+#include "snes9x.h"
+#include "memmap.h"
+#include "display.h"
+#include "cpuexec.h"
+#include "apu.h"
+#include "spc700.h"
+
+// SPC700/Sound DSP chips have a 24.57MHz crystal on their PCB.
+
+//#if defined(ASM_SPC700)
+extern "C" {
+uint8 S9xAPUGetByteZ (uint8 address);
+uint8 S9xAPUGetByte (uint32 address);
+void S9xAPUSetByteZ (uint8, uint8 address);
+void S9xAPUSetByte (uint8, uint32 address);
+}
+/*
+#elif defined(NO_INLINE_SET_GET)
+uint8 S9xAPUGetByteZ (uint8 address);
+uint8 S9xAPUGetByte (uint32 address);
+void S9xAPUSetByteZ (uint8, uint8 address);
+void S9xAPUSetByte (uint8, uint32 address);
+
+#else
+#undef INLINE
+#define INLINE inline
+#include "apumem.h"
+#endif
+*/
+
+START_EXTERN_C
+extern uint8 Work8;
+extern uint16 Work16;
+extern uint32 Work32;
+extern signed char Int8;
+extern short Int16;
+extern long Int32;
+extern short Int16;
+extern uint8 W1;
+extern uint8 W2;
+
+END_EXTERN_C
+
+#define OP1 (*(pIAPU->PC + 1))
+#define OP2 (*(pIAPU->PC + 2))
+
+#ifdef SPC700_SHUTDOWN
+#define APUShutdown() \
+ if (Settings.Shutdown && (pIAPU->PC == pIAPU->WaitAddress1 || pIAPU->PC == pIAPU->WaitAddress2)) \
+ { \
+ if (pIAPU->WaitCounter == 0) \
+ { \
+ if (!ICPU.CPUExecuting) \
+ CPU.APU_Cycles = CPU.Cycles = CPU.NextEvent; \
+ else \
+ CPU.APU_APUExecuting = FALSE; \
+ } \
+ else \
+ if (pIAPU->WaitCounter >= 2) \
+ pIAPU->WaitCounter = 1; \
+ else \
+ pIAPU->WaitCounter--; \
+ }
+#else
+#define APUShutdown()
+#endif
+
+#define APUSetZN8(b)\
+ pIAPU->_Zero = (b);
+
+#define APUSetZN16(w)\
+ pIAPU->_Zero = ((w) != 0) | ((w) >> 8);
+
+void STOP (char *s)
+{
+ char buffer[100];
+
+#ifdef DEBUGGER
+ S9xAPUOPrint (buffer, pIAPU->PC - pIAPU->RAM);
+#endif
+
+ sprintf (String, "Sound CPU in unknown state executing %s at %04lX\n%s\n", s, pIAPU->PC - pIAPU->RAM, buffer);
+ S9xMessage (S9X_ERROR, S9X_APU_STOPPED, String);
+ APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE;
+ CPU.APU_APUExecuting = FALSE;
+
+#ifdef DEBUGGER
+ CPU.Flags |= DEBUG_MODE_FLAG;
+#else
+ S9xExit ();
+#endif
+}
+
+#define TCALL(n)\
+{\
+ PushW ((pIAPU->PC - pIAPU->RAM + 1)); \
+ pIAPU->PC = pIAPU->RAM + (APU.ExtraRAM [((15 - n) << 1)] + \
+ (APU.ExtraRAM [((15 - n) << 1) + 1] << 8)); \
+}
+
+// XXX: HalfCarry - BJ fixed?
+#define SBC(a,b)\
+Int16 = (short) (a) - (short) (b) + (short) (APUCheckCarry ()) - 1;\
+pIAPU->_Carry = Int16 >= 0;\
+if ((((a) ^ (b)) & 0x80) && (((a) ^ (uint8) Int16) & 0x80))\
+ APUSetOverflow ();\
+else \
+ APUClearOverflow (); \
+APUSetHalfCarry ();\
+if(((a) ^ (b) ^ (uint8) Int16) & 0x10)\
+ APUClearHalfCarry ();\
+(a) = (uint8) Int16;\
+APUSetZN8 ((uint8) Int16);
+
+// XXX: HalfCarry - BJ fixed?
+#define ADC(a,b)\
+Work16 = (a) + (b) + APUCheckCarry();\
+pIAPU->_Carry = Work16 >= 0x100; \
+if (~((a) ^ (b)) & ((b) ^ (uint8) Work16) & 0x80)\
+ APUSetOverflow ();\
+else \
+ APUClearOverflow (); \
+APUClearHalfCarry ();\
+/*if(((a) ^ (b) ^ (uint8) Int16) & 0x10) notaz: Int16!? */\
+if(((a) ^ (b) ^ (uint8) Work16) & 0x10)\
+ APUSetHalfCarry ();\
+(a) = (uint8) Work16;\
+APUSetZN8 ((uint8) Work16);
+
+#define CMP(a,b)\
+Int16 = (short) (a) - (short) (b);\
+pIAPU->_Carry = Int16 >= 0;\
+APUSetZN8 ((uint8) Int16);
+
+#define ASL(b)\
+ pIAPU->_Carry = ((b) & 0x80) != 0; \
+ (b) <<= 1;\
+ APUSetZN8 (b);
+#define LSR(b)\
+ pIAPU->_Carry = (b) & 1;\
+ (b) >>= 1;\
+ APUSetZN8 (b);
+#define ROL(b)\
+ Work16 = ((b) << 1) | APUCheckCarry (); \
+ pIAPU->_Carry = Work16 >= 0x100; \
+ (b) = (uint8) Work16; \
+ APUSetZN8 (b);
+#define ROR(b)\
+ Work16 = (b) | ((uint16) APUCheckCarry () << 8); \
+ pIAPU->_Carry = (uint8) Work16 & 1; \
+ Work16 >>= 1; \
+ (b) = (uint8) Work16; \
+ APUSetZN8 (b);
+
+#define Push(b)\
+ *(pIAPU->RAM + 0x100 + pIAPU->S) = b;\
+ pIAPU->S--;
+
+#define Pop(b)\
+ pIAPU->S++;\
+ (b) = *(pIAPU->RAM + 0x100 + pIAPU->S);
+
+#ifdef FAST_LSB_WORD_ACCESS
+#define PushW(w)\
+ *(uint16 *) (pIAPU->RAM + 0xff + pIAPU->S) = w;\
+ pIAPU->S -= 2;
+#define PopW(w)\
+ pIAPU->S += 2;\
+ w = *(uint16 *) (pIAPU->RAM + 0xff + pIAPU->S);
+#else
+#define PushW(w)\
+ *(pIAPU->RAM + 0xff + pIAPU->S) = w;\
+ *(pIAPU->RAM + 0x100 + pIAPU->S) = (w >> 8);\
+ pIAPU->S -= 2;
+#define PopW(w)\
+ pIAPU->S += 2; \
+ (w) = *(pIAPU->RAM + 0xff + pIAPU->S) + (*(pIAPU->RAM + 0x100 + pIAPU->S) << 8);
+#endif
+
+#define Relative()\
+ Int8 = OP1;\
+ Int16 = (int) (pIAPU->PC + 2 - pIAPU->RAM) + Int8;
+
+#define Relative2()\
+ Int8 = OP2;\
+ Int16 = (int) (pIAPU->PC + 3 - pIAPU->RAM) + Int8;
+
+#ifdef FAST_LSB_WORD_ACCESS
+#define IndexedXIndirect()\
+ pIAPU->Address = *(uint16 *) (pIAPU->DirectPage + ((OP1 + pIAPU->X) & 0xff));
+
+#define Absolute()\
+ pIAPU->Address = *(uint16 *) (pIAPU->PC + 1);
+
+#define AbsoluteX()\
+ pIAPU->Address = *(uint16 *) (pIAPU->PC + 1) + pIAPU->X;
+
+#define AbsoluteY()\
+ pIAPU->Address = *(uint16 *) (pIAPU->PC + 1) + pIAPU->YA.B.Y;
+
+#define MemBit()\
+ pIAPU->Address = *(uint16 *) (pIAPU->PC + 1);\
+ pIAPU->Bit = (uint8)(pIAPU->Address >> 13);\
+ pIAPU->Address &= 0x1fff;
+
+#define IndirectIndexedY()\
+ pIAPU->Address = *(uint16 *) (pIAPU->DirectPage + OP1) + pIAPU->YA.B.Y;
+#else
+#define IndexedXIndirect()\
+ pIAPU->Address = *(pIAPU->DirectPage + ((OP1 + pIAPU->X) & 0xff)) + \
+ (*(pIAPU->DirectPage + ((OP1 + pIAPU->X + 1) & 0xff)) << 8);
+#define Absolute()\
+ pIAPU->Address = OP1 + (OP2 << 8);
+
+#define AbsoluteX()\
+ pIAPU->Address = OP1 + (OP2 << 8) + pIAPU->X;
+
+#define AbsoluteY()\
+ pIAPU->Address = OP1 + (OP2 << 8) + pIAPU->YA.B.Y;
+
+#define MemBit()\
+ pIAPU->Address = OP1 + (OP2 << 8);\
+ pIAPU->Bit = (int8) (pIAPU->Address >> 13);\
+ pIAPU->Address &= 0x1fff;
+
+#define IndirectIndexedY()\
+ pIAPU->Address = *(pIAPU->DirectPage + OP1) + \
+ (*(pIAPU->DirectPage + OP1 + 1) << 8) + \
+ pIAPU->YA.B.Y;
+#endif
+
+void Apu00 ()
+{
+// NOP
+ pIAPU->PC++;
+}
+
+void Apu01 () { TCALL (0) }
+
+void Apu11 () { TCALL (1) }
+
+void Apu21 () { TCALL (2) }
+
+void Apu31 () { TCALL (3) }
+
+void Apu41 () { TCALL (4) }
+
+void Apu51 () { TCALL (5) }
+
+void Apu61 () { TCALL (6) }
+
+void Apu71 () { TCALL (7) }
+
+void Apu81 () { TCALL (8) }
+
+void Apu91 () { TCALL (9) }
+
+void ApuA1 () { TCALL (10) }
+
+void ApuB1 () { TCALL (11) }
+
+void ApuC1 () { TCALL (12) }
+
+void ApuD1 () { TCALL (13) }
+
+void ApuE1 () { TCALL (14) }
+
+void ApuF1 () { TCALL (15) }
+
+void Apu3F () // CALL absolute
+{
+ Absolute ();
+ // 0xB6f for Star Fox 2
+ PushW ((pIAPU->PC + 3 - pIAPU->RAM));
+ pIAPU->PC = pIAPU->RAM + pIAPU->Address;
+}
+
+void Apu4F () // PCALL $XX
+{
+ Work8 = OP1;
+ PushW ((pIAPU->PC + 2 - pIAPU->RAM));
+ pIAPU->PC = pIAPU->RAM + 0xff00 + Work8;
+}
+
+#define SET(b) \
+S9xAPUSetByteZ ((uint8) (S9xAPUGetByteZ (OP1 ) | (1 << (b))), OP1); \
+pIAPU->PC += 2
+
+void Apu02 ()
+{
+ SET (0);
+}
+
+void Apu22 ()
+{
+ SET (1);
+}
+
+void Apu42 ()
+{
+ SET (2);
+}
+
+void Apu62 ()
+{
+ SET (3);
+}
+
+void Apu82 ()
+{
+ SET (4);
+}
+
+void ApuA2 ()
+{
+ SET (5);
+}
+
+void ApuC2 ()
+{
+ SET (6);
+}
+
+void ApuE2 ()
+{
+ SET (7);
+}
+
+#define CLR(b) \
+S9xAPUSetByteZ ((uint8) (S9xAPUGetByteZ (OP1) & ~(1 << (b))), OP1); \
+pIAPU->PC += 2;
+
+void Apu12 ()
+{
+ CLR (0);
+}
+
+void Apu32 ()
+{
+ CLR (1);
+}
+
+void Apu52 ()
+{
+ CLR (2);
+}
+
+void Apu72 ()
+{
+ CLR (3);
+}
+
+void Apu92 ()
+{
+ CLR (4);
+}
+
+void ApuB2 ()
+{
+ CLR (5);
+}
+
+void ApuD2 ()
+{
+ CLR (6);
+}
+
+void ApuF2 ()
+{
+ CLR (7);
+}
+
+#define BBS(b) \
+Work8 = OP1; \
+Relative2 (); \
+if (S9xAPUGetByteZ (Work8) & (1 << (b))) \
+{ \
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16; \
+ CPU.APU_Cycles += pIAPU->TwoCycles; \
+} \
+else \
+ pIAPU->PC += 3
+
+void Apu03 ()
+{
+ BBS (0);
+}
+
+void Apu23 ()
+{
+ BBS (1);
+}
+
+void Apu43 ()
+{
+ BBS (2);
+}
+
+void Apu63 ()
+{
+ BBS (3);
+}
+
+void Apu83 ()
+{
+ BBS (4);
+}
+
+void ApuA3 ()
+{
+ BBS (5);
+}
+
+void ApuC3 ()
+{
+ BBS (6);
+}
+
+void ApuE3 ()
+{
+ BBS (7);
+}
+
+#define BBC(b) \
+Work8 = OP1; \
+Relative2 (); \
+if (!(S9xAPUGetByteZ (Work8) & (1 << (b)))) \
+{ \
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16; \
+ CPU.APU_Cycles += pIAPU->TwoCycles; \
+} \
+else \
+ pIAPU->PC += 3
+
+void Apu13 ()
+{
+ BBC (0);
+}
+
+void Apu33 ()
+{
+ BBC (1);
+}
+
+void Apu53 ()
+{
+ BBC (2);
+}
+
+void Apu73 ()
+{
+ BBC (3);
+}
+
+void Apu93 ()
+{
+ BBC (4);
+}
+
+void ApuB3 ()
+{
+ BBC (5);
+}
+
+void ApuD3 ()
+{
+ BBC (6);
+}
+
+void ApuF3 ()
+{
+ BBC (7);
+}
+
+void Apu04 ()
+{
+// OR A,dp
+ pIAPU->YA.B.A |= S9xAPUGetByteZ (OP1);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu05 ()
+{
+// OR A,abs
+ Absolute ();
+ pIAPU->YA.B.A |= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void Apu06 ()
+{
+// OR A,(X)
+ pIAPU->YA.B.A |= S9xAPUGetByteZ (pIAPU->X);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu07 ()
+{
+// OR A,(dp+X)
+ IndexedXIndirect ();
+ pIAPU->YA.B.A |= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu08 ()
+{
+// OR A,#00
+ pIAPU->YA.B.A |= OP1;
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu09 ()
+{
+// OR dp(dest),dp(src)
+ Work8 = S9xAPUGetByteZ (OP1);
+ Work8 |= S9xAPUGetByteZ (OP2);
+ S9xAPUSetByteZ (Work8, OP2);
+ APUSetZN8 (Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu14 ()
+{
+// OR A,dp+X
+ pIAPU->YA.B.A |= S9xAPUGetByteZ (OP1 + pIAPU->X);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu15 ()
+{
+// OR A,abs+X
+ AbsoluteX ();
+ pIAPU->YA.B.A |= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void Apu16 ()
+{
+// OR A,abs+Y
+ AbsoluteY ();
+ pIAPU->YA.B.A |= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void Apu17 ()
+{
+// OR A,(dp)+Y
+ IndirectIndexedY ();
+ pIAPU->YA.B.A |= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu18 ()
+{
+// OR dp,#00
+ Work8 = OP1;
+ Work8 |= S9xAPUGetByteZ (OP2);
+ S9xAPUSetByteZ (Work8, OP2);
+ APUSetZN8 (Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu19 ()
+{
+// OR (X),(Y)
+ Work8 = S9xAPUGetByteZ (pIAPU->X) | S9xAPUGetByteZ (pIAPU->YA.B.Y);
+ APUSetZN8 (Work8);
+ S9xAPUSetByteZ (Work8, pIAPU->X);
+ pIAPU->PC++;
+}
+
+void Apu0A ()
+{
+// OR1 C,membit
+ MemBit ();
+ if (!APUCheckCarry ())
+ {
+ if (S9xAPUGetByte (pIAPU->Address) & (1 << pIAPU->Bit))
+ APUSetCarry ();
+ }
+ pIAPU->PC += 3;
+}
+
+void Apu2A ()
+{
+// OR1 C,not membit
+ MemBit ();
+ if (!APUCheckCarry ())
+ {
+ if (!(S9xAPUGetByte (pIAPU->Address) & (1 << pIAPU->Bit)))
+ APUSetCarry ();
+ }
+ pIAPU->PC += 3;
+}
+
+void Apu4A ()
+{
+// AND1 C,membit
+ MemBit ();
+ if (APUCheckCarry ())
+ {
+ if (!(S9xAPUGetByte (pIAPU->Address) & (1 << pIAPU->Bit)))
+ APUClearCarry ();
+ }
+ pIAPU->PC += 3;
+}
+
+void Apu6A ()
+{
+// AND1 C, not membit
+ MemBit ();
+ if (APUCheckCarry ())
+ {
+ if ((S9xAPUGetByte (pIAPU->Address) & (1 << pIAPU->Bit)))
+ APUClearCarry ();
+ }
+ pIAPU->PC += 3;
+}
+
+void Apu8A ()
+{
+// EOR1 C, membit
+ MemBit ();
+ if (APUCheckCarry ())
+ {
+ if (S9xAPUGetByte (pIAPU->Address) & (1 << pIAPU->Bit))
+ APUClearCarry ();
+ }
+ else
+ {
+ if (S9xAPUGetByte (pIAPU->Address) & (1 << pIAPU->Bit))
+ APUSetCarry ();
+ }
+ pIAPU->PC += 3;
+}
+
+void ApuAA ()
+{
+// MOV1 C,membit
+ MemBit ();
+ if (S9xAPUGetByte (pIAPU->Address) & (1 << pIAPU->Bit))
+ APUSetCarry ();
+ else
+ APUClearCarry ();
+ pIAPU->PC += 3;
+}
+
+void ApuCA ()
+{
+// MOV1 membit,C
+ MemBit ();
+ if (APUCheckCarry ())
+ {
+ S9xAPUSetByte (S9xAPUGetByte (pIAPU->Address) | (1 << pIAPU->Bit), pIAPU->Address);
+ }
+ else
+ {
+ S9xAPUSetByte (S9xAPUGetByte (pIAPU->Address) & ~(1 << pIAPU->Bit), pIAPU->Address);
+ }
+ pIAPU->PC += 3;
+}
+
+void ApuEA ()
+{
+// NOT1 membit
+ MemBit ();
+ S9xAPUSetByte (S9xAPUGetByte (pIAPU->Address) ^ (1 << pIAPU->Bit), pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void Apu0B ()
+{
+// ASL dp
+ Work8 = S9xAPUGetByteZ (OP1);
+ ASL (Work8);
+ S9xAPUSetByteZ (Work8, OP1);
+ pIAPU->PC += 2;
+}
+
+void Apu0C ()
+{
+// ASL abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ ASL (Work8);
+ S9xAPUSetByte (Work8, pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void Apu1B ()
+{
+// ASL dp+X
+ Work8 = S9xAPUGetByteZ (OP1 + pIAPU->X);
+ ASL (Work8);
+ S9xAPUSetByteZ (Work8, OP1 + pIAPU->X);
+ pIAPU->PC += 2;
+}
+
+void Apu1C ()
+{
+// ASL A
+ ASL (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu0D ()
+{
+// PUSH PSW
+ S9xAPUPackStatus ();
+ Push (pIAPU->P);
+ pIAPU->PC++;
+}
+
+void Apu2D ()
+{
+// PUSH A
+ Push (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu4D ()
+{
+// PUSH X
+ Push (pIAPU->X);
+ pIAPU->PC++;
+}
+
+void Apu6D ()
+{
+// PUSH Y
+ Push (pIAPU->YA.B.Y);
+ pIAPU->PC++;
+}
+
+void Apu8E ()
+{
+// POP PSW
+ Pop (pIAPU->P);
+ S9xAPUUnpackStatus ();
+ if (APUCheckDirectPage ())
+ pIAPU->DirectPage = pIAPU->RAM + 0x100;
+ else
+ pIAPU->DirectPage = pIAPU->RAM;
+ pIAPU->PC++;
+}
+
+void ApuAE ()
+{
+// POP A
+ Pop (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void ApuCE ()
+{
+// POP X
+ Pop (pIAPU->X);
+ pIAPU->PC++;
+}
+
+void ApuEE ()
+{
+// POP Y
+ Pop (pIAPU->YA.B.Y);
+ pIAPU->PC++;
+}
+
+void Apu0E ()
+{
+// TSET1 abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ S9xAPUSetByte (Work8 | pIAPU->YA.B.A, pIAPU->Address);
+ Work8 &= pIAPU->YA.B.A;
+ APUSetZN8 (Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu4E ()
+{
+// TCLR1 abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ S9xAPUSetByte (Work8 & ~pIAPU->YA.B.A, pIAPU->Address);
+ Work8 &= pIAPU->YA.B.A;
+ APUSetZN8 (Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu0F ()
+{
+// BRK
+
+#if 0
+ STOP ("BRK");
+#else
+ PushW ((pIAPU->PC + 1 - pIAPU->RAM));
+ S9xAPUPackStatus ();
+ Push (pIAPU->P);
+ APUSetBreak ();
+ APUClearInterrupt ();
+// XXX:Where is the BRK vector ???
+ pIAPU->PC = pIAPU->RAM + APU.ExtraRAM[0x20] + (APU.ExtraRAM[0x21] << 8);
+#endif
+}
+
+void ApuEF ()
+{
+// SLEEP
+ // XXX: sleep
+ // STOP ("SLEEP");
+ CPU.APU_APUExecuting = FALSE;
+ pIAPU->PC++;
+}
+
+void ApuFF ()
+{
+// STOP
+ // STOP ("STOP");
+ CPU.APU_APUExecuting = FALSE;
+ pIAPU->PC++;
+}
+
+void Apu10 ()
+{
+// BPL
+ Relative ();
+ if (!APUCheckNegative ())
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ APUShutdown ();
+ }
+ else
+ pIAPU->PC += 2;
+}
+
+void Apu30 ()
+{
+// BMI
+ Relative ();
+ if (APUCheckNegative ())
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ APUShutdown ();
+ }
+ else
+ pIAPU->PC += 2;
+}
+
+void Apu90 ()
+{
+// BCC
+ Relative ();
+ if (!APUCheckCarry ())
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ APUShutdown ();
+ }
+ else
+ pIAPU->PC += 2;
+}
+
+void ApuB0 ()
+{
+// BCS
+ Relative ();
+ if (APUCheckCarry ())
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ APUShutdown ();
+ }
+ else
+ pIAPU->PC += 2;
+}
+
+void ApuD0 ()
+{
+// BNE
+ Relative ();
+ if (!APUCheckZero ())
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ APUShutdown ();
+ }
+ else
+ pIAPU->PC += 2;
+}
+
+void ApuF0 ()
+{
+// BEQ
+ Relative ();
+ if (APUCheckZero ())
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ APUShutdown ();
+ }
+ else
+ pIAPU->PC += 2;
+}
+
+void Apu50 ()
+{
+// BVC
+ Relative ();
+ if (!APUCheckOverflow ())
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ }
+ else
+ pIAPU->PC += 2;
+}
+
+void Apu70 ()
+{
+// BVS
+ Relative ();
+ if (APUCheckOverflow ())
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ }
+ else
+ pIAPU->PC += 2;
+}
+
+void Apu2F ()
+{
+// BRA
+ Relative ();
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+}
+
+void Apu80 ()
+{
+// SETC
+ APUSetCarry ();
+ pIAPU->PC++;
+}
+
+void ApuED ()
+{
+// NOTC
+ pIAPU->_Carry ^= 1;
+ pIAPU->PC++;
+}
+
+void Apu40 ()
+{
+// SETP
+ APUSetDirectPage ();
+ pIAPU->DirectPage = pIAPU->RAM + 0x100;
+ pIAPU->PC++;
+}
+
+void Apu1A ()
+{
+// DECW dp
+ Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8);
+ Work16--;
+ S9xAPUSetByteZ ((uint8) Work16, OP1);
+ S9xAPUSetByteZ (Work16 >> 8, OP1 + 1);
+ APUSetZN16 (Work16);
+ pIAPU->PC += 2;
+}
+
+void Apu5A ()
+{
+// CMPW YA,dp
+ Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8);
+ Int32 = (long) pIAPU->YA.W - (long) Work16;
+ pIAPU->_Carry = Int32 >= 0;
+ APUSetZN16 ((uint16) Int32);
+ pIAPU->PC += 2;
+}
+
+void Apu3A ()
+{
+// INCW dp
+ Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8);
+ Work16++;
+ S9xAPUSetByteZ ((uint8) Work16, OP1);
+ S9xAPUSetByteZ (Work16 >> 8, OP1 + 1);
+ APUSetZN16 (Work16);
+ pIAPU->PC += 2;
+}
+
+// XXX: HalfCarry - BJ Fixed? Or is it between bits 7 and 8 for ADDW/SUBW?
+void Apu7A ()
+{
+// ADDW YA,dp
+ Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8);
+ Work32 = (uint32) pIAPU->YA.W + Work16;
+ pIAPU->_Carry = Work32 >= 0x10000;
+ if (~(pIAPU->YA.W ^ Work16) & (Work16 ^ (uint16) Work32) & 0x8000)
+ APUSetOverflow ();
+ else
+ APUClearOverflow ();
+ APUClearHalfCarry ();
+ if((pIAPU->YA.W ^ Work16 ^ (uint16) Work32) & 0x10)
+ APUSetHalfCarry ();
+ pIAPU->YA.W = (uint16) Work32;
+ APUSetZN16 (pIAPU->YA.W);
+ pIAPU->PC += 2;
+}
+
+// XXX: BJ: i think the old HalfCarry behavior was wrong...
+// XXX: Or is it between bits 7 and 8 for ADDW/SUBW?
+void Apu9A ()
+{
+// SUBW YA,dp
+ Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8);
+ Int32 = (long) pIAPU->YA.W - (long) Work16;
+ APUClearHalfCarry ();
+ pIAPU->_Carry = Int32 >= 0;
+ if (((pIAPU->YA.W ^ Work16) & 0x8000) &&
+ ((pIAPU->YA.W ^ (uint16) Int32) & 0x8000))
+ APUSetOverflow ();
+ else
+ APUClearOverflow ();
+// if (((pIAPU->YA.W ^ Work16) & 0x0080) &&
+// ((pIAPU->YA.W ^ (uint16) Int32) & 0x0080))
+// APUSetHalfCarry (); // notaz: strange here
+ APUSetHalfCarry ();
+// if((pIAPU->YA.W ^ Work16 ^ (uint16) Work32) & 0x10) // notaz: Work32?!
+ if((pIAPU->YA.W ^ Work16 ^ (uint16) Int32) & 0x10)
+ APUClearHalfCarry ();
+ pIAPU->YA.W = (uint16) Int32;
+ APUSetZN16 (pIAPU->YA.W);
+ pIAPU->PC += 2;
+}
+
+void ApuBA ()
+{
+// MOVW YA,dp
+ pIAPU->YA.B.A = S9xAPUGetByteZ (OP1);
+ pIAPU->YA.B.Y = S9xAPUGetByteZ (OP1 + 1);
+ APUSetZN16 (pIAPU->YA.W);
+ pIAPU->PC += 2;
+}
+
+void ApuDA ()
+{
+// MOVW dp,YA
+ S9xAPUSetByteZ (pIAPU->YA.B.A, OP1);
+ S9xAPUSetByteZ (pIAPU->YA.B.Y, OP1 + 1);
+ pIAPU->PC += 2;
+}
+
+void Apu64 ()
+{
+// CMP A,dp
+ Work8 = S9xAPUGetByteZ (OP1);
+ CMP (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu65 ()
+{
+// CMP A,abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ CMP (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu66 ()
+{
+// CMP A,(X)
+ Work8 = S9xAPUGetByteZ (pIAPU->X);
+ CMP (pIAPU->YA.B.A, Work8);
+ pIAPU->PC++;
+}
+
+void Apu67 ()
+{
+// CMP A,(dp+X)
+ IndexedXIndirect ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ CMP (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu68 ()
+{
+// CMP A,#00
+ Work8 = OP1;
+ CMP (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu69 ()
+{
+// CMP dp(dest), dp(src)
+ W1 = S9xAPUGetByteZ (OP1);
+ Work8 = S9xAPUGetByteZ (OP2);
+ CMP (Work8, W1);
+ pIAPU->PC += 3;
+}
+
+void Apu74 ()
+{
+// CMP A, dp+X
+ Work8 = S9xAPUGetByteZ (OP1 + pIAPU->X);
+ CMP (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu75 ()
+{
+// CMP A,abs+X
+ AbsoluteX ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ CMP (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu76 ()
+{
+// CMP A, abs+Y
+ AbsoluteY ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ CMP (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu77 ()
+{
+// CMP A,(dp)+Y
+ IndirectIndexedY ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ CMP (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu78 ()
+{
+// CMP dp,#00
+ Work8 = OP1;
+ W1 = S9xAPUGetByteZ (OP2);
+ CMP (W1, Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu79 ()
+{
+// CMP (X),(Y)
+ W1 = S9xAPUGetByteZ (pIAPU->X);
+ Work8 = S9xAPUGetByteZ (pIAPU->YA.B.Y);
+ CMP (W1, Work8);
+ pIAPU->PC++;
+}
+
+void Apu1E ()
+{
+// CMP X,abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ CMP (pIAPU->X, Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu3E ()
+{
+// CMP X,dp
+ Work8 = S9xAPUGetByteZ (OP1);
+ CMP (pIAPU->X, Work8);
+ pIAPU->PC += 2;
+}
+
+void ApuC8 ()
+{
+// CMP X,#00
+ CMP (pIAPU->X, OP1);
+ pIAPU->PC += 2;
+}
+
+void Apu5E ()
+{
+// CMP Y,abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ CMP (pIAPU->YA.B.Y, Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu7E ()
+{
+// CMP Y,dp
+ Work8 = S9xAPUGetByteZ (OP1);
+ CMP (pIAPU->YA.B.Y, Work8);
+ pIAPU->PC += 2;
+}
+
+void ApuAD ()
+{
+// CMP Y,#00
+ Work8 = OP1;
+ CMP (pIAPU->YA.B.Y, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu1F ()
+{
+// JMP (abs+X)
+ Absolute ();
+ pIAPU->PC = pIAPU->RAM + S9xAPUGetByte (pIAPU->Address + pIAPU->X) +
+ (S9xAPUGetByte (pIAPU->Address + pIAPU->X + 1) << 8);
+// XXX: HERE:
+ // APU.Flags |= TRACE_FLAG;
+}
+
+void Apu5F ()
+{
+// JMP abs
+ Absolute ();
+ pIAPU->PC = pIAPU->RAM + pIAPU->Address;
+}
+
+void Apu20 ()
+{
+// CLRP
+ APUClearDirectPage ();
+ pIAPU->DirectPage = pIAPU->RAM;
+ pIAPU->PC++;
+}
+
+void Apu60 ()
+{
+// CLRC
+ APUClearCarry ();
+ pIAPU->PC++;
+}
+
+void ApuE0 ()
+{
+// CLRV
+ APUClearHalfCarry ();
+ APUClearOverflow ();
+ pIAPU->PC++;
+}
+
+void Apu24 ()
+{
+// AND A,dp
+ pIAPU->YA.B.A &= S9xAPUGetByteZ (OP1);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu25 ()
+{
+// AND A,abs
+ Absolute ();
+ pIAPU->YA.B.A &= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void Apu26 ()
+{
+// AND A,(X)
+ pIAPU->YA.B.A &= S9xAPUGetByteZ (pIAPU->X);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu27 ()
+{
+// AND A,(dp+X)
+ IndexedXIndirect ();
+ pIAPU->YA.B.A &= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu28 ()
+{
+// AND A,#00
+ pIAPU->YA.B.A &= OP1;
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu29 ()
+{
+// AND dp(dest),dp(src)
+ Work8 = S9xAPUGetByteZ (OP1);
+ Work8 &= S9xAPUGetByteZ (OP2);
+ S9xAPUSetByteZ (Work8, OP2);
+ APUSetZN8 (Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu34 ()
+{
+// AND A,dp+X
+ pIAPU->YA.B.A &= S9xAPUGetByteZ (OP1 + pIAPU->X);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu35 ()
+{
+// AND A,abs+X
+ AbsoluteX ();
+ pIAPU->YA.B.A &= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void Apu36 ()
+{
+// AND A,abs+Y
+ AbsoluteY ();
+ pIAPU->YA.B.A &= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void Apu37 ()
+{
+// AND A,(dp)+Y
+ IndirectIndexedY ();
+ pIAPU->YA.B.A &= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu38 ()
+{
+// AND dp,#00
+ Work8 = OP1;
+ Work8 &= S9xAPUGetByteZ (OP2);
+ S9xAPUSetByteZ (Work8, OP2);
+ APUSetZN8 (Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu39 ()
+{
+// AND (X),(Y)
+ Work8 = S9xAPUGetByteZ (pIAPU->X) & S9xAPUGetByteZ (pIAPU->YA.B.Y);
+ APUSetZN8 (Work8);
+ S9xAPUSetByteZ (Work8, pIAPU->X);
+ pIAPU->PC++;
+}
+
+void Apu2B ()
+{
+// ROL dp
+ Work8 = S9xAPUGetByteZ (OP1);
+ ROL (Work8);
+ S9xAPUSetByteZ (Work8, OP1);
+ pIAPU->PC += 2;
+}
+
+void Apu2C ()
+{
+// ROL abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ ROL (Work8);
+ S9xAPUSetByte (Work8, pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void Apu3B ()
+{
+// ROL dp+X
+ Work8 = S9xAPUGetByteZ (OP1 + pIAPU->X);
+ ROL (Work8);
+ S9xAPUSetByteZ (Work8, OP1 + pIAPU->X);
+ pIAPU->PC += 2;
+}
+
+void Apu3C ()
+{
+// ROL A
+ ROL (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu2E ()
+{
+// CBNE dp,rel
+ Work8 = OP1;
+ Relative2 ();
+
+ if (S9xAPUGetByteZ (Work8) != pIAPU->YA.B.A)
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ APUShutdown ();
+ }
+ else
+ pIAPU->PC += 3;
+}
+
+void ApuDE ()
+{
+// CBNE dp+X,rel
+ Work8 = OP1 + pIAPU->X;
+ Relative2 ();
+
+ if (S9xAPUGetByteZ (Work8) != pIAPU->YA.B.A)
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ APUShutdown ();
+ }
+ else
+ pIAPU->PC += 3;
+}
+
+void Apu3D ()
+{
+// INC X
+ pIAPU->X++;
+ APUSetZN8 (pIAPU->X);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC++;
+}
+
+void ApuFC ()
+{
+// INC Y
+ pIAPU->YA.B.Y++;
+ APUSetZN8 (pIAPU->YA.B.Y);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC++;
+}
+
+void Apu1D ()
+{
+// DEC X
+ pIAPU->X--;
+ APUSetZN8 (pIAPU->X);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC++;
+}
+
+void ApuDC ()
+{
+// DEC Y
+ pIAPU->YA.B.Y--;
+ APUSetZN8 (pIAPU->YA.B.Y);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC++;
+}
+
+void ApuAB ()
+{
+// INC dp
+ Work8 = S9xAPUGetByteZ (OP1) + 1;
+ S9xAPUSetByteZ (Work8, OP1);
+ APUSetZN8 (Work8);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC += 2;
+}
+
+void ApuAC ()
+{
+// INC abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address) + 1;
+ S9xAPUSetByte (Work8, pIAPU->Address);
+ APUSetZN8 (Work8);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC += 3;
+}
+
+void ApuBB ()
+{
+// INC dp+X
+ Work8 = S9xAPUGetByteZ (OP1 + pIAPU->X) + 1;
+ S9xAPUSetByteZ (Work8, OP1 + pIAPU->X);
+ APUSetZN8 (Work8);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC += 2;
+}
+
+void ApuBC ()
+{
+// INC A
+ pIAPU->YA.B.A++;
+ APUSetZN8 (pIAPU->YA.B.A);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC++;
+}
+
+void Apu8B ()
+{
+// DEC dp
+ Work8 = S9xAPUGetByteZ (OP1) - 1;
+ S9xAPUSetByteZ (Work8, OP1);
+ APUSetZN8 (Work8);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC += 2;
+}
+
+void Apu8C ()
+{
+// DEC abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address) - 1;
+ S9xAPUSetByte (Work8, pIAPU->Address);
+ APUSetZN8 (Work8);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC += 3;
+}
+
+void Apu9B ()
+{
+// DEC dp+X
+ Work8 = S9xAPUGetByteZ (OP1 + pIAPU->X) - 1;
+ S9xAPUSetByteZ (Work8, OP1 + pIAPU->X);
+ APUSetZN8 (Work8);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC += 2;
+}
+
+void Apu9C ()
+{
+// DEC A
+ pIAPU->YA.B.A--;
+ APUSetZN8 (pIAPU->YA.B.A);
+
+#ifdef SPC700_SHUTDOWN
+ pIAPU->WaitCounter++;
+#endif
+
+ pIAPU->PC++;
+}
+
+void Apu44 ()
+{
+// EOR A,dp
+ pIAPU->YA.B.A ^= S9xAPUGetByteZ (OP1);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu45 ()
+{
+// EOR A,abs
+ Absolute ();
+ pIAPU->YA.B.A ^= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void Apu46 ()
+{
+// EOR A,(X)
+ pIAPU->YA.B.A ^= S9xAPUGetByteZ (pIAPU->X);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu47 ()
+{
+// EOR A,(dp+X)
+ IndexedXIndirect ();
+ pIAPU->YA.B.A ^= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu48 ()
+{
+// EOR A,#00
+ pIAPU->YA.B.A ^= OP1;
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu49 ()
+{
+// EOR dp(dest),dp(src)
+ Work8 = S9xAPUGetByteZ (OP1);
+ Work8 ^= S9xAPUGetByteZ (OP2);
+ S9xAPUSetByteZ (Work8, OP2);
+ APUSetZN8 (Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu54 ()
+{
+// EOR A,dp+X
+ pIAPU->YA.B.A ^= S9xAPUGetByteZ (OP1 + pIAPU->X);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu55 ()
+{
+// EOR A,abs+X
+ AbsoluteX ();
+ pIAPU->YA.B.A ^= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void Apu56 ()
+{
+// EOR A,abs+Y
+ AbsoluteY ();
+ pIAPU->YA.B.A ^= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void Apu57 ()
+{
+// EOR A,(dp)+Y
+ IndirectIndexedY ();
+ pIAPU->YA.B.A ^= S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void Apu58 ()
+{
+// EOR dp,#00
+ Work8 = OP1;
+ Work8 ^= S9xAPUGetByteZ (OP2);
+ S9xAPUSetByteZ (Work8, OP2);
+ APUSetZN8 (Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu59 ()
+{
+// EOR (X),(Y)
+ Work8 = S9xAPUGetByteZ (pIAPU->X) ^ S9xAPUGetByteZ (pIAPU->YA.B.Y);
+ APUSetZN8 (Work8);
+ S9xAPUSetByteZ (Work8, pIAPU->X);
+ pIAPU->PC++;
+}
+
+void Apu4B ()
+{
+// LSR dp
+ Work8 = S9xAPUGetByteZ (OP1);
+ LSR (Work8);
+ S9xAPUSetByteZ (Work8, OP1);
+ pIAPU->PC += 2;
+}
+
+void Apu4C ()
+{
+// LSR abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ LSR (Work8);
+ S9xAPUSetByte (Work8, pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void Apu5B ()
+{
+// LSR dp+X
+ Work8 = S9xAPUGetByteZ (OP1 + pIAPU->X);
+ LSR (Work8);
+ S9xAPUSetByteZ (Work8, OP1 + pIAPU->X);
+ pIAPU->PC += 2;
+}
+
+void Apu5C ()
+{
+// LSR A
+ LSR (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu7D ()
+{
+// MOV A,X
+ pIAPU->YA.B.A = pIAPU->X;
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void ApuDD ()
+{
+// MOV A,Y
+ pIAPU->YA.B.A = pIAPU->YA.B.Y;
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu5D ()
+{
+// MOV X,A
+ pIAPU->X = pIAPU->YA.B.A;
+ APUSetZN8 (pIAPU->X);
+ pIAPU->PC++;
+}
+
+void ApuFD ()
+{
+// MOV Y,A
+ pIAPU->YA.B.Y = pIAPU->YA.B.A;
+ APUSetZN8 (pIAPU->YA.B.Y);
+ pIAPU->PC++;
+}
+
+void Apu9D ()
+{
+//MOV X,SP
+ pIAPU->X = pIAPU->S;
+ APUSetZN8 (pIAPU->X);
+ pIAPU->PC++;
+}
+
+void ApuBD ()
+{
+// MOV SP,X
+ pIAPU->S = pIAPU->X;
+ pIAPU->PC++;
+}
+
+void Apu6B ()
+{
+// ROR dp
+ Work8 = S9xAPUGetByteZ (OP1);
+ ROR (Work8);
+ S9xAPUSetByteZ (Work8, OP1);
+ pIAPU->PC += 2;
+}
+
+void Apu6C ()
+{
+// ROR abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ ROR (Work8);
+ S9xAPUSetByte (Work8, pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void Apu7B ()
+{
+// ROR dp+X
+ Work8 = S9xAPUGetByteZ (OP1 + pIAPU->X);
+ ROR (Work8);
+ S9xAPUSetByteZ (Work8, OP1 + pIAPU->X);
+ pIAPU->PC += 2;
+}
+
+void Apu7C ()
+{
+// ROR A
+ ROR (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu6E ()
+{
+// DBNZ dp,rel
+ Work8 = OP1;
+ Relative2 ();
+ W1 = S9xAPUGetByteZ (Work8) - 1;
+ S9xAPUSetByteZ (W1, Work8);
+ if (W1 != 0)
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ }
+ else
+ pIAPU->PC += 3;
+}
+
+void ApuFE ()
+{
+// DBNZ Y,rel
+ Relative ();
+ pIAPU->YA.B.Y--;
+ if (pIAPU->YA.B.Y != 0)
+ {
+ pIAPU->PC = pIAPU->RAM + (uint16) Int16;
+ CPU.APU_Cycles += pIAPU->TwoCycles;
+ }
+ else
+ pIAPU->PC += 2;
+}
+
+void Apu6F ()
+{
+// RET
+ PopW (Work16);
+ pIAPU->PC = pIAPU->RAM + Work16;
+}
+
+void Apu7F ()
+{
+// RETI
+ // STOP ("RETI");
+ Pop (pIAPU->P);
+ S9xAPUUnpackStatus ();
+ PopW (Work16);
+ pIAPU->PC = pIAPU->RAM + Work16;
+}
+
+void Apu84 ()
+{
+// ADC A,dp
+ Work8 = S9xAPUGetByteZ (OP1);
+ ADC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu85 ()
+{
+// ADC A, abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ ADC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu86 ()
+{
+// ADC A,(X)
+ Work8 = S9xAPUGetByteZ (pIAPU->X);
+ ADC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC++;
+}
+
+void Apu87 ()
+{
+// ADC A,(dp+X)
+ IndexedXIndirect ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ ADC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu88 ()
+{
+// ADC A,#00
+ Work8 = OP1;
+ ADC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu89 ()
+{
+// ADC dp(dest),dp(src)
+ Work8 = S9xAPUGetByteZ (OP1);
+ W1 = S9xAPUGetByteZ (OP2);
+ ADC (W1, Work8);
+ S9xAPUSetByteZ (W1, OP2);
+ pIAPU->PC += 3;
+}
+
+void Apu94 ()
+{
+// ADC A,dp+X
+ Work8 = S9xAPUGetByteZ (OP1 + pIAPU->X);
+ ADC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu95 ()
+{
+// ADC A, abs+X
+ AbsoluteX ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ ADC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu96 ()
+{
+// ADC A, abs+Y
+ AbsoluteY ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ ADC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 3;
+}
+
+void Apu97 ()
+{
+// ADC A, (dp)+Y
+ IndirectIndexedY ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ ADC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void Apu98 ()
+{
+// ADC dp,#00
+ Work8 = OP1;
+ W1 = S9xAPUGetByteZ (OP2);
+ ADC (W1, Work8);
+ S9xAPUSetByteZ (W1, OP2);
+ pIAPU->PC += 3;
+}
+
+void Apu99 ()
+{
+// ADC (X),(Y)
+ W1 = S9xAPUGetByteZ (pIAPU->X);
+ Work8 = S9xAPUGetByteZ (pIAPU->YA.B.Y);
+ ADC (W1, Work8);
+ S9xAPUSetByteZ (W1, pIAPU->X);
+ pIAPU->PC++;
+}
+
+void Apu8D ()
+{
+// MOV Y,#00
+ pIAPU->YA.B.Y = OP1;
+ APUSetZN8 (pIAPU->YA.B.Y);
+ pIAPU->PC += 2;
+}
+
+void Apu8F ()
+{
+// MOV dp,#00
+ Work8 = OP1;
+ S9xAPUSetByteZ (Work8, OP2);
+ pIAPU->PC += 3;
+}
+
+void Apu9E ()
+{
+// DIV YA,X
+ if (pIAPU->X == 0)
+ {
+ APUSetOverflow ();
+ pIAPU->YA.B.Y = 0xff;
+ pIAPU->YA.B.A = 0xff;
+ }
+ else
+ {
+ APUClearOverflow ();
+ Work8 = pIAPU->YA.W / pIAPU->X;
+ pIAPU->YA.B.Y = pIAPU->YA.W % pIAPU->X;
+ pIAPU->YA.B.A = Work8;
+ }
+// XXX How should Overflow, Half Carry, Zero and Negative flags be set??
+ // APUSetZN16 (pIAPU->YA.W);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void Apu9F ()
+{
+// XCN A
+ pIAPU->YA.B.A = (pIAPU->YA.B.A >> 4) | (pIAPU->YA.B.A << 4);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void ApuA4 ()
+{
+// SBC A, dp
+ Work8 = S9xAPUGetByteZ (OP1);
+ SBC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void ApuA5 ()
+{
+// SBC A, abs
+ Absolute ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ SBC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 3;
+}
+
+void ApuA6 ()
+{
+// SBC A, (X)
+ Work8 = S9xAPUGetByteZ (pIAPU->X);
+ SBC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC++;
+}
+
+void ApuA7 ()
+{
+// SBC A,(dp+X)
+ IndexedXIndirect ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ SBC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void ApuA8 ()
+{
+// SBC A,#00
+ Work8 = OP1;
+ SBC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void ApuA9 ()
+{
+// SBC dp(dest), dp(src)
+ Work8 = S9xAPUGetByteZ (OP1);
+ W1 = S9xAPUGetByteZ (OP2);
+ SBC (W1, Work8);
+ S9xAPUSetByteZ (W1, OP2);
+ pIAPU->PC += 3;
+}
+
+void ApuB4 ()
+{
+// SBC A, dp+X
+ Work8 = S9xAPUGetByteZ (OP1 + pIAPU->X);
+ SBC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void ApuB5 ()
+{
+// SBC A,abs+X
+ AbsoluteX ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ SBC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 3;
+}
+
+void ApuB6 ()
+{
+// SBC A,abs+Y
+ AbsoluteY ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ SBC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 3;
+}
+
+void ApuB7 ()
+{
+// SBC A,(dp)+Y
+ IndirectIndexedY ();
+ Work8 = S9xAPUGetByte (pIAPU->Address);
+ SBC (pIAPU->YA.B.A, Work8);
+ pIAPU->PC += 2;
+}
+
+void ApuB8 ()
+{
+// SBC dp,#00
+ Work8 = OP1;
+ W1 = S9xAPUGetByteZ (OP2);
+ SBC (W1, Work8);
+ S9xAPUSetByteZ (W1, OP2);
+ pIAPU->PC += 3;
+}
+
+void ApuB9 ()
+{
+// SBC (X),(Y)
+ W1 = S9xAPUGetByteZ (pIAPU->X);
+ Work8 = S9xAPUGetByteZ (pIAPU->YA.B.Y);
+ SBC (W1, Work8);
+ S9xAPUSetByteZ (W1, pIAPU->X);
+ pIAPU->PC++;
+}
+
+void ApuAF ()
+{
+// MOV (X)+, A
+ S9xAPUSetByteZ (pIAPU->YA.B.A, pIAPU->X++);
+ pIAPU->PC++;
+}
+
+void ApuBE ()
+{
+// DAS
+ if ((pIAPU->YA.B.A & 0x0f) > 9 || !APUCheckHalfCarry())
+ {
+ pIAPU->YA.B.A -= 6;
+ }
+ if (pIAPU->YA.B.A > 0x9f || !pIAPU->_Carry)
+ {
+ pIAPU->YA.B.A -= 0x60;
+ APUClearCarry ();
+ }
+ else { APUSetCarry (); }
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void ApuBF ()
+{
+// MOV A,(X)+
+ pIAPU->YA.B.A = S9xAPUGetByteZ (pIAPU->X++);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void ApuC0 ()
+{
+// DI
+ APUClearInterrupt ();
+ pIAPU->PC++;
+}
+
+void ApuA0 ()
+{
+// EI
+ APUSetInterrupt ();
+ pIAPU->PC++;
+}
+
+void ApuC4 ()
+{
+// MOV dp,A
+ S9xAPUSetByteZ (pIAPU->YA.B.A, OP1);
+ pIAPU->PC += 2;
+}
+
+void ApuC5 ()
+{
+// MOV abs,A
+ Absolute ();
+ S9xAPUSetByte (pIAPU->YA.B.A, pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void ApuC6 ()
+{
+// MOV (X), A
+ S9xAPUSetByteZ (pIAPU->YA.B.A, pIAPU->X);
+ pIAPU->PC++;
+}
+
+void ApuC7 ()
+{
+// MOV (dp+X),A
+ IndexedXIndirect ();
+ S9xAPUSetByte (pIAPU->YA.B.A, pIAPU->Address);
+ pIAPU->PC += 2;
+}
+
+void ApuC9 ()
+{
+// MOV abs,X
+ Absolute ();
+ S9xAPUSetByte (pIAPU->X, pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void ApuCB ()
+{
+// MOV dp,Y
+ S9xAPUSetByteZ (pIAPU->YA.B.Y, OP1);
+ pIAPU->PC += 2;
+}
+
+void ApuCC ()
+{
+// MOV abs,Y
+ Absolute ();
+ S9xAPUSetByte (pIAPU->YA.B.Y, pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void ApuCD ()
+{
+// MOV X,#00
+ pIAPU->X = OP1;
+ APUSetZN8 (pIAPU->X);
+ pIAPU->PC += 2;
+}
+
+void ApuCF ()
+{
+// MUL YA
+ pIAPU->YA.W = (uint16) pIAPU->YA.B.A * pIAPU->YA.B.Y;
+ APUSetZN16 (pIAPU->YA.W);
+ pIAPU->PC++;
+}
+
+void ApuD4 ()
+{
+// MOV dp+X, A
+ S9xAPUSetByteZ (pIAPU->YA.B.A, OP1 + pIAPU->X);
+ pIAPU->PC += 2;
+}
+
+void ApuD5 ()
+{
+// MOV abs+X,A
+ AbsoluteX ();
+ S9xAPUSetByte (pIAPU->YA.B.A, pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void ApuD6 ()
+{
+// MOV abs+Y,A
+ AbsoluteY ();
+ S9xAPUSetByte (pIAPU->YA.B.A, pIAPU->Address);
+ pIAPU->PC += 3;
+}
+
+void ApuD7 ()
+{
+// MOV (dp)+Y,A
+ IndirectIndexedY ();
+ S9xAPUSetByte (pIAPU->YA.B.A, pIAPU->Address);
+ pIAPU->PC += 2;
+}
+
+void ApuD8 ()
+{
+// MOV dp,X
+ S9xAPUSetByteZ (pIAPU->X, OP1);
+ pIAPU->PC += 2;
+}
+
+void ApuD9 ()
+{
+// MOV dp+Y,X
+ S9xAPUSetByteZ (pIAPU->X, OP1 + pIAPU->YA.B.Y);
+ pIAPU->PC += 2;
+}
+
+void ApuDB ()
+{
+// MOV dp+X,Y
+ S9xAPUSetByteZ (pIAPU->YA.B.Y, OP1 + pIAPU->X);
+ pIAPU->PC += 2;
+}
+
+void ApuDF ()
+{
+// DAA
+ if ((pIAPU->YA.B.A & 0x0f) > 9 || APUCheckHalfCarry())
+ {
+ if(pIAPU->YA.B.A > 0xf0) APUSetCarry ();
+ pIAPU->YA.B.A += 6;
+ //APUSetHalfCarry (); Intel procs do this, but this is a Sony proc...
+ }
+ //else { APUClearHalfCarry (); } ditto as above
+ if (pIAPU->YA.B.A > 0x9f || pIAPU->_Carry)
+ {
+ pIAPU->YA.B.A += 0x60;
+ APUSetCarry ();
+ }
+ else { APUClearCarry (); }
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void ApuE4 ()
+{
+// MOV A, dp
+ pIAPU->YA.B.A = S9xAPUGetByteZ (OP1);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void ApuE5 ()
+{
+// MOV A,abs
+ Absolute ();
+ pIAPU->YA.B.A = S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void ApuE6 ()
+{
+// MOV A,(X)
+ pIAPU->YA.B.A = S9xAPUGetByteZ (pIAPU->X);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC++;
+}
+
+void ApuE7 ()
+{
+// MOV A,(dp+X)
+ IndexedXIndirect ();
+ pIAPU->YA.B.A = S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void ApuE8 ()
+{
+// MOV A,#00
+ pIAPU->YA.B.A = OP1;
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void ApuE9 ()
+{
+// MOV X, abs
+ Absolute ();
+ pIAPU->X = S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->X);
+ pIAPU->PC += 3;
+}
+
+void ApuEB ()
+{
+// MOV Y,dp
+ pIAPU->YA.B.Y = S9xAPUGetByteZ (OP1);
+ APUSetZN8 (pIAPU->YA.B.Y);
+ pIAPU->PC += 2;
+}
+
+void ApuEC ()
+{
+// MOV Y,abs
+ Absolute ();
+ pIAPU->YA.B.Y = S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.Y);
+ pIAPU->PC += 3;
+}
+
+void ApuF4 ()
+{
+// MOV A, dp+X
+ pIAPU->YA.B.A = S9xAPUGetByteZ (OP1 + pIAPU->X);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void ApuF5 ()
+{
+// MOV A, abs+X
+ AbsoluteX ();
+ pIAPU->YA.B.A = S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void ApuF6 ()
+{
+// MOV A, abs+Y
+ AbsoluteY ();
+ pIAPU->YA.B.A = S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 3;
+}
+
+void ApuF7 ()
+{
+// MOV A, (dp)+Y
+ IndirectIndexedY ();
+ pIAPU->YA.B.A = S9xAPUGetByte (pIAPU->Address);
+ APUSetZN8 (pIAPU->YA.B.A);
+ pIAPU->PC += 2;
+}
+
+void ApuF8 ()
+{
+// MOV X,dp
+ pIAPU->X = S9xAPUGetByteZ (OP1);
+ APUSetZN8 (pIAPU->X);
+ pIAPU->PC += 2;
+}
+
+void ApuF9 ()
+{
+// MOV X,dp+Y
+ pIAPU->X = S9xAPUGetByteZ (OP1 + pIAPU->YA.B.Y);
+ APUSetZN8 (pIAPU->X);
+ pIAPU->PC += 2;
+}
+
+void ApuFA ()
+{
+// MOV dp(dest),dp(src)
+ S9xAPUSetByteZ (S9xAPUGetByteZ (OP1), OP2);
+ pIAPU->PC += 3;
+}
+
+void ApuFB ()
+{
+// MOV Y,dp+X
+ pIAPU->YA.B.Y = S9xAPUGetByteZ (OP1 + pIAPU->X);
+ APUSetZN8 (pIAPU->YA.B.Y);
+ pIAPU->PC += 2;
+}
+
+//#if defined(ASM_SPC700)
+#undef INLINE
+#define INLINE extern "C"
+#include "apumem.h"
+/*
+#elif defined(NO_INLINE_SET_GET)
+#undef INLINE
+#define INLINE
+#include "apumem.h"
+#endif
+*/
+
+void (*S9xApuOpcodes[256]) (void) =
+{
+ Apu00, Apu01, Apu02, Apu03, Apu04, Apu05, Apu06, Apu07,
+ Apu08, Apu09, Apu0A, Apu0B, Apu0C, Apu0D, Apu0E, Apu0F,
+ Apu10, Apu11, Apu12, Apu13, Apu14, Apu15, Apu16, Apu17,
+ Apu18, Apu19, Apu1A, Apu1B, Apu1C, Apu1D, Apu1E, Apu1F,
+ Apu20, Apu21, Apu22, Apu23, Apu24, Apu25, Apu26, Apu27,
+ Apu28, Apu29, Apu2A, Apu2B, Apu2C, Apu2D, Apu2E, Apu2F,
+ Apu30, Apu31, Apu32, Apu33, Apu34, Apu35, Apu36, Apu37,
+ Apu38, Apu39, Apu3A, Apu3B, Apu3C, Apu3D, Apu3E, Apu3F,
+ Apu40, Apu41, Apu42, Apu43, Apu44, Apu45, Apu46, Apu47,
+ Apu48, Apu49, Apu4A, Apu4B, Apu4C, Apu4D, Apu4E, Apu4F,
+ Apu50, Apu51, Apu52, Apu53, Apu54, Apu55, Apu56, Apu57,
+ Apu58, Apu59, Apu5A, Apu5B, Apu5C, Apu5D, Apu5E, Apu5F,
+ Apu60, Apu61, Apu62, Apu63, Apu64, Apu65, Apu66, Apu67,
+ Apu68, Apu69, Apu6A, Apu6B, Apu6C, Apu6D, Apu6E, Apu6F,
+ Apu70, Apu71, Apu72, Apu73, Apu74, Apu75, Apu76, Apu77,
+ Apu78, Apu79, Apu7A, Apu7B, Apu7C, Apu7D, Apu7E, Apu7F,
+ Apu80, Apu81, Apu82, Apu83, Apu84, Apu85, Apu86, Apu87,
+ Apu88, Apu89, Apu8A, Apu8B, Apu8C, Apu8D, Apu8E, Apu8F,
+ Apu90, Apu91, Apu92, Apu93, Apu94, Apu95, Apu96, Apu97,
+ Apu98, Apu99, Apu9A, Apu9B, Apu9C, Apu9D, Apu9E, Apu9F,
+ ApuA0, ApuA1, ApuA2, ApuA3, ApuA4, ApuA5, ApuA6, ApuA7,
+ ApuA8, ApuA9, ApuAA, ApuAB, ApuAC, ApuAD, ApuAE, ApuAF,
+ ApuB0, ApuB1, ApuB2, ApuB3, ApuB4, ApuB5, ApuB6, ApuB7,
+ ApuB8, ApuB9, ApuBA, ApuBB, ApuBC, ApuBD, ApuBE, ApuBF,
+ ApuC0, ApuC1, ApuC2, ApuC3, ApuC4, ApuC5, ApuC6, ApuC7,
+ ApuC8, ApuC9, ApuCA, ApuCB, ApuCC, ApuCD, ApuCE, ApuCF,
+ ApuD0, ApuD1, ApuD2, ApuD3, ApuD4, ApuD5, ApuD6, ApuD7,
+ ApuD8, ApuD9, ApuDA, ApuDB, ApuDC, ApuDD, ApuDE, ApuDF,
+ ApuE0, ApuE1, ApuE2, ApuE3, ApuE4, ApuE5, ApuE6, ApuE7,
+ ApuE8, ApuE9, ApuEA, ApuEB, ApuEC, ApuED, ApuEE, ApuEF,
+ ApuF0, ApuF1, ApuF2, ApuF3, ApuF4, ApuF5, ApuF6, ApuF7,
+ ApuF8, ApuF9, ApuFA, ApuFB, ApuFC, ApuFD, ApuFE, ApuFF
+};
+
+
+struct SIAPU IAPU2;
+struct SIAPU *pIAPU;
+
+void APUCompare()
+{
+ IAPU.icount++;
+
+ if(IAPU.PC != IAPU2.PC) {
+ dprintf("!%02X %5i PC %08X vs %08X", IAPU.opcode, IAPU.icount, IAPU.PC, IAPU2.PC);
+ exit(1);
+ }
+
+ if(IAPU.YA.W != IAPU2.YA.W) {
+ dprintf("!%02X %5i YA %04X vs %04X", IAPU.opcode, IAPU.icount, IAPU.YA.W, IAPU2.YA.W);
+ dprintf(" (%04X / %02X)", IAPU.ya_prev, IAPU.x_prev);
+ exit(1);
+ }
+
+ if((IAPU.P&0x7d) != (IAPU2.P&0x7d)) {
+ dprintf("!%02X %5i P %02X vs %02X", IAPU.opcode, IAPU.icount, IAPU.P, IAPU2.P);
+ exit(1);
+ }
+
+ if(IAPU.X != IAPU2.X) {
+ dprintf("!%02X %5i X %02X vs %02X", IAPU.opcode, IAPU.icount, IAPU.X, IAPU2.X);
+ exit(1);
+ }
+
+ if(IAPU.S != IAPU2.S) {
+ dprintf("!%02X %5i S %02X vs %02X", IAPU.opcode, IAPU.icount, IAPU.S, IAPU2.S);
+ exit(1);
+ }
+
+ if((IAPU._Zero == 0) != (IAPU2._Zero == 0)) {
+ dprintf("!%02X %5i _Zero %02X vs %02X", IAPU.opcode, IAPU.icount, IAPU._Zero, IAPU2._Zero);
+ exit(1);
+ }
+
+ if((IAPU._Zero & 0x80) != (IAPU2._Zero & 0x80)) {
+ dprintf("!%02X %5i _Zero(n) %02X vs %02X", IAPU.opcode, IAPU.icount, IAPU._Zero, IAPU2._Zero);
+ exit(1);
+ }
+
+ if(IAPU.memread_addr != IAPU2.memread_addr) {
+ dprintf("!%02X %5i memread_addr %04X vs %04X", IAPU.opcode, IAPU.icount, IAPU.memread_addr, IAPU2.memread_addr);
+ exit(1);
+ }
+
+ if(IAPU.memread_data != IAPU2.memread_data) {
+ dprintf("!%02X %5i memread_data %02X@%04X vs %02X@%04X", IAPU.opcode, IAPU.icount, IAPU.memread_data, IAPU.memread_addr, IAPU2.memread_data, IAPU2.memread_addr);
+ exit(1);
+ }
+
+ if(IAPU.memwrite_addr != IAPU2.memwrite_addr) {
+ dprintf("!%02X %5i memwrite_addr %04X vs %04X", IAPU.opcode, IAPU.icount, IAPU.memwrite_addr, IAPU2.memwrite_addr);
+ exit(1);
+ }
+
+ if(IAPU.memwrite_data != IAPU2.memwrite_data) {
+ dprintf("!%02X %5i memwrite_data %02X@%04X vs %02X@%04X", IAPU.opcode, IAPU.icount, IAPU.memwrite_data, IAPU.memwrite_addr, IAPU2.memwrite_data, IAPU2.memwrite_addr);
+ exit(1);
+ }
+}
+
+
diff --git a/src/spc700/debug/spc700.h b/src/spc700/debug/spc700.h
new file mode 100644
index 0000000..507c247
--- /dev/null
+++ b/src/spc700/debug/spc700.h
@@ -0,0 +1,172 @@
+/*
+ * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
+ *
+ * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
+ * Jerremy Koot (jkoot@snes9x.com)
+ *
+ * Super FX C emulator code
+ * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
+ * Gary Henderson.
+ * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
+ *
+ * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
+ * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
+ * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
+ *
+ * DOS port code contains the works of other authors. See headers in
+ * individual files.
+ *
+ * Snes9x homepage: http://www.snes9x.com
+ *
+ * Permission to use, copy, modify and distribute Snes9x in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Snes9x is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Snes9x or software derived from Snes9x.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so everyone can benefit from the modifications
+ * in future versions.
+ *
+ * Super NES and Super Nintendo Entertainment System are trademarks of
+ * Nintendo Co., Limited and its subsidiary companies.
+ */
+#ifndef _SPC700_H_
+#define _SPC700_H_
+
+#ifdef SPCTOOL
+#define NO_CHANNEL_STRUCT
+#include "spctool/dsp.h"
+#include "spctool/spc700.h"
+#include "spctool/soundmod.h"
+#endif
+
+
+#define Carry 1
+#define Zero 2
+#define Interrupt 4
+#define HalfCarry 8
+#define BreakFlag 16
+#define DirectPageFlag 32
+#define Overflow 64
+#define Negative 128
+
+#define APUClearCarry() (pIAPU->_Carry = 0)
+#define APUSetCarry() (pIAPU->_Carry = 1)
+#define APUSetInterrupt() (pIAPU->P |= Interrupt)
+#define APUClearInterrupt() (pIAPU->P &= ~Interrupt)
+#define APUSetHalfCarry() (pIAPU->P |= HalfCarry)
+#define APUClearHalfCarry() (pIAPU->P &= ~HalfCarry)
+#define APUSetBreak() (pIAPU->P |= BreakFlag)
+#define APUClearBreak() (pIAPU->P &= ~BreakFlag)
+#define APUSetDirectPage() (pIAPU->P |= DirectPageFlag)
+#define APUClearDirectPage() (pIAPU->P &= ~DirectPageFlag)
+#define APUSetOverflow() (pIAPU->_Overflow = 1)
+#define APUClearOverflow() (pIAPU->_Overflow = 0)
+
+#define APUCheckZero() (pIAPU->_Zero == 0)
+#define APUCheckCarry() (pIAPU->_Carry)
+#define APUCheckInterrupt() (pIAPU->P & Interrupt)
+#define APUCheckHalfCarry() (pIAPU->P & HalfCarry)
+#define APUCheckBreak() (pIAPU->P & BreakFlag)
+#define APUCheckDirectPage() (pIAPU->P & DirectPageFlag)
+#define APUCheckOverflow() (pIAPU->_Overflow)
+#define APUCheckNegative() (pIAPU->_Zero & 0x80)
+
+//#define APUClearFlags(f) (IAPU.P &= ~(f))
+//#define APUSetFlags(f) (IAPU.P |= (f))
+//#define APUCheckFlag(f) (IAPU.P & (f))
+
+typedef union
+{
+#ifdef LSB_FIRST
+ struct { uint8 A, Y; } B;
+#else
+ struct { uint8 Y, A; } B;
+#endif
+ uint16 W;
+ uint32 _padder; // make sure this whole thing takes 4 bytes
+} YAndA;
+
+struct SAPURegisters{
+ uint8 P;
+ YAndA YA;
+ uint8 X;
+ uint8 S;
+ uint16 PC;
+};
+
+//EXTERN_C struct SAPURegisters APURegisters;
+
+// Needed by ILLUSION OF GAIA
+//#define ONE_APU_CYCLE 14
+#define ONE_APU_CYCLE 21
+
+// Needed by all games written by the software company called Human
+//#define ONE_APU_CYCLE_HUMAN 17
+#define ONE_APU_CYCLE_HUMAN 21
+
+// 1.953us := 1.024065.54MHz
+
+// return cycles left (always negative)
+extern "C" int spc700_execute(int cycles);
+extern "C" uint32 Spc700JumpTab;
+
+#ifdef SPCTOOL
+EXTERN_C int32 ESPC (int32);
+
+#define APU_EXECUTE() \
+{ \
+ int32 l = (CPU.Cycles - CPU.APU_Cycles) / 14; \
+ if (l > 0) \
+ { \
+ l -= _EmuSPC(l); \
+ CPU.APU_Cycles += l * 14; \
+ } \
+}
+
+#else
+
+#ifdef DEBUGGER
+#define APU_EXECUTE1() \
+{ \
+ if (APU.Flags & TRACE_FLAG) \
+ S9xTraceAPU ();\
+ CPU.APU_Cycles += S9xAPUCycles [*IAPU.PC]; \
+ (*S9xApuOpcodes[*IAPU.PC]) (); \
+}
+#else
+#define APU_EXECUTE1() \
+{ \
+ IAPU.asmJumpTab = &Spc700JumpTab; \
+ memcpy(&IAPU2, &IAPU, sizeof(IAPU)); \
+ CPU.APU_Cycles += S9xAPUCycles [*IAPU.PC]; \
+ IAPU.opcode = *IAPU.PC; \
+ pIAPU = &IAPU; \
+ (*S9xApuOpcodes[*IAPU.PC]) (); \
+ if(IAPU._Carry) IAPU.P |= Carry; else IAPU.P &= ~Carry; \
+ if(IAPU._Overflow) IAPU.P |= Overflow; else IAPU.P &= ~Overflow; \
+ pIAPU = &IAPU2; \
+ spc700_execute(0); \
+ APUCompare(); \
+ IAPU.ya_prev = IAPU.YA.W; \
+ IAPU.x_prev = IAPU.X; \
+}
+#endif
+
+#define APU_EXECUTE(mode) \
+if (CPU.APU_APUExecuting == mode) \
+{\
+ while (CPU.APU_Cycles <= CPU.Cycles) \
+ APU_EXECUTE1(); \
+}
+#endif
+
+#endif
diff --git a/src/spc700/spcgen.c b/src/spc700/spcgen.c
new file mode 100644
index 0000000..5a15bd7
--- /dev/null
+++ b/src/spc700/spcgen.c
@@ -0,0 +1,2164 @@
+// notaz's SPC700 Emulator
+// (c) Copyright 2006 notaz, All rights reserved.
+//
+// Added some modifications by Bitrider 2010-2011.
+//
+// this is a rewrite of spc700.cpp in ARM asm, inspired by other asm CPU cores like
+// Cyclone and DrZ80. It is meant to be used in Snes9x emulator ports for ARM platforms.
+//
+// notes:
+// "Shutdown" mechanism is not supported, so undefine SPC700_SHUTDOWN in your port.h
+// code branches backwards over start of memory are not supported
+// (never seen any game doing that)
+//
+// license:
+// the code is released under Snes9x license. It would be nice if the word "notaz"
+// would appear somewhere in your documentation or your program's "about" screen
+// if you use this :)
+
+/*
+ * Permission to use, copy, modify and distribute Snes9x in both binary and
+ * source form, for non-commercial purposes, is hereby granted without fee,
+ * providing that this license information and copyright notice appear with
+ * all copies and any derived work.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event shall the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Snes9x is freeware for PERSONAL USE only. Commercial users should
+ * seek permission of the copyright holders first. Commercial use includes
+ * charging money for Snes9x or software derived from Snes9x.
+ *
+ * The copyright holders request that bug fixes and improvements to the code
+ * should be forwarded to them so everyone can benefit from the modifications
+ * in future versions.
+ *
+ * Super NES and Super Nintendo Entertainment System are trademarks of
+ * Nintendo Co., Limited and its subsidiary companies.
+ */
+
+int one_apu_cycle[] = {13, 14, 15, 21};
+int current_cycles;
+
+
+// settings
+#define VERSION "0.12"
+#define APU_EXECUTING_OFF 124
+//#define SPC_DEBUG
+
+
+// includes
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+// timings
+int S9xAPUCycles [256] =
+{
+ /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */
+ /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8,
+ /* 10 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 4, 6,
+ /* 20 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 5, 4,
+ /* 30 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 3, 8,
+ /* 40 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 6, 6,
+ /* 50 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 4, 5, 2, 2, 4, 3,
+ /* 60 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 5, 5,
+ /* 70 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 6,
+ /* 80 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 2, 4, 5,
+ /* 90 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2,12, 5,
+ /* a0 */ 3, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 2, 4, 4,
+ /* b0 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 4,
+ /* c0 */ 3, 8, 4, 5, 4, 5, 4, 7, 2, 5, 6, 4, 5, 2, 4, 9,
+ /* d0 */ 2, 8, 4, 5, 5, 6, 6, 7, 4, 5, 4, 5, 2, 2, 6, 3,
+ /* e0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3,
+ /* f0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3
+};
+
+
+// stuff
+static FILE *AsmFile=NULL;
+static int opcode=0; // 0-0xff
+static int ibuffer = 0;
+static char buff[1024];
+
+
+void ot(char *format, ...)
+{
+ va_list valist=NULL;
+ int i, len;
+
+ // notaz: stop me from leaving newlines in the middle of format string
+ // and generating bad code
+ for(i=0, len=strlen(format); i < len && format[i] != '\n'; i++);
+ if(i < len-1 && format[len-1] != '\n') printf("\nWARNING: possible improper newline placement:\n%s\n", format);
+
+ va_start(valist,format);
+ if (AsmFile) vfprintf(AsmFile,format,valist);
+ va_end(valist);
+}
+
+// ot buffered
+void otb(char *format, ...)
+{
+ va_list valist=NULL;
+ int i, len;
+
+ // notaz: stop me from leaving newlines in the middle of format string
+ // and generating bad code
+ for(i=0, len=strlen(format); i < len && format[i] != '\n'; i++);
+ if(i < len-1 && format[len-1] != '\n') printf(buff, "\nWARNING: possible improper newline placement:\n%s\n", format);
+
+ va_start(valist,format);
+ if (AsmFile) vsprintf(buff,format,valist);
+ ibuffer = 1;
+ va_end(valist);
+}
+
+void flush_buffer() {
+ if (ibuffer != 0) {
+ ot(buff);
+ ibuffer = 0;
+ }
+}
+
+// trashes: r0, r1, r2
+// return: r0
+// exit at label "2"
+static void GetAPUDSP() {
+ ot("GetAPUDSP: \n");
+ ot(" ldrb r1, [spc_ram, #0xf2] \n");
+ // r1 = IAPU.RAM [0xf2]
+
+ ot(" mov r0, #0\n");
+ ot(" and r2, r1, #0X0f \n");
+ // switch (reg & 0xf) {
+ ot(" cmp r2, #0x08\n");
+ ot(" bxeq lr\n"); // APU_ENVX = 8
+ // r1 = IAPU.RAM [0xf2] & 0x7f;
+
+ ot(" cmp r2, #0x09\n");
+ // return APU.DSP [reg];
+ ot(" ldrne r2, .APU_DSP\n");
+ ot(" and r1, r1, #0X7f \n"); // r1 = IAPU.RAM[0xf2] & 0x7f
+ ot(" ldrneb r0, [r2, r1] \n");
+ ot(" bxne lr \n");
+
+ // APU_OUTX = 9
+ // if (SoundData.channels [reg >> 4].state == SOUND_SILENT) return 0;
+ // return ((SoundData.channels [reg >> 4].sample >> 8) | (SoundData.channels [reg >> 4].sample & 0x
+ ot(" ldr r2, .SOUNDDATA_CHANNELS\n");
+ ot(" mov r1, r1, lsr #4 \n");
+ //ot(" add r1, r2, r1, asl #8\n");
+ //ot(" ldr r0, [r1, #0x0] \n"); // r0 = SoundData.channels[reg >> 4].state
+ ot(" ldr r0, [r2, r1, asl #8] \n");
+ ot(" add r1, r2, r1, asl #8\n");
+ ot(" cmp r0, #0 \n"); // SOUND_SILENT = 0
+ ot(" ldrneh r1, [r1, #0x48] \n"); // r1 = SoundData.channels[reg >> 4].sample
+ ot(" bxeq lr \n");
+
+ ot(" and r0, r1, #0xff\n");
+ ot(" orr r0, r0, r1, lsr #8\n");
+ ot(" bx lr \n");
+
+ ot(".APU_DSP:\n");
+ ot(" .long APU + 0x0b\n"); // &APU.DSP
+ ot(".SOUNDDATA_CHANNELS:\n");
+ ot(" .long SoundData + 0x30\n"); // &SoundData.channels[0]
+}
+
+
+// bitrider
+// macros
+static void GetByte() {
+ ot(" mov r1, r0\n");
+
+ ot(" ldrb r0, [spc_ram, r1] \n");
+
+ ot(" cmp r1, #0x0ff\n");
+ ot(" bhi 1f \n");
+
+ ot(" cmp r1, #0xf3 \n");
+ ot(" addeq lr, pc, #12 \n"); // lr = &ExitPoint
+ ot(" beq GetAPUDSP \n");
+
+ ot(" cmp r1, #0xfd \n");
+ ot(" movhs r2, #0 \n");
+ ot(" strhsb r2, [spc_ram, r1] \n");
+ ot("1:\n");
+
+
+}
+
+// trashes: r0, r1, r14
+static void GetByteZ() {
+ ot(" mov r1, r0\n");
+
+ ot(" cmp r1, #0xf3 \n");
+ ot(" addeq lr, pc, #20 \n"); // lr = &ExitPoint
+ ot(" beq GetAPUDSP \n");
+
+ ot(" ldr r14, [context, #iapu_directpage]\n");
+ ot(" cmp r1, #0xfd \n");
+ ot(" ldrb r0, [r14, r1] \n");
+ ot(" movhs r2, #0 \n");
+ ot(" strhsb r2, [r14, r1] \n");
+}
+
+static void SetByte(int restore) {
+ // Still should check for ShowRom
+ ot(" add r2, r1, #40 \n");
+ ot(" tst r2, #0x10000 \n");
+ ot(" bne 1f \n");
+
+ ot(" bic r2, r1, #0x0f\n");
+ ot(" cmp r2, #0xf0\n");
+ ot(" strneb r0, [spc_ram, r1] \n");
+ ot(" bne 3f\n");
+
+ ot(" add lr, pc, #20\n");
+
+ ot(" cmp r1, #0xf1 \n");
+ ot(" beq S9xSetAPUControl \n");
+
+ ot(" cmp r1, #0xf3 \n"); // pc + 4
+ ot(" beq S9xSetAPUDSP \n"); // pc + 8
+ ot(" b S9xAPUSetByteFFtoF0 \n"); // pc + 12
+
+ ot("1: \n");
+ ot(" bl S9xAPUSetByteFFC0 \n");
+ ot(" ldr spc_ram, [context, #iapu_ram] \n");
+ ot("3: \n");
+
+}
+
+static void SetByteZ(int restore) {
+ ot(" ldr r2, [context, #iapu_directpage] \n");
+ ot(" cmp r2, spc_ram \n");
+ ot(" bne 2f \n");
+
+ ot(" cmp r1, #0xf0 \n");
+ ot(" blo 2f \n");
+
+ ot(" cmp r1, #0xfe \n");
+ ot(" bhs 1f \n");
+
+ if (restore) ot(" add lr, pc, #16\n");
+ else ot(" add lr, pc, #20\n");
+
+ ot(" cmp r1, #0xf1 \n");
+ ot(" beq S9xSetAPUControl \n");
+
+ ot(" cmp r1, #0xf3 \n"); // pc + 4
+ ot(" beq S9xSetAPUDSP \n"); // pc + 8
+ ot(" b S9xAPUSetByteFFtoF0 \n"); // pc + 12
+ //ot("6: \n"); // pc + 16
+ if (restore) {
+ ot(" ldr spc_ram, [context, #iapu_ram] \n");
+ ot(" b 1f \n");
+ }
+ ot("2: \n");
+ ot(" strb r0, [r2, r1] \n");
+ ot("1: \n");
+}
+
+
+// r0-2: Temporary registers
+// r3 : current opcode or temp
+// r4 : Cycles remaining
+// r5 : Pointer to IAPU structure
+// r6 : Pointer to Opcode Jump table
+// r7 : Current PC
+// r8 : YA
+// r9 : P (nzzzzzzz ........ ........ NODBHIZC; nzzzzzzz - NZ flag in use (for a little speedup)
+
+// r10 : X
+// r11 : S
+// r14 : temp
+// lr : RAM pointer
+
+static void PrintFramework()
+{
+
+
+#ifndef SPC_DEBUG
+ ot(" .extern IAPU\n");
+#else
+ ot(" .extern IAPU2\n");
+#endif
+ ot(" .extern CPU @ for STOP and SLEEP\n");
+ ot(" .extern S9xAPUGetByte\n");
+ ot(" .extern S9xAPUSetByte\n");
+ ot(" .extern S9xAPUGetByteZ\n");
+ ot(" .extern S9xAPUSetByteZ\n\n");
+
+ // bitrider
+ ot(" .extern S9xGetAPUDSP\n");
+ ot(" .extern S9xSetAPUDSP\n");
+ ot(" .extern S9xSetAPUControl\n");
+ ot(" .extern S9xAPUSetByteFFC0\n");
+ ot(" .extern S9xAPUSetByteFFtoF0\n");
+
+ ot(" .global spc700_execute @ int cycles\n");
+ //ot(" .global Spc700JumpTab\n\n");
+ for (current_cycles=0; current_cycles < (sizeof(one_apu_cycle) / sizeof(int)); current_cycles++)
+ ot(" .global Spc700JumpTab_%i\n", one_apu_cycle[current_cycles]);
+ ot("\n");
+
+
+ ot(" opcode .req r3\n");
+ ot(" cycles .req r4\n");
+ ot(" context .req r5\n");
+ ot(" opcodes .req r6\n");
+ ot(" spc_pc .req r7\n");
+ ot(" spc_ya .req r8\n");
+ ot(" spc_p .req r9\n");
+ ot(" spc_x .req r10\n");
+ ot(" spc_s .req r11\n");
+ ot(" spc_ram .req r12\n\n");
+
+ ot(" .equ iapu_directpage, 0x00\n");
+ ot(" .equ iapu_ram, 0x44\n");
+ ot(" .equ iapu_extraram, 0x48\n");
+ ot(" .equ iapu_allregs_load, 0x30\n");
+ ot(" .equ iapu_allregs_save, 0x34\n\n");
+
+ ot(" .equ flag_c, 0x01\n");
+ ot(" .equ flag_z, 0x02\n");
+ ot(" .equ flag_i, 0x04\n");
+ ot(" .equ flag_h, 0x08\n");
+ ot(" .equ flag_b, 0x10\n");
+ ot(" .equ flag_d, 0x20\n");
+ ot(" .equ flag_o, 0x40\n");
+ ot(" .equ flag_n, 0x80\n\n");
+
+ ot(" .equ cpu_apu_executing, %i \n\n", APU_EXECUTING_OFF);
+ // tmp
+// ot(" .equ iapu_carry, 0x24\n");
+// ot(" .equ iapu_overflow, 0x26\n\n");
+
+ ot("@ --------------------------- Framework --------------------------\n");
+ ot(" .align 4\n");
+ ot("spc700_execute: @ int cycles\n");
+
+ ot(" stmfd sp!,{r4-r11,lr}\n");
+
+#ifndef SPC_DEBUG
+ ot(" ldr context,=IAPU @ Pointer to SIAPU struct\n");
+#else
+ ot(" ldr context,=IAPU2 @ Pointer to SIAPU struct\n");
+#endif
+ ot(" mov cycles,r0 @ Cycles\n");
+ ot(" add r0,context,#iapu_allregs_load\n");
+ ot(" ldmia r0,{opcodes,spc_pc,spc_ya,spc_p,spc_x,spc_ram}\n");
+
+ ot(" ldrb opcode,[spc_pc],#1 @ Fetch first opcode\n");
+ ot(" mov spc_s,spc_x,lsr #8\n");
+ ot(" and spc_x,spc_x,#0xff\n");
+ ot("\n");
+
+ ot(" ldr pc,[opcodes,opcode,lsl #2] @ Jump to opcode handler\n");
+ ot("\n\n");
+
+
+ ot("@ We come back here after execution\n");
+ ot("spc700End:\n");
+ ot(" orr spc_x,spc_x,spc_s,lsl #8\n");
+ ot(" add r0,context,#iapu_allregs_save\n");
+ ot(" stmia r0,{spc_pc,spc_ya,spc_p,spc_x}\n");
+ ot(" mov r0,cycles\n");
+ ot(" ldmfd sp!,{r4-r11,pc}\n");
+ ot("\n");
+
+ ot(" .ltorg\n");
+ ot("\n");
+
+ GetAPUDSP();
+}
+
+
+// ---------------------------------------------------------------------------
+
+// Trashes r0-r3
+static void MemHandler(int set, int z, int save)
+{
+ //if(set) ot(" bl S9xAPUSetByte%s\n", z ? "Z" : "");
+ //else ot(" bl S9xAPUGetByte%s\n", z ? "Z" : "");
+
+ //if(set) ot(" asm_S9xAPUSetByte%s\n", z ? "Z" : "");
+ //else ot(" asm_S9xAPUGetByte%s\n", z ? "Z" : "");
+ if(set) {
+ if (z) SetByteZ(save);
+ else SetByte(save);
+ } else {
+ if (z) GetByteZ();
+ else GetByte();
+ }
+
+ //if(save) ot(" ldr spc_ram,[context,#iapu_ram]\n");
+}
+
+// pushes reg, trashes r1
+static void Push(char *reg)
+{
+ ot(" add r1,spc_ram,spc_s\n");
+ ot(" strb %s,[r1,#0x100]\n", reg);
+ ot(" sub spc_s,spc_s,#1\n");
+}
+
+// pushes r0, trashes r0,r1
+static void PushW()
+{
+ ot(" add r1,spc_ram,spc_s\n");
+ ot(" sub spc_s,spc_s,#2\n");
+ ot(" strb r0,[r1,#0xff]\n");
+ ot(" mov r0,r0,lsr #8\n");
+ ot(" strb r0,[r1,#0x100]\n");
+}
+
+// pops to reg
+static void Pop(char *reg)
+{
+ ot(" add %s,spc_ram,spc_s\n", reg);
+ ot(" ldrb %s,[%s,#(0x100 + 1)]\n", reg, reg);
+ ot(" add spc_s,spc_s,#1\n");
+}
+
+// pops to r0, trashes r1
+static void PopW()
+{
+ ot(" add r1,spc_ram,spc_s\n");
+ ot(" ldrb r0,[r1,#(0xff + 2)]\n");
+ ot(" ldrb r1,[r1,#(0x100 + 2)]\n");
+ ot(" add spc_s,spc_s,#2\n");
+ ot(" orr r0,r0,r1,lsl #8\n");
+}
+
+// // rr <- absolute, trashes r14
+// rr <- absolute
+
+static void AbsoluteAdd(int r, char *rAdd)
+{
+ ot(" ldrb r%i,[spc_pc],#1\n", r);
+ ot(" ldrb r14,[spc_pc],#1\n");
+ if (rAdd) ot(" add r%i,r%i,%s\n", r, r, rAdd);
+ ot(" add r%i,r%i,r14,lsl #8\n", r, r);
+}
+
+// // rr <- absolute, trashes r14
+// rr <- absolute
+static void Absolute(int r)
+{
+ //ot(" ldrb r%i,[spc_pc],#1\n", r);
+ //ot(" ldrb r14,[spc_pc],#1\n");
+ //ot(" orr r%i,r%i,r14,lsl #8\n", r, r);
+ AbsoluteAdd(r, NULL);
+}
+
+
+// rr <- absoluteX, trashes r14
+static void AbsoluteX(int r)
+{
+ //Absolute(r);
+ //ot(" ldrb r%i,[spc_pc],#1\n", r);
+ //ot(" ldrb r14,[spc_pc],#1\n");
+ //ot(" add r%i,r%i,spc_x\n", r, r);
+ //ot(" add r%i,r%i,r14,lsl #8\n", r, r);
+ AbsoluteAdd(r, "spc_x");
+}
+
+// r0 <- absoluteY, trashes r1
+static void AbsoluteY(int r)
+{
+ //Absolute(r);
+ //ot(" ldrb r%i,[spc_pc],#1\n", r);
+ //ot(" ldrb r14,[spc_pc],#1\n");
+ //ot(" add r%i,r%i,spc_ya,lsr #8\n", r, r);
+ //ot(" add r%i,r%i,r14,lsl #8\n", r, r);
+ AbsoluteAdd(r, "spc_ya, lsr #8");
+}
+
+// rr <- IndirectIndexedY, trashes r14
+static void IndirectIndexedY(int r)
+{
+ ot(" ldrb r%i,[spc_pc],#1\n", r);
+ ot(" ldr r14,[context,#iapu_directpage]\n");
+ ot(" ldrb r%i,[r14,r%i]!\n", r, r);
+ ot(" ldrb r14,[r14,#1]\n");
+ //ot(" orr r%i,r%i,r14,lsl #8\n", r, r);
+ ot(" add r%i,r%i,spc_ya,lsr #8\n", r, r);
+ ot(" add r%i,r%i,r14,lsl #8\n", r, r);
+}
+
+// rr <- address, trashes r14
+static void IndexedXIndirect(int r)
+{
+ ot(" ldrb r%i,[spc_pc],#1\n", r);
+ ot(" ldr r14,[context,#iapu_directpage]\n"); // again, interlocks are bad
+ ot(" add r%i,r%i,spc_x\n", r, r);
+ ot(" and r%i,r%i,#0xff\n", r, r);
+ ot(" ldrb r%i,[r14,r%i]!\n", r, r);
+ ot(" ldrb r14,[r14,#1]\n");
+ ot(" orr r%i,r%i,r14,lsl #8\n", r, r);
+}
+
+// sets ZN for reg in *reg, not suitable for Y
+static void SetZN8(char *reg)
+{
+ ot(" and spc_p,spc_p,#0xff\n");
+ ot(" orr spc_p,spc_p,%s,lsl #24\n", reg);
+}
+
+// sets ZN for reg in *reg
+static void SetZN16(char *reg)
+{
+ ot(" and spc_p,spc_p,#0xff\n");
+ ot(" orr spc_p,spc_p,%s,lsl #16\n", reg);
+ ot(" tst %s,#0xff\n", reg);
+ ot(" orrne spc_p,spc_p,#0x01000000\n");
+}
+
+// does ROL on r0, sets flags
+static void Rol()
+{
+ ot(" mov r0,r0,lsl #1\n");
+ ot(" tst spc_p,#flag_c\n");
+ ot(" orrne r0,r0,#1\n");
+ ot(" tst r0,#0x100\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ SetZN8("r0");
+}
+
+// does ROR on r0, sets flags
+static void Ror()
+{
+ ot(" tst spc_p,#flag_c\n");
+ ot(" orrne r0,r0,#0x100\n");
+ ot(" movs r0,r0,lsr #1\n");
+ ot(" orrcs spc_p,spc_p,#flag_c\n");
+ ot(" biccc spc_p,spc_p,#flag_c\n");
+ SetZN8("r0");
+}
+
+// does ASL on r0, sets flags but doesn't cut the shifted bits
+static void Asl()
+{
+ ot(" tst r0,#0x80\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" mov r0,r0,lsl #1\n");
+ SetZN8("r0");
+}
+
+// does LSR on r0, sets flags
+static void Lsr()
+{
+ ot(" tst r0,#0x01\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" mov r0,r0,lsr #1\n");
+ SetZN8("r0");
+}
+
+// CMP rr0,rr1; trashes r14
+static void Cmp(char *r0, char *r1, int and_r0)
+{
+ char *lop = r0;
+
+ if(and_r0) { ot(" and r14,%s,#0xff\n", r0); lop = "r14"; }
+ ot(" subs r14,%s,%s\n", lop, r1);
+ //ot(" orrge spc_p,spc_p,#flag_c\n");
+ //ot(" biclt spc_p,spc_p,#flag_c\n");
+ ot(" orrcs spc_p,spc_p,#flag_c\n");
+ ot(" biccc spc_p,spc_p,#flag_c\n");
+ SetZN8("r14");
+}
+
+// ADC rr0,rr1 -> rr0, trashes r2,r14, does not mask to byte
+static void Adc(char *r0, char *r1)
+{
+ ot(" eor r2,%s,%s\n", r0, r1); // r3=(a) ^ (b)
+ ot(" movs r14, spc_p, lsr #1\n");
+ ot(" adc %s, %s, %s\n", r0, r0, r1);
+ //ot(" add %s,%s,%s\n", r0, r0, r1);
+ //ot(" tst spc_p,#flag_c\n");
+ //ot(" addne %s,%s,#1\n", r0, r0);
+ ot(" movs r14,%s,lsr #8\n", r0);
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" eor r14,%s,%s\n", r0, r1); // r14=(b) ^ Work16
+ ot(" bic r14,r14,r2\n"); // ((b) ^ Work16) & ~((a) ^ (b))
+ ot(" tst r14,#0x80\n");
+ ot(" orrne spc_p,spc_p,#flag_o\n");
+ ot(" biceq spc_p,spc_p,#flag_o\n");
+ ot(" eor r14,r2,%s\n", r0);
+ ot(" tst r14,#0x10\n");
+ ot(" orrne spc_p,spc_p,#flag_h\n");
+ ot(" biceq spc_p,spc_p,#flag_h\n");
+}
+
+// SBC rr0,rr1 -> rr0, trashes r2,r3,r14, does not mask to byte
+static void Sbc(char *r0, char *r1)
+{
+ ot(" movs r14,spc_p,lsr #1\n");
+ ot(" sbcs r2,%s,%s\n", r0, r1);
+ ot(" orrge spc_p,spc_p,#flag_c\n");
+ ot(" biclt spc_p,spc_p,#flag_c\n");
+ ot(" eor r14,%s,r2\n", r0); // r14=(a) ^ Int16
+ ot(" eor r3,%s,%s\n", r0, r1); // r3=(a) ^ (b)
+ ot(" and r14,r14,r3\n"); // ((a) ^ Work16) & ((a) ^ (b))
+ ot(" tst r14,#0x80\n");
+ ot(" orrne spc_p,spc_p,#flag_o\n");
+ ot(" biceq spc_p,spc_p,#flag_o\n");
+ ot(" eor r14,r3,r2\n");
+ ot(" tst r14,#0x10\n");
+ ot(" orreq spc_p,spc_p,#flag_h\n");
+ ot(" bicne spc_p,spc_p,#flag_h\n");
+ ot(" mov %s,r2\n", r0);
+}
+
+
+//
+static void TCall()
+{
+ ot(" sub r0,spc_pc,spc_ram\n");
+ PushW();
+ ot(" ldr r0,[context,#iapu_extraram]\n");
+ ot(" ldrh r0,[r0,#0x%x]\n", (15-(opcode>>4))<<1);
+ ot(" add spc_pc,spc_ram,r0\n");
+}
+
+//
+static void SetClr1()
+{
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" %s r0,r0,#0x%02x\n", opcode & 0x10 ? "bic" : "orr", 1<<(opcode>>5));
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+}
+
+//
+static void BssBbc()
+{
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" tst r0,#0x%02x\n", 1<<(opcode>>5));
+ ot(" add%s spc_pc,spc_pc,#1\n", opcode & 0x10 ? "ne" : "eq");
+ ot(" ldr%ssb r0,[spc_pc],#1\n", opcode & 0x10 ? "eq" : "ne");
+ ot(" sub%s cycles,cycles,#%i\n",opcode & 0x10 ? "eq" : "ne", one_apu_cycle[current_cycles]*2);
+ ot(" add%s spc_pc,spc_pc,r0\n", opcode & 0x10 ? "eq" : "ne");
+}
+
+//
+static void Membit()
+{
+ ot(" ldrb r0,[spc_pc], #1\n");
+ ot(" ldrb r3,[spc_pc], #1\n");
+ //ot(" orr spc_x,spc_x,r1,lsl #(29-5)
+ ot(" add r3,r0,r3,lsl #8\n"); //@ store membit where it can survive memhandler call\n"); // saving bit 12 ?
+ //ot(" mov r1,r1,lsr #5\n");
+ //ot(" mov r0,r0,lsl #19\n");
+ //ot(" mov r0,r0,lsr #19\n");
+ //if((opcode >> 4) >= 0xC) ot(" mov r3, r0\n"); //ot(" stmfd sp!,{r0}\n"); // membit
+ ot(" bic r0, r3, #0xe000\n"); // Clear bits 15, 14 & 13 => r0 = r0 & 0x1fff
+ MemHandler(0, 0, 0);
+ //ot(" mov r1,spc_x,lsr #29\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ ot(" mov r1, r3, lsr #13\n"); // membit = bits[15:13] of memory address
+ if((opcode >> 4) < 0xC) {
+ ot(" mov r0,r0,lsr r1\n");
+ ot(" tst r0,#1\n");
+ switch(opcode >> 4) {
+ case 0x0: ot(" orrne spc_p,spc_p,#flag_c\n"); break; // OR1 C,membit
+ case 0x2: ot(" orreq spc_p,spc_p,#flag_c\n"); break; // OR1 C,not membit
+ case 0x4: ot(" biceq spc_p,spc_p,#flag_c\n"); break; // AND1 C,membit
+ case 0x6: ot(" bicne spc_p,spc_p,#flag_c\n"); break; // AND1 C, not membit
+ case 0x8: ot(" eorne spc_p,spc_p,#flag_c\n"); break; // EOR1 C, membit
+ case 0xA: ot(" orrne spc_p,spc_p,#flag_c\n"); // MOV1 C,membit
+ ot(" biceq spc_p,spc_p,#flag_c\n"); break;
+ }
+ } else {
+ ot(" mov r2,#1\n");
+ ot(" mov r2,r2,lsl r1\n");
+ if((opcode >> 4) == 0xC) { // MOV1 membit,C
+ ot(" tst spc_p,#flag_c\n");
+ ot(" orrne r0,r0,r2\n");
+ ot(" biceq r0,r0,r2\n");
+ } else { // NOT1 membit
+ ot(" eor r0,r0,r2\n");
+ }
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" bic r1, r3, #0xe000\n"); // Clear bits 15, 14 & 13 => r0 = r0 & 0x1fff
+ MemHandler(1, 0, 0);
+ }
+ //ot(" ldr spc_ram,[context,#iapu_ram] @ restore what memhandler(s) messed up\n");
+}
+
+//
+static void CBranch()
+{
+ int tests[] = { 0x80000000, 0x40, 0x01, 0xff000000 }; // NOCZ
+ char *eq = "eq";
+ char *ne = "ne";
+
+ if((opcode>>6) == 3) { // zero test inverts everything
+ eq = "ne";
+ ne = "eq";
+ }
+
+ ot(" tst spc_p,#0x%08X\n", tests[opcode>>6]);
+ ot(" add%s spc_pc,spc_pc,#1\n", opcode & 0x20 ? eq : ne);
+/*
+ ot(" b%s Apu%02X\n", opcode & 0x20 ? eq : ne, opcode);
+ ot(" sub r0,spc_pc,spc_ram\n");
+ ot(" ldrsb r1,[spc_pc],#1\n");
+ ot(" add r0,r0,r1\n");
+ ot(" mov r0,r0,lsl #16\n");
+ ot(" add spc_pc,spc_ram,r0,lsr #16\n");
+*/
+ ot(" ldr%ssb r0,[spc_pc],#1\n", opcode & 0x20 ? ne : eq);
+
+ ot(" sub%s cycles,cycles,#%i\n", opcode & 0x20 ? ne : eq, one_apu_cycle[current_cycles]*2);
+ ot(" add%s spc_pc,spc_pc,r0\n", opcode & 0x20 ? ne : eq);
+// ot("Apu%02X:\n", opcode);
+}
+
+// NeededOperation spc_ya,r0 -> spc_ya
+static void ArithOpToA()
+{
+ // special A pre-processing
+ if((opcode>>5) == 4 || (opcode>>5) == 5) {
+ ot(" and r1,spc_ya,#0xff00\n");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ }
+
+ switch(opcode>>5) {
+ case 0: ot(" orr spc_ya,spc_ya,r0\n"); break; // OR
+ case 1: ot(" orr r0,r0,#0xff00\n");
+ ot(" and spc_ya,spc_ya,r0\n"); break; // AND
+ case 2: ot(" eor spc_ya,spc_ya,r0\n"); break; // EOR
+ case 3: Cmp("spc_ya", "r0", 1); break; // CMP
+ case 4: Adc("spc_ya", "r0"); break; // ADC
+ case 5: Sbc("spc_ya", "r0"); break; // SBC
+ case 6: printf("MOV (reversed)!?\n"); break; // MOV (reversed)
+ case 7: ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0\n"); break; // MOV
+ }
+
+ if((opcode>>5) != 3) SetZN8("spc_ya"); // only if not Cmp
+
+ // special A post-processing
+ if((opcode>>5) == 4 || (opcode>>5) == 5) {
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r1\n");
+ }
+}
+
+//
+static void ArithmeticToA()
+{
+ switch(opcode&0x1f) {
+ case 0x04: // OP A,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ArithOpToA();
+ break;
+
+ case 0x05: // OP A,abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ case 0x06: // OP A,(X)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ArithOpToA();
+ break;
+
+ case 0x07: // OP A,(dp+X)
+ IndexedXIndirect(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ case 0x08: // OP A,#00
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ArithOpToA();
+ break;
+
+ case 0x14: // OP A,dp+X
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ArithOpToA();
+ break;
+
+ case 0x15: // OP A,abs+X
+ AbsoluteX(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ case 0x16: // OP A,abs+Y
+ AbsoluteY(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ case 0x17: // OP A,(dp)+Y
+ IndirectIndexedY(0);
+ MemHandler(0, 0, 1);
+ ArithOpToA();
+ break;
+
+ default:
+ printf("Op %02X - arithmetic??\n", opcode);
+ }
+}
+
+void printOpcodes(int apu_cycles) {
+ for(opcode = 0; opcode < 0x100; opcode++) {
+ printf("%02X", opcode);
+
+ ot("\n\n");
+ //tmp_prologue();
+ ot("Apu%02X_%i:\n", opcode, apu_cycles);
+
+ if((opcode & 0x1f) == 0x10) CBranch(); // BXX
+ if((opcode & 0x0f) == 0x01) TCall(); // TCALL X
+ if((opcode & 0x0f) == 0x02) SetClr1(); // SET1/CLR1 direct page bit X
+ if((opcode & 0x0f) == 0x03) BssBbc(); // BBS/BBC direct page bit X
+ if((opcode & 0x1f) == 0x0A) Membit(); // membit ops
+ if((opcode & 0x0f) >= 0x04 && (opcode & 0x0f) <= 0x08 && (opcode & 0x1f) != 0x18 && (opcode >> 5) != 6)
+ ArithmeticToA();
+
+
+ switch(opcode) {
+ case 0x00: // NOP
+ break;
+
+ case 0x3F: // CALL absolute
+ Absolute(2);
+ ot(" sub r0,spc_pc,spc_ram\n");
+ PushW();
+ ot(" add spc_pc,spc_ram,r2\n");
+ break;
+
+ case 0x4F: // PCALL $XX
+ ot(" ldrb r2,[spc_pc],#1\n");
+ ot(" sub r0,spc_pc,spc_ram\n");
+ PushW();
+ ot(" add spc_pc,spc_ram,r2\n");
+ ot(" add spc_pc,spc_pc,#0xff00\n");
+ break;
+
+ case 0x09: // OR dp(dest),dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" orr spc_x,spc_x,r0,lsl #24 @ save from harm\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" orr r0, r0, r3\n");
+ //ot(" orr r0,r0,spc_x,lsr #24\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x18: // OR dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" orr r0,r0,r1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x19: // OR (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" orr spc_x,spc_x,r0,lsl #24\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ ot(" orr r0, r3, r0\n");
+ //ot(" orr r0,r0,spc_x,lsr #24\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x0B: // ASL dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ Asl();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x0C: // ASL abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ Asl();
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x1B: // ASL dp+X
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_x\n");
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 1, 0);
+ Asl();
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x1C: // ASL A
+ ot(" tst spc_ya,#0x80\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" and r0,spc_ya,#0x7f\n");
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #1\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0x0D: // PUSH PSW
+ ot(" mov r0,spc_p,lsr #24\n");
+ ot(" and r1,r0,#0x80\n");
+ ot(" tst r0,r0\n");
+ ot(" orreq r1,r1,#flag_z\n");
+ ot(" and spc_p,spc_p,#0x7d @ clear N & Z\n");
+ ot(" orr spc_p,spc_p,r1\n");
+ Push("spc_p");
+ otb(" orr spc_p,spc_p,r0,lsl #24\n");
+ break;
+
+ case 0x2D: // PUSH A
+ Push("spc_ya");
+ break;
+
+ case 0x4D: // PUSH X
+ Push("spc_x");
+ break;
+
+ case 0x6D: // PUSH Y
+ ot(" mov r0,spc_ya,lsr #8\n");
+ Push("r0");
+ break;
+
+ case 0x8E: // POP PSW
+ Pop("spc_p");
+ ot(" and r0,spc_p,#(flag_z|flag_n)\n");
+ ot(" eor r0,r0,#flag_z\n");
+ ot(" orr spc_p,spc_p,r0,lsl #24\n");
+ ot(" tst spc_p,#flag_d\n");
+ ot(" addne r0,spc_ram,#0x100\n");
+ ot(" moveq r0,spc_ram\n");
+ otb(" str r0,[context,#iapu_directpage]\n");
+ break;
+
+ case 0xAE: // POP A
+ Pop("r0");
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ otb(" orr spc_ya,spc_ya,r0\n");
+ break;
+
+ case 0xCE: // POP X
+ Pop("spc_x");
+ break;
+
+ case 0xEE: // POP X
+ Pop("r0");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ otb(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ break;
+
+ case 0x0E: // TSET1 abs
+ Absolute(0);
+ ot(" mov r3, r0\n");
+ //ot(" orr spc_x,spc_x,r0,lsl #16 @ save from memhandler\n");
+ MemHandler(0, 0, 0);
+ ot(" and r2,r0,spc_ya\n");
+ SetZN8("r2");
+ ot(" orr r0,r0,spc_ya\n");
+ ot(" mov r1, r3\n");
+ //ot(" mov r1,spc_x,lsr #16\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x4E: // TCLR1 abs
+ Absolute(0);
+ ot(" mov r3, r0\n");
+ //ot(" orr spc_x,spc_x,r0,lsl #16 @ save from memhandler\n");
+ MemHandler(0, 0, 0);
+ ot(" and r2,r0,spc_ya\n");
+ SetZN8("r2");
+ ot(" bic r0,r0,spc_ya\n");
+ ot(" mov r1, r3\n");
+ //ot(" mov r1,spc_x,lsr #16\n");
+ //ot(" and spc_x,spc_x,#0xff\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x0F: // BRK
+ ot(" sub r0,spc_pc,spc_ram\n");
+ PushW();
+ ot(" mov r0,spc_p,lsr #24\n");
+ ot(" and r1,r0,#0x80\n");
+ ot(" tst r0,r0\n");
+ ot(" orrne r1,r1,#flag_z\n");
+ ot(" and spc_p,spc_p,#0x7d @ clear N & Z\n");
+ ot(" orr spc_p,spc_p,r1\n");
+ Push("spc_p");
+ ot(" orr spc_p,spc_p,#flag_b\n");
+ ot(" bic spc_p,spc_p,#flag_i\n");
+ ot(" ldr r0,[context,#iapu_extraram]\n");
+ ot(" ldrh r0,[r0,#0x20]\n");
+ ot(" add spc_pc,spc_ram,r0\n");
+ break;
+
+ case 0xEF: // SLEEP
+ case 0xFF: // STOP: this is to be compatible with yoyofr's code
+ //ot(" ldr r0,=CPU\n");
+ ot(" ldr r0, 5001f\n", apu_cycles);
+ ot(" mov r1,#0\n");
+ //otb(" strb r1,[r0,#122]\n");
+ otb(" str r1,[r0,#cpu_apu_executing]\n");
+ //tmp_epilogue();
+ ot(" subs cycles,cycles,#%i\n", S9xAPUCycles[opcode] * one_apu_cycle[current_cycles]);
+ ot(" ldrgeb opcode,[spc_pc],#1\n");
+ flush_buffer();
+ ot(" ldrge pc,[opcodes,opcode,lsl #2]\n");
+ ot(" b spc700End\n");
+ // don't let code flow until here
+ ot("5001:\n", apu_cycles);
+ ot(" .long CPU \n");
+ break;
+
+ case 0x2F: // BRA
+ ot(" ldrsb r0,[spc_pc],#1\n");
+ ot(" add spc_pc,spc_pc,r0\n");
+ break;
+
+ case 0x80: // SETC
+ otb(" orr spc_p,spc_p,#flag_c\n");
+ break;
+
+ case 0xED: // NOTC
+ otb(" eor spc_p,spc_p,#flag_c\n");
+ break;
+
+ case 0x40: // SETP
+ ot(" orr spc_p,spc_p,#flag_d\n");
+ ot(" add r0,spc_ram,#0x100\n");
+ otb(" str r0,[context,#iapu_directpage]\n");
+ break;
+
+ case 0x1A: // DECW dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" sub r0,r1,#1\n");
+ SetZN16("r0");
+ ot(" stmfd sp!,{r0}\n");
+ ot(" ldrb r1,[spc_pc]\n");
+ MemHandler(1, 1, 0);
+ ot(" ldmfd sp!,{r0}\n");
+ ot(" mov r0,r0,lsr #8\n");
+ ot(" ldrb r1,[spc_pc],#1\n");
+
+ ot(" add r1,r1,#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x5A: // CMPW YA,dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 1);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" subs r0,spc_ya,r1\n");
+ ot(" orrge spc_p,spc_p,#flag_c\n");
+ ot(" biclt spc_p,spc_p,#flag_c\n");
+ SetZN16("r0");
+ break;
+
+ case 0x3A: // INCW dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" add r0,r1,#1\n");
+ SetZN16("r0");
+ ot(" stmfd sp!,{r0}\n");
+ ot(" ldrb r1,[spc_pc]\n");
+ MemHandler(1, 1, 0);
+ ot(" ldmfd sp!,{r0}\n");
+ ot(" mov r0,r0,lsr #8\n");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x7A: // ADDW YA,dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 1);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" add r0,spc_ya,r1\n");
+ ot(" movs r2,r0,lsr #16\n");
+ ot(" orrne spc_p,spc_p,#flag_c\n");
+ ot(" biceq spc_p,spc_p,#flag_c\n");
+ ot(" bic r2,r0,#0x00ff0000\n");
+ ot(" eor r3,r1,r2\n"); // Work16 ^ (uint16) Work32
+ ot(" eor r14,spc_ya,r1\n");
+ ot(" mvn r14,r14\n"); // ~(pIAPU->YA.W ^ Work16)
+ ot(" and r14,r14,r3\n");
+ ot(" tst r14,#0x8000\n");
+ ot(" orrne spc_p,spc_p,#flag_o\n");
+ ot(" biceq spc_p,spc_p,#flag_o\n");
+ ot(" eor r14,r3,spc_ya\n");
+ ot(" tst r14,#0x10\n");
+ ot(" orrne spc_p,spc_p,#flag_h\n");
+ ot(" biceq spc_p,spc_p,#flag_h\n");
+ ot(" mov spc_ya,r2\n");
+ SetZN16("spc_ya");
+
+ break;
+
+ case 0x9A: // SUBW YA,dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 1, 1);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" orr r1,r3,r0,lsl #8\n");
+ ot(" subs r0,spc_ya,r1\n");
+ ot(" orrge spc_p,spc_p,#flag_c\n");
+ ot(" biclt spc_p,spc_p,#flag_c\n");
+ ot(" mov r2,r0,lsl #16\n");
+ ot(" mov r2,r2,lsr #16\n"); // r2=(uint16) Int32
+ ot(" eor r3,spc_ya,r2\n"); // r3=pIAPU->YA.W ^ (uint16) Int32
+ ot(" eor r14,spc_ya,r1\n");
+ ot(" and r14,r14,r3\n");
+ ot(" tst r14,#0x8000\n");
+ ot(" orrne spc_p,spc_p,#flag_o\n");
+ ot(" biceq spc_p,spc_p,#flag_o\n");
+ ot(" eor r14,r3,r1\n");
+ ot(" tst r14,#0x10\n");
+ ot(" bicne spc_p,spc_p,#flag_h\n");
+ ot(" orreq spc_p,spc_p,#flag_h\n");
+ ot(" mov spc_ya,r2\n");
+ SetZN16("spc_ya");
+ break;
+
+ case 0xBA: // MOVW YA,dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1, [spc_pc],#1\n");
+ ot(" mov spc_ya, r0\n"); // avoiding inter-locks
+ ot(" add r0, r1, #1\n");
+ MemHandler(0, 1, 1);
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN16("spc_ya");
+ break;
+
+ case 0xDA: // MOVW dp,YA
+ ot(" ldrb r1,[spc_pc]\n");
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 1, 0);
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya,lsr #8\n"); // avoiding inter-locks
+ ot(" add r1,r1,#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x69: // CMP dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ ot(" orr spc_x,spc_x,r0,lsl #24\n");
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" mov r1,spc_x,lsr #24\n");
+ Cmp("r0", "r1", 0);
+ otb(" and spc_x,spc_x,#0xff\n");
+ break;
+
+ case 0x78: // CMP dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 1);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ Cmp("r0", "r1", 0);
+ break;
+
+ case 0x79: // CMP (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ ot(" orr spc_x,spc_x,r0,lsl #24\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 1);
+ ot(" mov r1,spc_x,lsr #24\n");
+ Cmp("r1", "r0", 0);
+ otb(" and spc_x,spc_x,#0xff\n");
+ break;
+
+ case 0x1E: // CMP X,abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ Cmp("spc_x", "r0", 0);
+ break;
+
+ case 0x3E: // CMP X,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+
+ MemHandler(0, 1, 1);
+ Cmp("spc_x", "r0", 0);
+ break;
+
+ case 0xC8: // CMP X,#00
+ ot(" ldrb r0,[spc_pc],#1\n");
+ Cmp("spc_x", "r0", 0);
+ break;
+
+ case 0x5E: // CMP Y,abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ ot(" mov r1,spc_ya,lsr #8\n");
+ Cmp("r1", "r0", 0);
+ break;
+
+ case 0x7E: // CMP Y,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" mov r1,spc_ya,lsr #8\n");
+ Cmp("r1", "r0", 0);
+ break;
+
+ case 0xAD: // CMP Y,#00
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" mov r1,spc_ya,lsr #8\n");
+ Cmp("r1", "r0", 0);
+ break;
+
+ case 0x1F: // JMP (abs+X)
+ AbsoluteX(0);
+ ot(" sub sp,sp,#8\n");
+ ot(" str r0,[sp,#4]\n");
+ MemHandler(0, 0, 0);
+ ot(" str r0,[sp]\n");
+ ot(" ldr r0,[sp,#4]\n");
+ ot(" add r0,r0,#1\n");
+ MemHandler(0, 0, 1);
+ ot(" ldr r1,[sp],#8\n");
+ ot(" orr r0,r1,r0,lsl #8\n");
+ ot(" add spc_pc,spc_ram,r0\n");
+ break;
+
+ case 0x5F: // JMP abs
+ //Absolute(0);
+ //ot(" add spc_pc,spc_ram,r0\n");
+ ot(" ldrb r0, [spc_pc], #1\n");
+ ot(" ldrb r14, [spc_pc], #1\n");
+ ot(" add spc_pc, r0, spc_ram\n");
+ ot(" add spc_pc, spc_pc, r14, lsl #8\n");
+ break;
+
+ case 0x20: // CLRP
+ ot(" bic spc_p,spc_p,#flag_d\n");
+ otb(" str spc_ram,[context,#iapu_directpage]\n");
+ break;
+
+ case 0x60: // CLRC
+ otb(" bic spc_p,spc_p,#flag_c\n");
+ break;
+
+ case 0xE0: // CLRV
+ otb(" bic spc_p,spc_p,#(flag_o|flag_h)\n");
+ break;
+
+ case 0x29: // AND dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" and r0,r0,r3\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x38: // AND dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ ot(" and r0,r0,r1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc,#-1]\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x39: // AND (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" and r0,r0,r3\n");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x2B: // ROL dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ Rol();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x2C: // ROL abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ Rol();
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x3B: // ROL dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ Rol();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x3C: // ROL A
+ ot(" and r0,spc_ya,#0xff\n");
+ Rol();
+ ot(" and r0,r0,#0xff\n");
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x2E: // CBNE dp,rel
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" and r1,spc_ya,#0xff\n");
+ ot(" cmp r0,r1\n");
+ ot(" addeq spc_pc,spc_pc,#1\n");
+ ot(" ldrnesb r0,[spc_pc],#1\n");
+ ot(" subne cycles,cycles,#%i\n", one_apu_cycle[current_cycles]*2);
+ ot(" addne spc_pc,spc_pc,r0\n");
+ break;
+
+ case 0xDE: // CBNE dp+X,rel
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ot(" and r1,spc_ya,#0xff\n");
+ ot(" cmp r0,r1\n");
+ ot(" addeq spc_pc,spc_pc,#1\n");
+ ot(" ldrnesb r0,[spc_pc],#1\n");
+ ot(" addne spc_pc,spc_pc,r0\n");
+ ot(" subne cycles,cycles,#%i\n", one_apu_cycle[current_cycles]*2);
+ break;
+
+ case 0x3D: // INC X
+ ot(" add spc_x,spc_x,#1\n");
+ ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xFC: // INC Y
+ ot(" mov r0,spc_ya,lsr #8\n");
+ ot(" add r0,r0,#1\n");
+ ot(" and r0,r0,#0xff\n");
+ SetZN8("r0");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ otb(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ break;
+
+ case 0x1D: // DEC X
+ ot(" sub spc_x,spc_x,#1\n");
+ ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xDC: // DEC Y
+ ot(" mov r0,spc_ya,lsr #8\n");
+ ot(" sub r0,r0,#1\n");
+ ot(" and r0,r0,#0xff\n");
+ SetZN8("r0");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ otb(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ break;
+
+ case 0xAB: // INC dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" add r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xAC: // INC abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ ot(" add r0,r0,#1\n");
+ SetZN8("r0");
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xBB: // INC dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ ot(" add r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xBC: // INC A
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" add r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" and r0,r0,#0xff\n");
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x8B: // DEC dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" sub r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x8C: // DEC abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ ot(" sub r0,r0,#1\n");
+ SetZN8("r0");
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x9B: // DEC dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ ot(" sub r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x9C: // DEC A
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" sub r0,r0,#1\n");
+ SetZN8("r0");
+ ot(" and r0,r0,#0xff\n");
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x49: // EOR dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" eor r0,r0,r3\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x58: // EOR dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ ot(" eor r0,r0,r1\n");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc,#-1]\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x59: // EOR (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" eor r0,r0,r3\n");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x4B: // LSR dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ Lsr();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x4C: // LSR abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ Lsr();
+ //ot(" ldmfd sp!,{r1}\n");
+ ot(" mov r1, r3\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x5B: // LSR dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ Lsr();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x5C: // LSR A
+ ot(" and r0,spc_ya,#0xff\n");
+ Lsr();
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x7D: // MOV A,X
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,spc_x\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xDD: // MOV A,Y
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,spc_ya,lsr #8\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0x5D: // MOV X,A
+ ot(" and spc_x,spc_ya,#0xff\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xFD: // MOV Y,A
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,spc_ya,lsl #8\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0x9D: // MOV X,SP
+ ot(" mov spc_x,spc_s\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xBD: // SP,X
+ otb(" mov spc_s,spc_x\n");
+ break;
+
+ case 0x6B: // ROR dp
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ Ror();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x6C: // ROR abs
+ Absolute(0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ MemHandler(0, 0, 0);
+ Ror();
+ ot(" mov r1, r3\n");
+ //ot(" ldmfd sp!,{r1}\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0x7B: // ROR dp+X
+ ot(" ldrb r0,[spc_pc]\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ Ror();
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x7C: // ROR A
+ ot(" and r0,spc_ya,#0xff\n");
+ Ror();
+ ot(" mov spc_ya,spc_ya,lsr #8\n");
+ otb(" orr spc_ya,r0,spc_ya,lsl #8\n");
+ break;
+
+ case 0x6E: // DBNZ dp,rel
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" sub r0,r0,#1\n");
+ ot(" tst r0,r0\n");
+ ot(" addeq spc_pc,spc_pc,#1\n");
+ ot(" ldrnesb r2,[spc_pc],#1\n");
+ ot(" addne spc_pc,spc_pc,r2\n");
+ ot(" subne cycles,cycles,#%i\n", one_apu_cycle[current_cycles]*2);
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xFE: // DBNZ Y,rel
+ ot(" sub spc_ya,spc_ya,#0x100\n");
+ ot(" mov spc_ya,spc_ya,lsl #16\n");
+ ot(" mov spc_ya,spc_ya,lsr #16\n");
+ ot(" movs r0,spc_ya,lsr #8\n");
+ ot(" addeq spc_pc,spc_pc,#1\n");
+ ot(" ldrnesb r0,[spc_pc],#1\n");
+ ot(" addne spc_pc,spc_pc,r0\n");
+ ot(" subne cycles,cycles,#%i\n", one_apu_cycle[current_cycles]*2);
+ break;
+
+ case 0x6F: // RET
+ PopW();
+ ot(" add spc_pc,spc_ram,r0\n");
+ break;
+
+ case 0x7F: // RETI
+ Pop("spc_p");
+ ot(" and r0,spc_p,#(flag_z|flag_n)\n");
+ ot(" eor r0,r0,#flag_z\n");
+ ot(" orr spc_p,spc_p,r0,lsl #24\n");
+ ot(" tst spc_p,#flag_d\n");
+ ot(" addne r0,spc_ram,#0x100\n");
+ ot(" moveq r0,spc_ram\n");
+ ot(" str r0,[context,#iapu_directpage]\n");
+ PopW();
+ ot(" add spc_pc,spc_ram,r0\n");
+ break;
+
+ case 0x89: // ADC dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ //ot(" mov r1, r3\n");
+ Adc("r0", "r3");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x98: // ADC dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ Adc("r0", "r1");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc,#-1]\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x99: // ADC (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ //ot(" mov r1, r3\n");
+ Adc("r0", "r3");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x8D: // MOV Y,#00 //-REVISAR
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN8("r0");
+ break;
+
+ case 0x8F: // MOV dp,#00 //-REVISAR
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0x9E: // DIV YA,X
+ ot(" tst spc_x,spc_x @ div by 0?\n");
+ ot(" orreq spc_ya,spc_ya,#0xff00\n");
+ ot(" orreq spc_ya,spc_ya,#0x00ff\n");
+ ot(" orreq spc_p,spc_p,#flag_o\n");
+ ot(" beq 1002f\n");
+ ot(" bic spc_p,spc_p,#flag_o\n");
+
+ // division algo from Cyclone (result in r3, remainder instead of divident)
+ ot("@ Divide spc_ya by spc_x\n");
+ ot(" mov r3,#0\n");
+ ot(" mov r1,spc_x\n");
+ ot("\n");
+
+ //
+ /*ot("@ Shift up divisor till it's just less than numerator\n");
+ ot("divshift:\n");
+ ot(" cmp r1,spc_ya,lsr #1\n");
+ ot(" movls r1,r1,lsl #1\n");
+ ot(" bcc divshift\n");
+ ot("\n");*/
+
+ //optimised version of code provided by William Blair
+ ot("@ Shift up divisor till it's just less than numerator\n");
+ ot("cmp spc_ya,r1,lsl #8\n");
+ ot("movge r1,r1,lsl #8\n");
+ ot("cmp spc_ya,r1,lsl #4\n");
+ ot("movge r1,r1,lsl #4\n");
+ ot("cmp spc_ya,r1,lsl #2\n");
+ ot("movge r1,r1,lsl #2\n");
+ ot("cmp spc_ya,r1,lsl #1\n");
+ ot("movge r1,r1,lsl #1\n");
+
+ ot("1001:\n");
+ ot(" cmp spc_ya,r1\n");
+ ot(" adc r3,r3,r3 ;@ Double r3 and add 1 if carry set\n");
+ ot(" subcs spc_ya,spc_ya,r1\n");
+ ot(" teq r1,spc_x\n");
+ ot(" movne r1,r1,lsr #1\n");
+ ot(" bne 1001b\n");
+ ot("\n");
+
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" and r3,r3,#0xff\n");
+ ot(" orr spc_ya,r3,spc_ya,lsl #8\n");
+
+ ot("1002:\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0x9F: // XCN A
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" mov r1,r0,lsl #28\n");
+ ot(" orr r0,r1,r0,lsl #20\n");
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0,lsr #24\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xA9: // SBC dp(dest), dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" ldrb r0,[spc_pc]\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ //ot(" mov r1, r3\n");
+ Sbc("r0", "r3");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xB8: // SBC dp,#00
+ ot(" ldrb r0,[spc_pc,#1]\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#2\n");
+ Sbc("r0", "r1");
+ SetZN8("r0");
+ ot(" ldrb r1,[spc_pc,#-1]\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xB9: // SBC (X),(Y)
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 0);
+ //ot(" stmfd sp!,{r0}\n");
+ ot(" mov r3, r0\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 0);
+ //ot(" ldmfd sp!,{r1}\n");
+ //ot(" mov r1, r3\n");
+ Sbc("r0", "r3");
+ SetZN8("r0");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xAF: // MOV (X)+, A
+ ot(" mov r0,spc_ya\n");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ ot(" add spc_x,spc_x,#1\n");
+ otb(" and spc_x,spc_x,#0xff\n");
+ break;
+
+ case 0xBE: // DAS
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" and r1,spc_ya,#0x0f\n");
+ ot(" cmp r1,#9\n");
+ ot(" subhi r0,r0,#6\n");
+ ot(" tstls spc_p,#flag_h\n");
+ ot(" subeq r0,r0,#6\n");
+ ot(" cmp r0,#0x9f\n");
+ ot(" bhi 2001f\n");
+ ot(" tst spc_p,#flag_c\n");
+ ot(" beq 2001f\n");
+ ot(" orr spc_p,spc_p,#flag_c\n");
+ ot(" b 2002f\n");
+ ot("2001:\n"); // tens
+ ot(" sub r0,r0,#0x60\n");
+ ot(" bic spc_p,spc_p,#flag_c\n");
+
+ ot("2002:\n"); // end
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xBF: // MOV A,(X)+
+ ot(" mov r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0\n");
+ ot(" add spc_x,spc_x,#1\n");
+ ot(" and spc_x,spc_x,#0xff\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xC0: // DI
+ otb(" bic spc_p,spc_p,#flag_i\n");
+ break;
+
+ case 0xA0: // EI
+ otb(" orr spc_p,spc_p,#flag_i\n");
+ break;
+
+ case 0xC4: // MOV dp,A
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xC5: // MOV abs,A
+ Absolute(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xC6: // MOV (X),A
+ ot(" mov r0,spc_ya\n");
+ ot(" mov r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xC7: // MOV (dp+X),A
+ IndexedXIndirect(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xC9: // MOV abs,X
+ Absolute(1);
+ ot(" mov r0,spc_x\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xCB: // MOV dp,Y
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xCC: // MOV abs,Y
+
+ Absolute(1);
+ ot(" mov r0,spc_ya,lsr #8\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xCD: // MOV X,#00
+ ot(" ldrb spc_x,[spc_pc],#1\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xCF: // MUL YA
+ ot(" mov r0,spc_ya,lsr #8\n");
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" mul spc_ya,r0,spc_ya\n");
+ SetZN16("spc_ya");
+ break;
+
+ case 0xD4: // MOV dp+X, A
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xD5: // MOV abs+X,A
+ AbsoluteX(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xD6: // MOV abs+Y,A
+ AbsoluteY(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xD7: // MOV (dp)+Y,A
+ IndirectIndexedY(1);
+ ot(" mov r0,spc_ya\n");
+ MemHandler(1, 0, 1);
+ break;
+
+ case 0xD8: // MOV dp,X
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xD9: // MOV dp+Y,X
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_x\n");
+ ot(" add r1,r1,spc_ya,lsr #8\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xDB: // MOV dp+X,Y
+ ot(" ldrb r1,[spc_pc],#1\n");
+ ot(" mov r0,spc_ya,lsr #8\n");
+ ot(" add r1,r1,spc_x\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xDF: // DAA
+ ot(" and r0,spc_ya,#0xff\n");
+ ot(" and r1,spc_ya,#0x0f\n");
+ ot(" cmp r1,#9\n");
+ ot(" addhi r0,r0,#6\n");
+ ot(" bls 3001f\n");
+ ot(" cmphi r0,#0xf0\n");
+ ot(" orrhi spc_p,spc_p,#flag_c\n");
+ ot(" b 3002f\n");
+ ot("3001:\n"); // testHc
+ ot(" tst spc_p,#flag_h\n");
+ ot(" addne r0,r0,#6\n");
+ ot(" beq 3002f\n");
+ ot(" cmp r0,#0xf0\n");
+ ot(" orrhi spc_p,spc_p,#flag_c\n");
+ ot("3002:\n"); // test2
+ ot(" tst spc_p,#flag_c\n");
+ ot(" addne r0,r0,#0x60\n");
+ ot(" bne 3003f\n");
+ ot(" cmp r0,#0x9f\n");
+ ot(" addhi r0,r0,#0x60\n");
+ ot(" orrhi spc_p,spc_p,#flag_c\n");
+ ot(" bicls spc_p,spc_p,#flag_c\n");
+ ot("3003:\n"); // end
+ ot(" and spc_ya,spc_ya,#0xff00\n");
+ ot(" orr spc_ya,spc_ya,r0\n");
+ SetZN8("spc_ya");
+ break;
+
+ case 0xE9: // MOV X, abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ ot(" mov spc_x,r0\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xEB: // MOV Y,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN8("r0");
+ break;
+
+ case 0xEC: // MOV Y,abs
+ Absolute(0);
+ MemHandler(0, 0, 1);
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN8("r0");
+ break;
+
+ case 0xF8: // MOV X,dp
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 1);
+ ot(" mov spc_x,r0\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xF9: // MOV X,dp+Y
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_ya,lsr #8\n");
+ MemHandler(0, 1, 1);
+ ot(" mov spc_x,r0\n");
+ SetZN8("spc_x");
+ break;
+
+ case 0xFA: // MOV dp(dest),dp(src)
+ ot(" ldrb r0,[spc_pc],#1\n");
+ MemHandler(0, 1, 0);
+ ot(" ldrb r1,[spc_pc],#1\n");
+ MemHandler(1, 1, 1);
+ break;
+
+ case 0xFB: // MOV Y,dp+X
+ ot(" ldrb r0,[spc_pc],#1\n");
+ ot(" add r0,r0,spc_x\n");
+ MemHandler(0, 1, 1);
+ ot(" and spc_ya,spc_ya,#0xff\n");
+ ot(" orr spc_ya,spc_ya,r0,lsl #8\n");
+ SetZN8("r0");
+ break;
+ }
+
+ //tmp_epilogue();
+ ot(" subs cycles,cycles,#%i\n", S9xAPUCycles[opcode] * one_apu_cycle[current_cycles]);
+ ot(" ldrgeb opcode,[spc_pc],#1\n");
+ flush_buffer();
+ ot(" ldrge pc,[opcodes,opcode,lsl #2]\n");
+ ot(" b spc700End\n");
+
+ printf("\b\b");
+ }
+
+
+ ot("\n\n");
+
+}
+
+
+void printJumpTable(int apu_cycles) {
+ int i;
+ ot("@ -------------------------- Jump Table %i --------------------------\n", apu_cycles);
+ ot("Spc700JumpTab_%i:\n", apu_cycles);
+
+ for (i=0; i < 0x100; i++)
+ {
+ if ((i&7)==0) ot(" .long ");
+
+ ot("Apu%02X_%i", i, apu_cycles);
+
+ if ((i&7)==7) ot(" @ %02x\n",i-7);
+ else if (i+1 < 0x100) ot(", ");
+ }
+
+}
+
+int main()
+{
+ printf("\n notaz's SPC700 Emulator v%s - Core Creator\n\n", VERSION);
+
+ // Open the assembly file
+ AsmFile=fopen("spc700a.s", "wt"); if (AsmFile==NULL) return 1;
+
+ ot("@ notaz's SPC700 Emulator v%s - Assembler Output\n\n", VERSION);
+ ot("@ (c) Copyright 2006 notaz, All rights reserved.\n\n");
+ ot("@ Modified by bitrider 2010 - 2011\n\n");
+ ot("@ this is a rewrite of spc700.cpp in ARM asm, inspired by other asm CPU cores like\n");
+ ot("@ Cyclone and DrZ80. It is meant to be used in Snes9x emulator ports for ARM platforms.\n\n");
+ ot("@ the code is released under Snes9x license. See spcgen.c or any other source file\n@ from Snes9x source tree.\n\n\n");
+
+ PrintFramework();
+
+ ot(" .align 4\n");
+
+ for (current_cycles=0; current_cycles < (sizeof(one_apu_cycle) / sizeof(int)); current_cycles++) {
+ printOpcodes(one_apu_cycle[current_cycles]);
+ printJumpTable(one_apu_cycle[current_cycles]);
+ }
+
+
+ fclose(AsmFile); AsmFile=NULL;
+
+ printf("Assembling...\n");
+ // Assemble the file
+ //system("as -marmv4t -mthumb-interwork -o spc700a.o spc700a.S");
+ printf("Done!\n\n");
+
+ return 0;
+}
diff --git a/src/spc700/spcgen.dsp b/src/spc700/spcgen.dsp
new file mode 100644
index 0000000..a6bf264
--- /dev/null
+++ b/src/spc700/spcgen.dsp
@@ -0,0 +1,88 @@
+# Microsoft Developer Studio Project File - Name="spcgen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=spcgen - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "spcgen.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "spcgen.mak" CFG="spcgen - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "spcgen - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "spcgen - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "spcgen - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF "$(CFG)" == "spcgen - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "spcgen - Win32 Release"
+# Name "spcgen - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\spcgen.c
+# End Source File
+# End Target
+# End Project
diff --git a/src/spc700/spcgen.dsw b/src/spc700/spcgen.dsw
new file mode 100644
index 0000000..7b947fc
--- /dev/null
+++ b/src/spc700/spcgen.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "spcgen"=.\spcgen.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/src/spc700/spcgen.ncb b/src/spc700/spcgen.ncb
new file mode 100644
index 0000000..22b2108
--- /dev/null
+++ b/src/spc700/spcgen.ncb
Binary files differ
diff --git a/src/spc700/spcgen.opt b/src/spc700/spcgen.opt
new file mode 100644
index 0000000..673f065
--- /dev/null
+++ b/src/spc700/spcgen.opt
Binary files differ
diff --git a/src/spc700/spcgen.plg b/src/spc700/spcgen.plg
new file mode 100644
index 0000000..8db8f5e
--- /dev/null
+++ b/src/spc700/spcgen.plg
@@ -0,0 +1,32 @@
+<html>
+<body>
+<pre>
+<h1>Build Log</h1>
+<h3>
+--------------------Configuration: spcgen - Win32 Debug--------------------
+</h3>
+<h3>Command Lines</h3>
+Creating temporary file "C:\DOCUME~1\Dave\LOCALS~1\Temp\RSP2C.tmp" with contents
+[
+/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Debug/spcgen.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
+"C:\Downloads\squidgesnes0392src\squidgesnes\spc700\spcgen.c"
+]
+Creating command line "cl.exe @C:\DOCUME~1\Dave\LOCALS~1\Temp\RSP2C.tmp"
+Creating temporary file "C:\DOCUME~1\Dave\LOCALS~1\Temp\RSP2E.tmp" with contents
+[
+kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/spcgen.pdb" /debug /machine:I386 /out:"Debug/spcgen.exe" /pdbtype:sept
+.\Debug\spcgen.obj
+]
+Creating command line "link.exe @C:\DOCUME~1\Dave\LOCALS~1\Temp\RSP2E.tmp"
+<h3>Output Window</h3>
+Compiling...
+spcgen.c
+Linking...
+
+
+
+<h3>Results</h3>
+spcgen.exe - 0 error(s), 0 warning(s)
+</pre>
+</body>
+</html>