2019-02-11 19:18:47 -05:00
# include "stdafx.h"
# include "CpuTypes.h"
# include "Cpu.h"
2019-02-11 22:41:34 -05:00
# include "MemoryManager.h"
2019-02-11 19:18:47 -05:00
2019-02-11 22:41:34 -05:00
Cpu : : Cpu ( shared_ptr < MemoryManager > memoryManager )
2019-02-11 19:18:47 -05:00
{
typedef Cpu C ;
Func opTable [ 256 ] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
& C : : BRK , & C : : ORA , & C : : COP , & C : : ORA , & C : : TSB , & C : : ORA , & C : : ASL , & C : : ORA , & C : : PHP , & C : : ORA , & C : : ASL , & C : : PHD , & C : : TSB , & C : : ORA , & C : : ASL , & C : : ORA , // 0
& C : : BPL , & C : : ORA , & C : : ORA , & C : : ORA , & C : : TRB , & C : : ORA , & C : : ASL , & C : : ORA , & C : : CLC , & C : : ORA , & C : : INC , & C : : TCS , & C : : TRB , & C : : ORA , & C : : ASL , & C : : ORA , // 1
& C : : JSR , & C : : AND , & C : : JSL , & C : : AND , & C : : BIT , & C : : AND , & C : : ROL , & C : : AND , & C : : PLP , & C : : AND , & C : : ROL , & C : : PLD , & C : : BIT , & C : : AND , & C : : ROL , & C : : AND , // 2
& C : : BMI , & C : : AND , & C : : AND , & C : : AND , & C : : BIT , & C : : AND , & C : : ROL , & C : : AND , & C : : SEC , & C : : AND , & C : : DEC , & C : : TSC , & C : : BIT , & C : : AND , & C : : ROL , & C : : AND , // 3
& C : : RTI , & C : : EOR , & C : : WDM , & C : : EOR , & C : : MVP , & C : : EOR , & C : : LSR , & C : : EOR , & C : : PHA , & C : : EOR , & C : : LSR , & C : : PHK , & C : : JMP , & C : : EOR , & C : : LSR , & C : : EOR , // 4
2019-02-15 00:09:46 -05:00
& C : : BVC , & C : : EOR , & C : : EOR , & C : : EOR , & C : : MVN , & C : : EOR , & C : : LSR , & C : : EOR , & C : : CLI , & C : : EOR , & C : : PHY , & C : : TCD , & C : : JML , & C : : EOR , & C : : LSR , & C : : EOR , // 5
2019-02-11 19:18:47 -05:00
& C : : RTS , & C : : ADC , & C : : PER , & C : : ADC , & C : : STZ , & C : : ADC , & C : : ROR , & C : : ADC , & C : : PLA , & C : : ADC , & C : : ROR , & C : : RTL , & C : : JMP , & C : : ADC , & C : : ROR , & C : : ADC , // 6
& C : : BVS , & C : : ADC , & C : : ADC , & C : : ADC , & C : : STZ , & C : : ADC , & C : : ROR , & C : : ADC , & C : : SEI , & C : : ADC , & C : : PLY , & C : : TDC , & C : : JMP , & C : : ADC , & C : : ROR , & C : : ADC , // 7
& C : : BRA , & C : : STA , & C : : BRL , & C : : STA , & C : : STY , & C : : STA , & C : : STX , & C : : STA , & C : : DEY , & C : : BIT , & C : : TXA , & C : : PHB , & C : : STY , & C : : STA , & C : : STX , & C : : STA , // 8
& C : : BCC , & C : : STA , & C : : STA , & C : : STA , & C : : STY , & C : : STA , & C : : STX , & C : : STA , & C : : TYA , & C : : STA , & C : : TXS , & C : : TXY , & C : : STZ , & C : : STA , & C : : STZ , & C : : STA , // 9
& C : : LDY , & C : : LDA , & C : : LDX , & C : : LDA , & C : : LDY , & C : : LDA , & C : : LDX , & C : : LDA , & C : : TAY , & C : : LDA , & C : : TAX , & C : : PLB , & C : : LDY , & C : : LDA , & C : : LDX , & C : : LDA , // A
& C : : BCS , & C : : LDA , & C : : LDA , & C : : LDA , & C : : LDY , & C : : LDA , & C : : LDX , & C : : LDA , & C : : CLV , & C : : LDA , & C : : TSX , & C : : TYX , & C : : LDY , & C : : LDA , & C : : LDX , & C : : LDA , // B
& C : : CPY , & C : : CMP , & C : : REP , & C : : CMP , & C : : CPY , & C : : CMP , & C : : DEC , & C : : CMP , & C : : INY , & C : : CMP , & C : : DEX , & C : : WAI , & C : : CPY , & C : : CMP , & C : : DEC , & C : : CMP , // C
& C : : BNE , & C : : CMP , & C : : CMP , & C : : CMP , & C : : PEI , & C : : CMP , & C : : DEC , & C : : CMP , & C : : CLD , & C : : CMP , & C : : PHX , & C : : STP , & C : : JML , & C : : CMP , & C : : DEC , & C : : CMP , // D
& C : : CPX , & C : : SBC , & C : : SEP , & C : : SBC , & C : : CPX , & C : : SBC , & C : : INC , & C : : SBC , & C : : INX , & C : : SBC , & C : : NOP , & C : : XBA , & C : : CPX , & C : : SBC , & C : : INC , & C : : SBC , // E
& C : : BEQ , & C : : SBC , & C : : SBC , & C : : SBC , & C : : PEA , & C : : SBC , & C : : INC , & C : : SBC , & C : : SED , & C : : SBC , & C : : PLX , & C : : XCE , & C : : JSR , & C : : SBC , & C : : INC , & C : : SBC // F
} ;
typedef AddrMode M ;
AddrMode addrMode [ 256 ] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
2019-02-11 22:41:34 -05:00
M : : Stk , M : : DirIdxIndX , M : : Stk , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Stk , M : : ImmM , M : : Acc , M : : Stk , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // 0
2019-02-11 19:18:47 -05:00
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : Dir , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Acc , M : : Imp , M : : Abs , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 1
2019-02-13 13:32:21 -05:00
M : : AbsJmp , M : : DirIdxIndX , M : : AbsLngJmp , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Stk , M : : ImmM , M : : Acc , M : : Stk , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // 2
2019-02-11 19:18:47 -05:00
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : DirIdxX , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Acc , M : : Imp , M : : AbsIdxX , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 3
2019-02-13 13:32:21 -05:00
M : : Stk , M : : DirIdxIndX , M : : Imm8 , M : : StkRel , M : : BlkMov , M : : Dir , M : : Dir , M : : DirIndLng , M : : Stk , M : : ImmM , M : : Acc , M : : Stk , M : : AbsJmp , M : : Abs , M : : Abs , M : : AbsLng , // 4
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : BlkMov , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Stk , M : : Imp , M : : AbsLngJmp , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 5
2019-02-14 19:00:17 -05:00
M : : Stk , M : : DirIdxIndX , M : : RelLng , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Stk , M : : ImmM , M : : Acc , M : : Stk , M : : AbsInd , M : : Abs , M : : Abs , M : : AbsLng , // 6
2019-02-11 19:18:47 -05:00
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : DirIdxX , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Stk , M : : Imp , M : : AbsIdxXInd , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 7
2019-02-11 22:41:34 -05:00
M : : Rel , M : : DirIdxIndX , M : : RelLng , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Imp , M : : ImmM , M : : Imp , M : : Stk , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // 8
2019-02-11 19:18:47 -05:00
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : DirIdxX , M : : DirIdxX , M : : DirIdxY , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Imp , M : : Imp , M : : Abs , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 9
2019-02-11 22:41:34 -05:00
M : : ImmX , M : : DirIdxIndX , M : : ImmX , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Imp , M : : ImmM , M : : Imp , M : : Stk , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // A
2019-02-11 19:18:47 -05:00
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : DirIdxX , M : : DirIdxX , M : : DirIdxY , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Imp , M : : Imp , M : : AbsIdxX , M : : AbsIdxX , M : : AbsIdxY , M : : AbsLngIdxX , // B
2019-02-11 22:41:34 -05:00
M : : ImmX , M : : DirIdxIndX , M : : Imm8 , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Imp , M : : ImmM , M : : Imp , M : : Imp , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // C
2019-02-14 19:00:17 -05:00
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : Dir , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Stk , M : : Imp , M : : AbsIndLng , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // D
2019-02-11 22:41:34 -05:00
M : : ImmX , M : : DirIdxIndX , M : : Imm8 , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Imp , M : : ImmM , M : : Imp , M : : Imp , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // E
2019-02-14 19:00:17 -05:00
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : Imm16 , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Stk , M : : Imp , M : : AbsIdxXInd , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX // F
2019-02-11 19:18:47 -05:00
} ;
memcpy ( _opTable , opTable , sizeof ( opTable ) ) ;
memcpy ( _addrMode , addrMode , sizeof ( addrMode ) ) ;
2019-02-11 22:41:34 -05:00
_memoryManager = memoryManager ;
2019-02-11 19:18:47 -05:00
_state = { } ;
2019-02-11 22:41:34 -05:00
_state . PC = ReadDataWord ( Cpu : : ResetVector ) ;
_state . SP = 0x1FF ;
2019-02-11 19:18:47 -05:00
_state . EmulationMode = true ;
2019-02-13 18:44:12 -05:00
_nmiFlag = false ;
2019-02-17 01:09:47 -05:00
_irqSource = ( uint8_t ) IrqSource : : None ;
2019-02-11 19:18:47 -05:00
SetFlags ( ProcFlags : : MemoryMode8 ) ;
SetFlags ( ProcFlags : : IndexMode8 ) ;
}
Cpu : : ~ Cpu ( )
{
}
void Cpu : : Reset ( )
{
}
void Cpu : : Exec ( )
{
uint8_t opCode = GetOpCode ( ) ;
_instAddrMode = _addrMode [ opCode ] ;
_operand = FetchEffectiveAddress ( ) ;
( this - > * _opTable [ opCode ] ) ( ) ;
opCount + + ;
2019-02-13 18:44:12 -05:00
if ( _nmiFlag ) {
2019-02-15 00:09:46 -05:00
ProcessInterrupt ( _state . EmulationMode ? Cpu : : LegacyNmiVector : Cpu : : NmiVector ) ;
2019-02-13 18:44:12 -05:00
_nmiFlag = false ;
2019-02-17 01:09:47 -05:00
} else if ( _irqSource & & ! CheckFlag ( ProcFlags : : IrqDisable ) ) {
ProcessInterrupt ( _state . EmulationMode ? Cpu : : LegacyIrqVector : Cpu : : IrqVector ) ;
2019-02-13 18:44:12 -05:00
}
}
void Cpu : : SetNmiFlag ( )
{
_nmiFlag = true ;
2019-02-11 19:18:47 -05:00
}
2019-02-17 01:09:47 -05:00
void Cpu : : SetIrqSource ( IrqSource source )
{
_irqSource | = ( uint8_t ) source ;
}
2019-02-17 15:37:31 -05:00
bool Cpu : : CheckIrqSource ( IrqSource source )
{
if ( _irqSource & ( uint8_t ) source ) {
return true ;
} else {
return false ;
}
}
2019-02-17 01:09:47 -05:00
void Cpu : : ClearIrqSource ( IrqSource source )
{
2019-02-20 20:50:43 -05:00
_irqSource & = ~ ( uint8_t ) source ;
2019-02-17 01:09:47 -05:00
}
2019-02-13 13:32:21 -05:00
uint32_t Cpu : : GetProgramAddress ( uint16_t addr )
2019-02-11 19:18:47 -05:00
{
2019-02-13 13:32:21 -05:00
return ( _state . K < < 16 ) | addr ;
2019-02-11 19:18:47 -05:00
}
uint32_t Cpu : : GetDataAddress ( uint16_t addr )
{
return ( _state . DBR < < 16 ) | addr ;
}
uint8_t Cpu : : GetOpCode ( )
{
uint8_t opCode = ReadCode ( _state . PC , MemoryOperationType : : ExecOpCode ) ;
_state . PC + + ;
return opCode ;
}
void Cpu : : DummyRead ( )
{
ReadCode ( _state . PC , MemoryOperationType : : DummyRead ) ;
}
uint8_t Cpu : : ReadOperandByte ( )
{
return ReadCode ( _state . PC + + , MemoryOperationType : : ExecOperand ) ;
}
uint16_t Cpu : : ReadOperandWord ( )
{
uint8_t lsb = ReadOperandByte ( ) ;
uint8_t msb = ReadOperandByte ( ) ;
return ( msb < < 8 ) | lsb ;
}
uint32_t Cpu : : ReadOperandLong ( )
{
uint8_t b1 = ReadOperandByte ( ) ;
uint8_t b2 = ReadOperandByte ( ) ;
uint8_t b3 = ReadOperandByte ( ) ;
return ( b3 < < 16 ) | ( b2 < < 8 ) | b1 ;
}
uint8_t Cpu : : ReadCode ( uint16_t addr , MemoryOperationType type )
{
2019-02-13 13:32:21 -05:00
_state . CycleCount + + ;
2019-02-12 22:13:09 -05:00
return _memoryManager - > Read ( ( _state . K < < 16 ) | addr , type ) ;
2019-02-11 19:18:47 -05:00
}
2019-02-13 13:32:21 -05:00
uint16_t Cpu : : ReadCodeWord ( uint16_t addr , MemoryOperationType type )
{
uint8_t lsb = ReadCode ( addr ) ;
uint8_t msb = ReadCode ( addr + 1 ) ;
return ( msb < < 8 ) | lsb ;
}
2019-02-11 19:18:47 -05:00
uint8_t Cpu : : ReadData ( uint32_t addr , MemoryOperationType type )
{
2019-02-13 13:32:21 -05:00
_state . CycleCount + + ;
2019-02-12 22:13:09 -05:00
return _memoryManager - > Read ( addr , type ) ;
2019-02-11 19:18:47 -05:00
}
uint16_t Cpu : : ReadDataWord ( uint32_t addr , MemoryOperationType type )
{
uint8_t lsb = ReadData ( addr ) ;
uint8_t msb = ReadData ( addr + 1 ) ;
return ( msb < < 8 ) | lsb ;
}
uint32_t Cpu : : ReadDataLong ( uint32_t addr , MemoryOperationType type )
{
uint8_t b1 = ReadData ( addr ) ;
uint8_t b2 = ReadData ( addr + 1 ) ;
uint8_t b3 = ReadData ( addr + 2 ) ;
return ( b3 < < 16 ) | ( b2 < < 8 ) | b1 ;
}
void Cpu : : Write ( uint32_t addr , uint8_t value , MemoryOperationType type )
{
2019-02-13 13:32:21 -05:00
_state . CycleCount + + ;
2019-02-12 22:13:09 -05:00
_memoryManager - > Write ( addr , value , type ) ;
2019-02-11 19:18:47 -05:00
}
void Cpu : : WriteWord ( uint32_t addr , uint16_t value , MemoryOperationType type )
{
Write ( addr , ( uint8_t ) value ) ;
Write ( addr + 1 , ( uint8_t ) ( value > > 8 ) ) ;
}
uint8_t Cpu : : GetByteValue ( )
{
2019-02-11 22:41:34 -05:00
if ( _instAddrMode < = AddrMode : : ImmM ) {
2019-02-11 19:18:47 -05:00
return ( uint8_t ) _operand ;
} else {
return ReadData ( _operand ) ;
}
}
uint16_t Cpu : : GetWordValue ( )
{
2019-02-11 22:41:34 -05:00
if ( _instAddrMode < = AddrMode : : ImmM ) {
2019-02-11 19:18:47 -05:00
return ( uint16_t ) _operand ;
} else {
return ReadDataWord ( _operand ) ;
}
}
void Cpu : : PushByte ( uint8_t value )
{
2019-02-14 00:48:16 -05:00
Write ( _state . SP , value ) ;
SetSP ( _state . SP - 1 ) ;
2019-02-11 19:18:47 -05:00
}
uint8_t Cpu : : PopByte ( )
{
2019-02-14 00:48:16 -05:00
SetSP ( _state . SP + 1 ) ;
2019-02-11 22:41:34 -05:00
return ReadData ( _state . SP ) ;
2019-02-11 19:18:47 -05:00
}
void Cpu : : PushWord ( uint16_t value )
{
PushByte ( value > > 8 ) ;
PushByte ( ( uint8_t ) value ) ;
}
uint16_t Cpu : : PopWord ( )
{
uint8_t lo = PopByte ( ) ;
uint8_t hi = PopByte ( ) ;
return lo | hi < < 8 ;
}
2019-02-13 18:44:12 -05:00
uint16_t Cpu : : GetDirectAddress ( uint16_t offset , bool allowEmulationMode )
2019-02-11 19:18:47 -05:00
{
if ( allowEmulationMode & & _state . EmulationMode & & ( _state . D & 0xFF ) = = 0 ) {
//TODO: Check if new instruction or not (PEI)
2019-02-13 18:44:12 -05:00
return ( uint16_t ) ( ( _state . D & 0xFF00 ) | ( offset & 0xFF ) ) ;
2019-02-11 19:18:47 -05:00
} else {
2019-02-13 18:44:12 -05:00
return ( uint16_t ) ( _state . D + offset ) ;
2019-02-11 19:18:47 -05:00
}
}
2019-02-13 18:44:12 -05:00
uint16_t Cpu : : GetDirectAddressIndirectWord ( uint16_t offset , bool allowEmulationMode )
{
uint8_t lsb = ReadData ( GetDirectAddress ( offset + 0 ) ) ;
uint8_t msb = ReadData ( GetDirectAddress ( offset + 1 ) ) ;
return ( msb < < 8 ) | lsb ;
}
uint32_t Cpu : : GetDirectAddressIndirectLong ( uint16_t offset , bool allowEmulationMode )
{
uint8_t b1 = ReadData ( GetDirectAddress ( offset + 0 ) ) ;
uint8_t b2 = ReadData ( GetDirectAddress ( offset + 1 ) ) ;
uint8_t b3 = ReadData ( GetDirectAddress ( offset + 2 ) ) ;
return ( b3 < < 16 ) | ( b2 < < 8 ) | b1 ;
}
2019-02-11 19:18:47 -05:00
uint32_t Cpu : : FetchEffectiveAddress ( )
{
switch ( _instAddrMode ) {
2019-02-13 13:32:21 -05:00
case AddrMode : : Abs : return GetDataAddress ( ReadOperandWord ( ) ) ;
2019-02-13 18:44:12 -05:00
case AddrMode : : AbsIdxX : return ( GetDataAddress ( ReadOperandWord ( ) ) + _state . X ) & 0xFFFFFF ;
case AddrMode : : AbsIdxY : return ( GetDataAddress ( ReadOperandWord ( ) ) + _state . Y ) & 0xFFFFFF ;
2019-02-11 22:41:34 -05:00
case AddrMode : : AbsLng : return ReadOperandLong ( ) ;
2019-02-13 18:44:12 -05:00
case AddrMode : : AbsLngIdxX : return ( ReadOperandLong ( ) + _state . X ) & 0xFFFFFF ;
2019-02-13 13:32:21 -05:00
case AddrMode : : AbsJmp : return GetProgramAddress ( ReadOperandWord ( ) ) ;
case AddrMode : : AbsLngJmp : return ReadOperandLong ( ) ;
case AddrMode : : AbsIdxXInd : return GetProgramAddress ( ReadDataWord ( GetProgramAddress ( ReadOperandWord ( ) + _state . X ) ) ) ; //JMP/JSR
2019-02-13 18:44:12 -05:00
case AddrMode : : AbsInd : return ReadDataWord ( ReadOperandWord ( ) ) ; //JMP only
2019-02-13 13:32:21 -05:00
case AddrMode : : AbsIndLng : return ReadDataLong ( ReadOperandWord ( ) ) ; //JML only
2019-02-11 19:18:47 -05:00
2019-02-11 22:41:34 -05:00
case AddrMode : : Acc : DummyRead ( ) ; return 0 ;
2019-02-11 19:18:47 -05:00
case AddrMode : : BlkMov : return ReadOperandWord ( ) ;
2019-02-11 22:41:34 -05:00
case AddrMode : : Dir : return GetDirectAddress ( ReadOperandByte ( ) ) ;
2019-02-13 18:44:12 -05:00
case AddrMode : : DirIdxX : return GetDirectAddress ( ReadOperandByte ( ) + _state . X ) ;
case AddrMode : : DirIdxY : return GetDirectAddress ( ReadOperandByte ( ) + _state . Y ) ;
case AddrMode : : DirInd : return GetDataAddress ( GetDirectAddressIndirectWord ( ReadOperandByte ( ) ) ) ;
case AddrMode : : DirIdxIndX : return GetDataAddress ( GetDirectAddressIndirectWord ( ReadOperandByte ( ) + _state . X ) ) ;
case AddrMode : : DirIndIdxY : return ( GetDataAddress ( GetDirectAddressIndirectWord ( ReadOperandByte ( ) ) ) + _state . Y ) & 0xFFFFFF ;
case AddrMode : : DirIndLng : return GetDirectAddressIndirectLong ( ReadOperandByte ( ) ) ;
case AddrMode : : DirIndLngIdxY : return ( GetDirectAddressIndirectLong ( ReadOperandByte ( ) ) + _state . Y ) & 0xFFFFFF ;
2019-02-11 19:18:47 -05:00
2019-02-11 22:41:34 -05:00
case AddrMode : : Imm8 : return ReadOperandByte ( ) ;
2019-02-14 19:00:17 -05:00
case AddrMode : : Imm16 : return ReadOperandWord ( ) ;
2019-02-11 22:41:34 -05:00
case AddrMode : : ImmX : return CheckFlag ( ProcFlags : : IndexMode8 ) ? ReadOperandByte ( ) : ReadOperandWord ( ) ;
case AddrMode : : ImmM : return CheckFlag ( ProcFlags : : MemoryMode8 ) ? ReadOperandByte ( ) : ReadOperandWord ( ) ;
case AddrMode : : Imp : DummyRead ( ) ; return 0 ;
2019-02-11 19:18:47 -05:00
2019-02-11 22:41:34 -05:00
case AddrMode : : RelLng : return ReadOperandWord ( ) ;
case AddrMode : : Rel : return ReadOperandByte ( ) ;
2019-02-11 19:18:47 -05:00
2019-02-13 18:44:12 -05:00
case AddrMode : : Stk : return 0 ;
2019-02-11 22:41:34 -05:00
case AddrMode : : StkRel : return ( uint16_t ) ( ReadOperandByte ( ) + _state . SP ) ;
2019-02-11 19:18:47 -05:00
2019-02-11 22:41:34 -05:00
case AddrMode : : StkRelIndIdxY : {
2019-02-11 19:18:47 -05:00
uint16_t addr = ( uint16_t ) ( ReadOperandByte ( ) + _state . SP ) ;
2019-02-14 00:48:16 -05:00
return ( GetDataAddress ( ReadDataWord ( addr ) ) + _state . Y ) & 0xFFFFFF ;
2019-02-11 19:18:47 -05:00
}
}
2019-02-21 18:18:25 -05:00
throw std : : runtime_error ( " Unreacheable code " ) ;
2019-02-11 19:18:47 -05:00
}
2019-02-14 00:48:16 -05:00
void Cpu : : SetSP ( uint16_t sp )
{
if ( _state . EmulationMode ) {
_state . SP = 0x100 | ( sp & 0xFF ) ;
} else {
_state . SP = sp ;
}
}
2019-02-20 22:46:14 -05:00
void Cpu : : SetPS ( uint8_t ps )
{
_state . PS = ps ;
if ( CheckFlag ( ProcFlags : : IndexMode8 ) ) {
//Truncate X/Y when 8-bit indexes are enabled
_state . Y & = 0xFF ;
_state . X & = 0xFF ;
}
}
2019-02-11 19:18:47 -05:00
void Cpu : : SetRegister ( uint8_t & reg , uint8_t value )
{
SetZeroNegativeFlags ( value ) ;
reg = value ;
}
void Cpu : : SetRegister ( uint16_t & reg , uint16_t value , bool eightBitMode )
{
if ( eightBitMode ) {
SetZeroNegativeFlags ( ( uint8_t ) value ) ;
reg = ( reg & 0xFF00 ) | ( uint8_t ) value ;
} else {
SetZeroNegativeFlags ( value ) ;
reg = value ;
}
}
void Cpu : : SetZeroNegativeFlags ( uint16_t value )
{
ClearFlags ( ProcFlags : : Zero | ProcFlags : : Negative ) ;
if ( value = = 0 ) {
SetFlags ( ProcFlags : : Zero ) ;
} else if ( value & 0x8000 ) {
SetFlags ( ProcFlags : : Negative ) ;
}
}
void Cpu : : SetZeroNegativeFlags ( uint8_t value )
{
ClearFlags ( ProcFlags : : Zero | ProcFlags : : Negative ) ;
if ( value = = 0 ) {
SetFlags ( ProcFlags : : Zero ) ;
} else if ( value & 0x80 ) {
SetFlags ( ProcFlags : : Negative ) ;
}
}
void Cpu : : ClearFlags ( uint8_t flags )
{
_state . PS & = ~ flags ;
}
void Cpu : : SetFlags ( uint8_t flags )
{
_state . PS | = flags ;
}
bool Cpu : : CheckFlag ( uint8_t flag )
{
return ( _state . PS & flag ) = = flag ;
}