From 6fb0c7a7a53e1eba7a0f5dc5b1ade312a0d76119 Mon Sep 17 00:00:00 2001 From: Toad King Date: Thu, 14 Jun 2012 03:21:06 -0400 Subject: initial pocketsnes commit --- src/spc700/debug/apu.h | 195 ++++ src/spc700/debug/apumem.h | 222 ++++ src/spc700/debug/port.h | 497 +++++++++ src/spc700/debug/spc700.cpp | 2600 +++++++++++++++++++++++++++++++++++++++++++ src/spc700/debug/spc700.h | 172 +++ 5 files changed, 3686 insertions(+) create mode 100644 src/spc700/debug/apu.h create mode 100644 src/spc700/debug/apumem.h create mode 100644 src/spc700/debug/port.h create mode 100644 src/spc700/debug/spc700.cpp create mode 100644 src/spc700/debug/spc700.h (limited to 'src/spc700/debug') 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 + +#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 + +#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 +#else +#include +#include +#endif +#else // #ifndef STORM +#include +#include +#endif + +//#include + +#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 +#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 -- cgit v1.2.3