//1// Copyright (c) 2004 K. Wilkins2//3// This software is provided 'as-is', without any express or implied warranty.4// In no event will the authors be held liable for any damages arising from5// the use of this software.6//7// Permission is granted to anyone to use this software for any purpose,8// including commercial applications, and to alter it and redistribute it9// freely, subject to the following restrictions:10//11// 1. The origin of this software must not be misrepresented; you must not12// claim that you wrote the original software. If you use this software13// in a product, an acknowledgment in the product documentation would be14// appreciated but is not required.15//16// 2. Altered source versions must be plainly marked as such, and must not17// be misrepresented as being the original software.18//19// 3. This notice may not be removed or altered from any source distribution.20//2122//////////////////////////////////////////////////////////////////////////////23// Handy - An Atari Lynx Emulator //24// Copyright (c) 1996,1997 //25// K. Wilkins //26//////////////////////////////////////////////////////////////////////////////27// 65C02 Emulation class //28//////////////////////////////////////////////////////////////////////////////29// //30// This class emulates a 65C02 processor. It is interfaced to the rest of //31// the system via the PEEK/POKE macros and a number of global variables //32// //33// K. Wilkins //34// August 1997 //35// //36//////////////////////////////////////////////////////////////////////////////37// Revision History: //38// ----------------- //39// //40// 01Aug1997 KW Document header added & class documented. //41// //42//////////////////////////////////////////////////////////////////////////////4344#ifndef C65C02_H45#define C65C02_H4647//#include <crtdbg.h>48//#define TRACE_CPU4950#ifdef TRACE_CPU5152#define TRACE_CPU0(msg) _RPT1(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",gSystemCycleCount)53#define TRACE_CPU1(msg,arg1) _RPT2(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",arg1,gSystemCycleCount)54#define TRACE_CPU2(msg,arg1,arg2) _RPT3(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",arg1,arg2,gSystemCycleCount)55#define TRACE_CPU3(msg,arg1,arg2,arg3) _RPT4(_CRT_WARN,"C65C02::"msg" (Time=%012d)\n",arg1,arg2,arg3,gSystemCycleCount)5657#else5859#define TRACE_CPU0(msg)60#define TRACE_CPU1(msg,arg1)61#define TRACE_CPU2(msg,arg1,arg2)62#define TRACE_CPU3(msg,arg1,arg2,arg3)6364#endif6566//67// Handy definitions68//6970#define NMI_VECTOR 0xfffa71#define BOOT_VECTOR 0xfffc72#define IRQ_VECTOR 0xfffe7374#define MAX_CPU_BREAKPOINTS 87576//77// ACCESS MACROS78//7980//#define CPU_PEEK(m) (mSystem.Peek_CPU(m))81//#define CPU_PEEKW(m) (mSystem.PeekW_CPU(m))82//#define CPU_POKE(m1,m2) (mSystem.Poke_CPU(m1,m2))8384#define CPU_PEEK(m) (((m<0xfc00)?mRamPointer[m]:mSystem.Peek_CPU(m)))85#define CPU_PEEKW(m) (((m<0xfc00)?(mRamPointer[m]+(mRamPointer[m+1]<<8)):mSystem.PeekW_CPU(m)))86#define CPU_POKE(m1,m2) {if(m1<0xfc00) mRamPointer[m1]=m2; else mSystem.Poke_CPU(m1,m2);}878889enum { illegal=0,90accu,91imm,92absl,93zp,94zpx,95zpy,96absx,97absy,98iabsx,99impl,100rel,101zrel,102indx,103indy,104iabs,105ind106};107108typedef struct109{110int PS; // Processor status register 8 bits111int A; // Accumulator 8 bits112int X; // X index register 8 bits113int Y; // Y index register 8 bits114int SP; // Stack Pointer 8 bits115int Opcode; // Instruction opcode 8 bits116int Operand;// Intructions operand 16 bits117int PC; // Program Counter 16 bits118bool NMI;119bool IRQ;120bool WAIT;121}C6502_REGS;122123//124// The CPU emulation macros125//126#include "c6502mak.h"127//128// The CPU emulation macros129//130131class C65C02132{133public:134C65C02(CSystem& parent)135:mSystem(parent)136{137TRACE_CPU0("C65C02()");138// Compute the BCD lookup table139for(uint16 t=0;t<256;++t)140{141mBCDTable[0][t]=((t >> 4) * 10) + (t & 0x0f);142mBCDTable[1][t]=(((t % 100) / 10) << 4) | (t % 10);143}144Reset();145146}147148~C65C02()149{150TRACE_CPU0("~C65C02()");151}152153public:154void Reset();155void Update();156157void SetRegs(C6502_REGS ®s);158void GetRegs(C6502_REGS ®s);159160161inline int GetPC() { return mPC; }162163template<bool isReader>void SyncState(NewState *ns);164165private:166CSystem &mSystem;167168// CPU Flags & status169170int mA; // Accumulator 8 bits171int mX; // X index register 8 bits172int mY; // Y index register 8 bits173int mSP; // Stack Pointer 8 bits174int mOpcode; // Instruction opcode 8 bits175int mOperand; // Intructions operand 16 bits176int mPC; // Program Counter 16 bits177178int mN; // N flag for processor status register179int mV; // V flag for processor status register180int mB; // B flag for processor status register181int mD; // D flag for processor status register182int mI; // I flag for processor status register183int mZ; // Z flag for processor status register184int mC; // C flag for processor status register185186int mIRQActive;187188uint8 *mRamPointer;189190// Associated lookup tables191192int mBCDTable[2][256];193194//195// Opcode prototypes196//197198private:199200// Answers value of the Processor Status register201INLINE int PS() const202{203uint8 ps = 0x20;204if(mN) ps|=0x80;205if(mV) ps|=0x40;206if(mB) ps|=0x10;207if(mD) ps|=0x08;208if(mI) ps|=0x04;209if(mZ) ps|=0x02;210if(mC) ps|=0x01;211return ps;212}213214215// Change the processor flags to correspond to the given value216INLINE void PS(int ps)217{218mN=ps&0x80;219mV=ps&0x40;220mB=ps&0x10;221mD=ps&0x08;222mI=ps&0x04;223mZ=ps&0x02;224mC=ps&0x01;225}226227};228229230#endif231232233