📄 spc700.cpp
字号:
/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary@daniver.demon.co.uk) 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@daniver.demon.co.uk). * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: 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 "spc700.h"#include "memmap.h"#include "display.h"#include "cpuexec.h"#include "apu.h"// SPC700/Sound DSP chips have a 24.57MHz crystal on their PCB.#ifdef NO_INLINE_SET_GETuint8 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"#endifSTART_EXTERN_Cextern 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 (*(IAPU.PC + 1))#define OP2 (*(IAPU.PC + 2))#ifdef SPC700_SHUTDOWN#define APUShutdown() \ if (Settings.Shutdown && (IAPU.PC == IAPU.WaitAddress1 || IAPU.PC == IAPU.WaitAddress2)) \ { \ if (IAPU.WaitCounter == 0) \ { \ if (!ICPU.CPUExecuting) \ APU.Cycles = CPU.Cycles = CPU.NextEvent; \ else \ IAPU.APUExecuting = FALSE; \ } \ else \ if (IAPU.WaitCounter >= 2) \ IAPU.WaitCounter = 1; \ else \ IAPU.WaitCounter--; \ }#else#define APUShutdown()#endif#define APUSetZN8(b)\ IAPU._Zero = (b);#define APUSetZN16(w)\ IAPU._Zero = ((w) != 0) | ((w) >> 8);void STOP (char *s){ char buffer[100];#ifdef DEBUGGER S9xAPUOPrint (buffer, IAPU.PC - IAPU.RAM);#endif sprintf (String, "Sound CPU in unknown state executing %s at %04X\n%s\n", s, IAPU.PC - IAPU.RAM, buffer); S9xMessage (S9X_ERROR, S9X_APU_STOPPED, String); APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; IAPU.APUExecuting = FALSE;#ifdef DEBUGGER CPU.Flags |= DEBUG_MODE_FLAG;#else S9xExit ();#endif}#define TCALL(n)\{\ PushW (IAPU.PC - IAPU.RAM + 1); \ IAPU.PC = IAPU.RAM + (APU.ExtraRAM [((15 - n) << 1)] + \ (APU.ExtraRAM [((15 - n) << 1) + 1] << 8)); \}// XXX: HalfCarry#define SBC(a,b)\Int16 = (short) (a) - (short) (b) + (short) (APUCheckCarry ()) - 1;\APUClearHalfCarry ();\IAPU._Carry = Int16 >= 0;\if ((((a) ^ (b)) & 0x80) && (((a) ^ (uint8) Int16) & 0x80))\ APUSetOverflow ();\else \ APUClearOverflow (); \(a) = (uint8) Int16;\APUSetZN8 ((uint8) Int16);// XXX: HalfCarry#define ADC(a,b)\Work16 = (a) + (b) + APUCheckCarry();\APUClearHalfCarry ();\IAPU._Carry = Work16 >= 0x100; \if (~((a) ^ (b)) & ((b) ^ (uint8) Work16) & 0x80)\ APUSetOverflow ();\else \ APUClearOverflow (); \(a) = (uint8) Work16;\APUSetZN8 ((uint8) Work16);#define CMP(a,b)\Int16 = (short) (a) - (short) (b);\IAPU._Carry = Int16 >= 0;\APUSetZN8 ((uint8) Int16);#define ASL(b)\ IAPU._Carry = ((b) & 0x80) != 0; \ (b) <<= 1;\ APUSetZN8 (b);#define LSR(b)\ IAPU._Carry = (b) & 1;\ (b) >>= 1;\ APUSetZN8 (b);#define ROL(b)\ Work16 = ((b) << 1) | APUCheckCarry (); \ IAPU._Carry = Work16 >= 0x100; \ (b) = (uint8) Work16; \ APUSetZN8 (b);#define ROR(b)\ Work16 = (b) | ((uint16) APUCheckCarry () << 8); \ IAPU._Carry = (uint8) Work16 & 1; \ Work16 >>= 1; \ (b) = (uint8) Work16; \ APUSetZN8 (b);#define Push(b)\ *(IAPU.RAM + 0x100 + APURegisters.S) = b;\ APURegisters.S--;#define Pop(b)\ APURegisters.S++;\ (b) = *(IAPU.RAM + 0x100 + APURegisters.S);#ifdef FAST_LSB_WORD_ACCESS#define PushW(w)\ *(uint16 *) (IAPU.RAM + 0xff + APURegisters.S) = w;\ APURegisters.S -= 2;#define PopW(w)\ APURegisters.S += 2;\ w = *(uint16 *) (IAPU.RAM + 0xff + APURegisters.S);#else#define PushW(w)\ *(IAPU.RAM + 0xff + APURegisters.S) = w;\ *(IAPU.RAM + 0x100 + APURegisters.S) = (w >> 8);\ APURegisters.S -= 2;#define PopW(w)\ APURegisters.S += 2; \ (w) = *(IAPU.RAM + 0xff + APURegisters.S) + (*(IAPU.RAM + 0x100 + APURegisters.S) << 8);#endif#define Relative()\ Int8 = OP1;\ Int16 = (int) (IAPU.PC + 2 - IAPU.RAM) + Int8;#define Relative2()\ Int8 = OP2;\ Int16 = (int) (IAPU.PC + 3 - IAPU.RAM) + Int8;#ifdef FAST_LSB_WORD_ACCESS#define IndexedXIndirect()\ IAPU.Address = *(uint16 *) (IAPU.DirectPage + ((OP1 + APURegisters.X) & 0xff));#define Absolute()\ IAPU.Address = *(uint16 *) (IAPU.PC + 1);#define AbsoluteX()\ IAPU.Address = *(uint16 *) (IAPU.PC + 1) + APURegisters.X;#define AbsoluteY()\ IAPU.Address = *(uint16 *) (IAPU.PC + 1) + APURegisters.YA.B.Y;#define MemBit()\ IAPU.Address = *(uint16 *) (IAPU.PC + 1);\ IAPU.Bit = (uint8)(IAPU.Address >> 13);\ IAPU.Address &= 0x1fff;#define IndirectIndexedY()\ IAPU.Address = *(uint16 *) (IAPU.DirectPage + OP1) + APURegisters.YA.B.Y;#else#define IndexedXIndirect()\ IAPU.Address = *(IAPU.DirectPage + ((OP1 + APURegisters.X) & 0xff)) + \ (*(IAPU.DirectPage + ((OP1 + APURegisters.X + 1) & 0xff)) << 8);#define Absolute()\ IAPU.Address = OP1 + (OP2 << 8);#define AbsoluteX()\ IAPU.Address = OP1 + (OP2 << 8) + APURegisters.X;#define AbsoluteY()\ IAPU.Address = OP1 + (OP2 << 8) + APURegisters.YA.B.Y;#define MemBit()\ IAPU.Address = OP1 + (OP2 << 8);\ IAPU.Bit = (int8) (IAPU.Address >> 13);\ IAPU.Address &= 0x1fff;#define IndirectIndexedY()\ IAPU.Address = *(IAPU.DirectPage + OP1) + \ (*(IAPU.DirectPage + OP1 + 1) << 8) + \ APURegisters.YA.B.Y;#endifvoid Apu00 (){// NOP IAPU.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 (); PushW (IAPU.PC + 3 - IAPU.RAM); IAPU.PC = IAPU.RAM + IAPU.Address;}void Apu4F () // PCALL $XX{ Work8 = OP1; PushW (IAPU.PC + 2 - IAPU.RAM); IAPU.PC = IAPU.RAM + 0xff00 + Work8;}#define SET(b) \S9xAPUSetByteZ ((uint8) (S9xAPUGetByteZ (OP1 ) | (1 << (b))), OP1); \IAPU.PC += 2void 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); \IAPU.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))) \{ \ IAPU.PC = IAPU.RAM + (uint16) Int16; \ APU.Cycles += IAPU.TwoCycles; \} \else \ IAPU.PC += 3void 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)))) \{ \ IAPU.PC = IAPU.RAM + (uint16) Int16; \ APU.Cycles += IAPU.TwoCycles; \} \else \ IAPU.PC += 3void 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 APURegisters.YA.B.A |= S9xAPUGetByteZ (OP1); APUSetZN8 (APURegisters.YA.B.A); IAPU.PC += 2;}void Apu05 (){// OR A,abs Absolute (); APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); APUSetZN8 (APURegisters.YA.B.A); IAPU.PC += 3;}void Apu06 (){// OR A,(X) APURegisters.YA.B.A |= S9xAPUGetByteZ (APURegisters.X); APUSetZN8 (APURegisters.YA.B.A); IAPU.PC++;}void Apu07 (){// OR A,(dp+X) IndexedXIndirect (); APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); APUSetZN8 (APURegisters.YA.B.A); IAPU.PC += 2;}void Apu08 (){// OR A,#00 APURegisters.YA.B.A |= OP1; APUSetZN8 (APURegisters.YA.B.A); IAPU.PC += 2;}void Apu09 (){// OR dp(dest),dp(src) Work8 = S9xAPUGetByteZ (OP1); Work8 |= S9xAPUGetByteZ (OP2); S9xAPUSetByteZ (Work8, OP2); APUSetZN8 (Work8); IAPU.PC += 3;}void Apu14 (){// OR A,dp+X APURegisters.YA.B.A |= S9xAPUGetByteZ (OP1 + APURegisters.X); APUSetZN8 (APURegisters.YA.B.A); IAPU.PC += 2;}void Apu15 (){// OR A,abs+X AbsoluteX (); APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); APUSetZN8 (APURegisters.YA.B.A); IAPU.PC += 3;}void Apu16 (){// OR A,abs+Y AbsoluteY (); APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); APUSetZN8 (APURegisters.YA.B.A); IAPU.PC += 3;}void Apu17 (){// OR A,(dp)+Y IndirectIndexedY (); APURegisters.YA.B.A |= S9xAPUGetByte (IAPU.Address); APUSetZN8 (APURegisters.YA.B.A); IAPU.PC += 2;}void Apu18 (){// OR dp,#00 Work8 = OP1; Work8 |= S9xAPUGetByteZ (OP2); S9xAPUSetByteZ (Work8, OP2); APUSetZN8 (Work8); IAPU.PC += 3;}void Apu19 (){// OR (X),(Y) Work8 = S9xAPUGetByteZ (APURegisters.X) | S9xAPUGetByteZ (APURegisters.YA.B.Y); APUSetZN8 (Work8); S9xAPUSetByteZ (Work8, APURegisters.X); IAPU.PC++;}void Apu0A (){// OR1 C,membit MemBit (); if (!APUCheckCarry ()) { if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) APUSetCarry (); } IAPU.PC += 3;}void Apu2A (){// OR1 C,not membit MemBit (); if (!APUCheckCarry ()) { if (!(S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) APUSetCarry (); } IAPU.PC += 3;}void Apu4A (){// AND1 C,membit MemBit (); if (APUCheckCarry ()) { if (!(S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) APUClearCarry (); } IAPU.PC += 3;}void Apu6A (){// AND1 C, not membit MemBit (); if (APUCheckCarry ()) { if ((S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) APUClearCarry (); } IAPU.PC += 3;}void Apu8A (){// EOR1 C, membit MemBit (); if (APUCheckCarry ()) { if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) APUClearCarry (); } else { if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) APUSetCarry (); } IAPU.PC += 3;}void ApuAA (){// MOV1 C,membit MemBit (); if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) APUSetCarry (); else APUClearCarry (); IAPU.PC += 3;}void ApuCA (){// MOV1 membit,C MemBit (); if (APUCheckCarry ()) { S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) | (1 << IAPU.Bit), IAPU.Address); } else { S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) & ~(1 << IAPU.Bit), IAPU.Address); } IAPU.PC += 3;}void ApuEA (){// NOT1 membit MemBit (); S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) ^ (1 << IAPU.Bit), IAPU.Address); IAPU.PC += 3;}void Apu0B (){// ASL dp Work8 = S9xAPUGetByteZ (OP1); ASL (Work8); S9xAPUSetByteZ (Work8, OP1); IAPU.PC += 2;}void Apu0C (){// ASL abs Absolute (); Work8 = S9xAPUGetByte (IAPU.Address); ASL (Work8); S9xAPUSetByte (Work8, IAPU.Address); IAPU.PC += 3;}void Apu1B (){// ASL dp+X Work8 = S9xAPUGetByteZ (OP1 + APURegisters.X); ASL (Work8); S9xAPUSetByteZ (Work8, OP1 + APURegisters.X); IAPU.PC += 2;}void Apu1C (){// ASL A ASL (APURegisters.YA.B.A); IAPU.PC++;}void Apu0D (){// PUSH PSW S9xAPUPackStatus (); Push (APURegisters.P); IAPU.PC++;}void Apu2D (){// PUSH A Push (APURegisters.YA.B.A); IAPU.PC++;}void Apu4D (){// PUSH X Push (APURegisters.X); IAPU.PC++;}void Apu6D (){// PUSH Y Push (APURegisters.YA.B.Y); IAPU.PC++;}void Apu8E (){// POP PSW Pop (APURegisters.P); S9xAPUUnpackStatus (); if (APUCheckDirectPage ()) IAPU.DirectPage = IAPU.RAM + 0x100; else IAPU.DirectPage = IAPU.RAM; IAPU.PC++;}void ApuAE (){// POP A Pop (APURegisters.YA.B.A); IAPU.PC++;}void ApuCE (){// POP X Pop (APURegisters.X); IAPU.PC++;}void ApuEE (){// POP Y Pop (APURegisters.YA.B.Y); IAPU.PC++;}void Apu0E (){// TSET1 abs Absolute (); Work8 = S9xAPUGetByte (IAPU.Address); S9xAPUSetByte (Work8 | APURegisters.YA.B.A, IAPU.Address); Work8 &= APURegisters.YA.B.A; APUSetZN8 (Work8); IAPU.PC += 3;}void Apu4E (){// TCLR1 abs Absolute (); Work8 = S9xAPUGetByte (IAPU.Address); S9xAPUSetByte (Work8 & ~APURegisters.YA.B.A, IAPU.Address); Work8 &= APURegisters.YA.B.A; APUSetZN8 (Work8); IAPU.PC += 3;}void Apu0F (){// BRK#if 0 STOP ("BRK");#else PushW (IAPU.PC + 1 - IAPU.RAM); S9xAPUPackStatus ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -