mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
823 lines
14 KiB
C++
823 lines
14 KiB
C++
#include "pch.h"
|
|
#include "PceCpu.h"
|
|
#include "PCE/PceMemoryManager.h"
|
|
|
|
void PceCpu::WriteMemoryModeValue(uint8_t value)
|
|
{
|
|
ClearFlags(PceCpuFlags::Zero | PceCpuFlags::Negative);
|
|
SetZeroNegativeFlags(value);
|
|
MemoryWrite(PceCpu::ZeroPage + X(), value);
|
|
}
|
|
|
|
void PceCpu::AND()
|
|
{
|
|
if(_memoryFlag) {
|
|
DummyRead();
|
|
uint8_t value = MemoryRead(PceCpu::ZeroPage + X());
|
|
WriteMemoryModeValue(value & GetOperandValue());
|
|
} else {
|
|
SetA(A() & GetOperandValue());
|
|
}
|
|
}
|
|
|
|
void PceCpu::EOR()
|
|
{
|
|
if(_memoryFlag) {
|
|
DummyRead();
|
|
uint8_t value = MemoryRead(PceCpu::ZeroPage + X());
|
|
WriteMemoryModeValue(value ^ GetOperandValue());
|
|
} else {
|
|
SetA(A() ^ GetOperandValue());
|
|
}
|
|
}
|
|
|
|
void PceCpu::ORA()
|
|
{
|
|
if(_memoryFlag) {
|
|
DummyRead();
|
|
uint8_t value = MemoryRead(PceCpu::ZeroPage + X());
|
|
WriteMemoryModeValue(value | GetOperandValue());
|
|
} else {
|
|
SetA(A() | GetOperandValue());
|
|
}
|
|
}
|
|
|
|
void PceCpu::ADD(uint8_t value)
|
|
{
|
|
uint8_t source;
|
|
if(_memoryFlag) {
|
|
DummyRead();
|
|
source = MemoryRead(PceCpu::ZeroPage + X());
|
|
} else {
|
|
source = A();
|
|
}
|
|
|
|
uint16_t result;
|
|
if(CheckFlag(PceCpuFlags::Decimal)) {
|
|
result = (uint16_t)(source & 0x0F) + (uint16_t)(value & 0x0F) + (_state.PS & PceCpuFlags::Carry);
|
|
if(result > 0x09) result += 0x06;
|
|
result = (uint16_t)(source & 0xF0) + (uint16_t)(value & 0xF0) + (result > 0x0F ? 0x10 : 0) + (result & 0x0F);
|
|
if(result > 0x9F) result += 0x60;
|
|
} else {
|
|
result = (uint16_t)source + (uint16_t)value + (CheckFlag(PceCpuFlags::Carry) ? PceCpuFlags::Carry : 0x00);
|
|
|
|
if(~(source ^ value) & (source ^ result) & 0x80) {
|
|
SetFlags(PceCpuFlags::Overflow);
|
|
} else {
|
|
ClearFlags(PceCpuFlags::Overflow);
|
|
}
|
|
}
|
|
|
|
ClearFlags(PceCpuFlags::Carry | PceCpuFlags::Negative | PceCpuFlags::Zero);
|
|
SetZeroNegativeFlags((uint8_t)result);
|
|
|
|
if(result > 0xFF) {
|
|
SetFlags(PceCpuFlags::Carry);
|
|
}
|
|
|
|
if(_memoryFlag) {
|
|
WriteMemoryModeValue((uint8_t)result);
|
|
} else {
|
|
SetA((uint8_t)result);
|
|
}
|
|
}
|
|
|
|
void PceCpu::SUB(uint8_t value)
|
|
{
|
|
int32_t result;
|
|
if(CheckFlag(PceCpuFlags::Decimal)) {
|
|
result = (A() & 0x0F) + (value & 0x0F) + (_state.PS & PceCpuFlags::Carry);
|
|
if(result <= 0x0F) result -= 0x06;
|
|
result = (A() & 0xF0) + (value & 0xF0) + (result > 0x0F ? 0x10 : 0) + (result & 0x0F);
|
|
if(result <= 0xFF) result -= 0x60;
|
|
} else {
|
|
result = (uint16_t)A() + (uint16_t)value + (_state.PS & PceCpuFlags::Carry);
|
|
|
|
if(~(A() ^ value) & (A() ^ result) & 0x80) {
|
|
SetFlags(PceCpuFlags::Overflow);
|
|
} else {
|
|
ClearFlags(PceCpuFlags::Overflow);
|
|
}
|
|
}
|
|
|
|
ClearFlags(PceCpuFlags::Carry | PceCpuFlags::Negative | PceCpuFlags::Zero);
|
|
SetZeroNegativeFlags((uint8_t)result);
|
|
|
|
if(result > 0xFF) {
|
|
SetFlags(PceCpuFlags::Carry);
|
|
}
|
|
|
|
SetA((uint8_t)result);
|
|
}
|
|
|
|
void PceCpu::ADC()
|
|
{
|
|
ADD(GetOperandValue());
|
|
}
|
|
|
|
void PceCpu::SBC()
|
|
{
|
|
SUB(~GetOperandValue());
|
|
}
|
|
|
|
void PceCpu::CMP(uint8_t reg, uint8_t value)
|
|
{
|
|
ClearFlags(PceCpuFlags::Carry | PceCpuFlags::Negative | PceCpuFlags::Zero);
|
|
|
|
auto result = reg - value;
|
|
|
|
if(reg >= value) {
|
|
SetFlags(PceCpuFlags::Carry);
|
|
}
|
|
if(reg == value) {
|
|
SetFlags(PceCpuFlags::Zero);
|
|
}
|
|
if((result & 0x80) == 0x80) {
|
|
SetFlags(PceCpuFlags::Negative);
|
|
}
|
|
}
|
|
|
|
void PceCpu::CPA() { CMP(A(), GetOperandValue()); }
|
|
void PceCpu::CPX() { CMP(X(), GetOperandValue()); }
|
|
void PceCpu::CPY() { CMP(Y(), GetOperandValue()); }
|
|
|
|
void PceCpu::INC()
|
|
{
|
|
uint16_t addr = GetOperand();
|
|
ClearFlags(PceCpuFlags::Negative | PceCpuFlags::Zero);
|
|
uint8_t value = MemoryRead(addr);
|
|
|
|
DummyRead();
|
|
|
|
value++;
|
|
SetZeroNegativeFlags(value);
|
|
MemoryWrite(addr, value);
|
|
}
|
|
|
|
void PceCpu::DEC()
|
|
{
|
|
uint16_t addr = GetOperand();
|
|
ClearFlags(PceCpuFlags::Negative | PceCpuFlags::Zero);
|
|
uint8_t value = MemoryRead(addr);
|
|
|
|
DummyRead();
|
|
|
|
value--;
|
|
SetZeroNegativeFlags(value);
|
|
MemoryWrite(addr, value);
|
|
}
|
|
|
|
uint8_t PceCpu::ASL(uint8_t value)
|
|
{
|
|
ClearFlags(PceCpuFlags::Carry | PceCpuFlags::Negative | PceCpuFlags::Zero);
|
|
if(value & 0x80) {
|
|
SetFlags(PceCpuFlags::Carry);
|
|
}
|
|
|
|
uint8_t result = value << 1;
|
|
SetZeroNegativeFlags(result);
|
|
return result;
|
|
}
|
|
|
|
uint8_t PceCpu::LSR(uint8_t value)
|
|
{
|
|
ClearFlags(PceCpuFlags::Carry | PceCpuFlags::Negative | PceCpuFlags::Zero);
|
|
if(value & 0x01) {
|
|
SetFlags(PceCpuFlags::Carry);
|
|
}
|
|
|
|
uint8_t result = value >> 1;
|
|
SetZeroNegativeFlags(result);
|
|
return result;
|
|
}
|
|
|
|
uint8_t PceCpu::ROL(uint8_t value)
|
|
{
|
|
bool carryFlag = CheckFlag(PceCpuFlags::Carry);
|
|
ClearFlags(PceCpuFlags::Carry | PceCpuFlags::Negative | PceCpuFlags::Zero);
|
|
|
|
if(value & 0x80) {
|
|
SetFlags(PceCpuFlags::Carry);
|
|
}
|
|
|
|
uint8_t result = (value << 1 | (carryFlag ? 0x01 : 0x00));
|
|
SetZeroNegativeFlags(result);
|
|
return result;
|
|
}
|
|
|
|
uint8_t PceCpu::ROR(uint8_t value)
|
|
{
|
|
bool carryFlag = CheckFlag(PceCpuFlags::Carry);
|
|
ClearFlags(PceCpuFlags::Carry | PceCpuFlags::Negative | PceCpuFlags::Zero);
|
|
if(value & 0x01) {
|
|
SetFlags(PceCpuFlags::Carry);
|
|
}
|
|
|
|
uint8_t result = (value >> 1 | (carryFlag ? 0x80 : 0x00));
|
|
SetZeroNegativeFlags(result);
|
|
return result;
|
|
}
|
|
|
|
void PceCpu::ASLAddr()
|
|
{
|
|
uint16_t addr = GetOperand();
|
|
uint8_t value = MemoryRead(addr);
|
|
DummyRead();
|
|
MemoryWrite(addr, ASL(value));
|
|
}
|
|
|
|
void PceCpu::LSRAddr()
|
|
{
|
|
uint16_t addr = GetOperand();
|
|
uint8_t value = MemoryRead(addr);
|
|
DummyRead();
|
|
MemoryWrite(addr, LSR(value));
|
|
}
|
|
|
|
void PceCpu::ROLAddr()
|
|
{
|
|
uint16_t addr = GetOperand();
|
|
uint8_t value = MemoryRead(addr);
|
|
DummyRead();
|
|
MemoryWrite(addr, ROL(value));
|
|
}
|
|
|
|
void PceCpu::RORAddr()
|
|
{
|
|
uint16_t addr = GetOperand();
|
|
uint8_t value = MemoryRead(addr);
|
|
DummyRead();
|
|
MemoryWrite(addr, ROR(value));
|
|
}
|
|
|
|
void PceCpu::BranchRelative(bool branch)
|
|
{
|
|
int8_t offset = (int8_t)GetOperand();
|
|
if(branch) {
|
|
DummyRead();
|
|
DummyRead();
|
|
|
|
SetPC(PC() + offset);
|
|
}
|
|
}
|
|
|
|
void PceCpu::BIT()
|
|
{
|
|
uint8_t value = GetOperandValue();
|
|
ClearFlags(PceCpuFlags::Zero | PceCpuFlags::Overflow | PceCpuFlags::Negative);
|
|
if((A() & value) == 0) {
|
|
SetFlags(PceCpuFlags::Zero);
|
|
}
|
|
if(value & 0x40) {
|
|
SetFlags(PceCpuFlags::Overflow);
|
|
}
|
|
if(value & 0x80) {
|
|
SetFlags(PceCpuFlags::Negative);
|
|
}
|
|
}
|
|
|
|
void PceCpu::TSB()
|
|
{
|
|
uint8_t value = MemoryRead(_operand);
|
|
|
|
ClearFlags(PceCpuFlags::Zero | PceCpuFlags::Overflow | PceCpuFlags::Negative);
|
|
if(value & 0x40) {
|
|
SetFlags(PceCpuFlags::Overflow);
|
|
}
|
|
if(value & 0x80) {
|
|
SetFlags(PceCpuFlags::Negative);
|
|
}
|
|
|
|
value |= A();
|
|
if(value == 0) {
|
|
SetFlags(PceCpuFlags::Zero);
|
|
}
|
|
|
|
DummyRead();
|
|
MemoryWrite(_operand, value);
|
|
}
|
|
|
|
void PceCpu::TRB()
|
|
{
|
|
uint8_t value = MemoryRead(_operand);
|
|
|
|
ClearFlags(PceCpuFlags::Zero | PceCpuFlags::Overflow | PceCpuFlags::Negative);
|
|
if(value & 0x40) {
|
|
SetFlags(PceCpuFlags::Overflow);
|
|
}
|
|
if(value & 0x80) {
|
|
SetFlags(PceCpuFlags::Negative);
|
|
}
|
|
|
|
value &= ~A();
|
|
if(value == 0) {
|
|
SetFlags(PceCpuFlags::Zero);
|
|
}
|
|
|
|
DummyRead();
|
|
MemoryWrite(_operand, value);
|
|
}
|
|
|
|
void PceCpu::TST()
|
|
{
|
|
DummyRead();
|
|
DummyRead();
|
|
|
|
uint8_t value = MemoryRead(_operand2);
|
|
|
|
ClearFlags(PceCpuFlags::Zero | PceCpuFlags::Overflow | PceCpuFlags::Negative);
|
|
if(value & 0x40) {
|
|
SetFlags(PceCpuFlags::Overflow);
|
|
}
|
|
if(value & 0x80) {
|
|
SetFlags(PceCpuFlags::Negative);
|
|
}
|
|
|
|
value &= _operand;
|
|
|
|
if(value == 0) {
|
|
SetFlags(PceCpuFlags::Zero);
|
|
}
|
|
}
|
|
|
|
void PceCpu::CSL()
|
|
{
|
|
//CSH/CSL take 3 cycles
|
|
DummyRead();
|
|
#ifndef DUMMYCPU
|
|
_memoryManager->SetSpeed(true);
|
|
#endif
|
|
}
|
|
|
|
void PceCpu::CSH()
|
|
{
|
|
//CSH/CSL take 3 cycles
|
|
DummyRead();
|
|
#ifndef DUMMYCPU
|
|
_memoryManager->SetSpeed(false);
|
|
#endif
|
|
}
|
|
|
|
//OP Codes
|
|
void PceCpu::LDA() { SetA(GetOperandValue()); }
|
|
void PceCpu::LDX() { SetX(GetOperandValue()); }
|
|
void PceCpu::LDY() { SetY(GetOperandValue()); }
|
|
|
|
void PceCpu::STA() { MemoryWrite(GetOperand(), A()); }
|
|
void PceCpu::STX() { MemoryWrite(GetOperand(), X()); }
|
|
void PceCpu::STY() { MemoryWrite(GetOperand(), Y()); }
|
|
void PceCpu::STZ() { MemoryWrite(GetOperand(), 0); }
|
|
|
|
void PceCpu::TAX() { SetX(A()); }
|
|
void PceCpu::TAY() { SetY(A()); }
|
|
void PceCpu::TSX() { SetX(SP()); }
|
|
void PceCpu::TXA() { SetA(X()); }
|
|
void PceCpu::TXS() { SetSP(X()); }
|
|
void PceCpu::TYA() { SetA(Y()); }
|
|
|
|
void PceCpu::PHA() { Push(A()); }
|
|
void PceCpu::PHX() { Push(X()); }
|
|
void PceCpu::PHY() { Push(Y()); }
|
|
|
|
void PceCpu::PHP()
|
|
{
|
|
uint8_t flags = PS() | PceCpuFlags::Break;
|
|
Push((uint8_t)flags);
|
|
}
|
|
|
|
void PceCpu::PLA()
|
|
{
|
|
DummyRead();
|
|
SetA(Pop());
|
|
}
|
|
|
|
void PceCpu::PLP()
|
|
{
|
|
DummyRead();
|
|
SetPS(Pop());
|
|
}
|
|
|
|
void PceCpu::PLX()
|
|
{
|
|
DummyRead();
|
|
SetX(Pop());
|
|
}
|
|
|
|
void PceCpu::PLY()
|
|
{
|
|
DummyRead();
|
|
SetY(Pop());
|
|
}
|
|
|
|
void PceCpu::INC_Acc() { SetA(A() + 1); }
|
|
void PceCpu::INX() { SetX(X() + 1); }
|
|
void PceCpu::INY() { SetY(Y() + 1); }
|
|
|
|
void PceCpu::DEC_Acc() { SetA(A() - 1); }
|
|
void PceCpu::DEX() { SetX(X() - 1); }
|
|
void PceCpu::DEY() { SetY(Y() - 1); }
|
|
|
|
void PceCpu::ASL_Acc() { SetA(ASL(A())); }
|
|
void PceCpu::ASL_Memory() { ASLAddr(); }
|
|
|
|
void PceCpu::LSR_Acc() { SetA(LSR(A())); }
|
|
void PceCpu::LSR_Memory() { LSRAddr(); }
|
|
|
|
void PceCpu::ROL_Acc() { SetA(ROL(A())); }
|
|
void PceCpu::ROL_Memory() { ROLAddr(); }
|
|
|
|
void PceCpu::ROR_Acc() { SetA(ROR(A())); }
|
|
void PceCpu::ROR_Memory() { RORAddr(); }
|
|
|
|
void PceCpu::JMP_Abs()
|
|
{
|
|
SetPC(GetOperand());
|
|
}
|
|
|
|
void PceCpu::JMP_Ind()
|
|
{
|
|
//Unlike the 6502 CPU, this CPU works normally when crossing a page during indirect jumps
|
|
DummyRead();
|
|
DummyRead();
|
|
SetPC(MemoryReadWord(_operand));
|
|
}
|
|
|
|
void PceCpu::JMP_AbsX()
|
|
{
|
|
DummyRead();
|
|
SetPC(MemoryReadWord(_operand));
|
|
}
|
|
|
|
void PceCpu::JSR()
|
|
{
|
|
uint16_t addr = GetOperand();
|
|
DummyRead();
|
|
Push((uint16_t)(PC() - 1));
|
|
SetPC(addr);
|
|
}
|
|
|
|
void PceCpu::RTS()
|
|
{
|
|
DummyRead();
|
|
uint16_t addr = PopWord();
|
|
DummyRead();
|
|
DummyRead();
|
|
SetPC(addr + 1);
|
|
}
|
|
|
|
void PceCpu::BCC()
|
|
{
|
|
BranchRelative(!CheckFlag(PceCpuFlags::Carry));
|
|
}
|
|
|
|
void PceCpu::BCS()
|
|
{
|
|
BranchRelative(CheckFlag(PceCpuFlags::Carry));
|
|
}
|
|
|
|
void PceCpu::BEQ()
|
|
{
|
|
BranchRelative(CheckFlag(PceCpuFlags::Zero));
|
|
}
|
|
|
|
void PceCpu::BMI()
|
|
{
|
|
BranchRelative(CheckFlag(PceCpuFlags::Negative));
|
|
}
|
|
|
|
void PceCpu::BNE()
|
|
{
|
|
BranchRelative(!CheckFlag(PceCpuFlags::Zero));
|
|
}
|
|
|
|
void PceCpu::BPL()
|
|
{
|
|
BranchRelative(!CheckFlag(PceCpuFlags::Negative));
|
|
}
|
|
|
|
void PceCpu::BVC()
|
|
{
|
|
BranchRelative(!CheckFlag(PceCpuFlags::Overflow));
|
|
}
|
|
|
|
void PceCpu::BVS()
|
|
{
|
|
BranchRelative(CheckFlag(PceCpuFlags::Overflow));
|
|
}
|
|
|
|
void PceCpu::CLC() { ClearFlags(PceCpuFlags::Carry); }
|
|
void PceCpu::CLD() { ClearFlags(PceCpuFlags::Decimal); }
|
|
void PceCpu::CLI() { ClearFlags(PceCpuFlags::Interrupt); }
|
|
void PceCpu::CLV() { ClearFlags(PceCpuFlags::Overflow); }
|
|
void PceCpu::SEC() { SetFlags(PceCpuFlags::Carry); }
|
|
void PceCpu::SED() { SetFlags(PceCpuFlags::Decimal); }
|
|
void PceCpu::SEI() { SetFlags(PceCpuFlags::Interrupt); }
|
|
void PceCpu::SET() { SetFlags(PceCpuFlags::Memory); }
|
|
|
|
void PceCpu::BRK()
|
|
{
|
|
ProcessIrq(true);
|
|
}
|
|
|
|
void PceCpu::RTI()
|
|
{
|
|
DummyRead();
|
|
SetPS(Pop());
|
|
DummyRead();
|
|
SetPC(PopWord());
|
|
}
|
|
|
|
void PceCpu::NOP()
|
|
{
|
|
//NOP
|
|
}
|
|
|
|
void PceCpu::BSR()
|
|
{
|
|
int8_t relAddr = (int8_t)GetOperand();
|
|
DummyRead();
|
|
DummyRead();
|
|
Push((uint16_t)(PC() - 1));
|
|
DummyRead();
|
|
DummyRead();
|
|
SetPC(PC() + relAddr);
|
|
}
|
|
|
|
void PceCpu::BRA()
|
|
{
|
|
BranchRelative(true);
|
|
}
|
|
|
|
void PceCpu::SXY()
|
|
{
|
|
DummyRead();
|
|
std::swap(_state.X, _state.Y);
|
|
}
|
|
|
|
void PceCpu::SAX()
|
|
{
|
|
DummyRead();
|
|
std::swap(_state.A, _state.X);
|
|
}
|
|
|
|
void PceCpu::SAY()
|
|
{
|
|
DummyRead();
|
|
std::swap(_state.A, _state.Y);
|
|
}
|
|
|
|
void PceCpu::CLA()
|
|
{
|
|
_state.A = 0;
|
|
}
|
|
|
|
void PceCpu::CLX()
|
|
{
|
|
_state.X = 0;
|
|
}
|
|
|
|
void PceCpu::CLY()
|
|
{
|
|
_state.Y = 0;
|
|
}
|
|
|
|
void PceCpu::ST0()
|
|
{
|
|
DummyRead(); //1 dummy read
|
|
#ifndef DUMMYCPU
|
|
ProcessCpuCycle(); //1 write cycle
|
|
_memoryManager->WriteVdc(0, _operand);
|
|
#endif
|
|
}
|
|
|
|
void PceCpu::ST1()
|
|
{
|
|
DummyRead(); //1 dummy read
|
|
#ifndef DUMMYCPU
|
|
ProcessCpuCycle(); //1 write cycle
|
|
_memoryManager->WriteVdc(2, _operand);
|
|
#endif
|
|
}
|
|
|
|
void PceCpu::ST2()
|
|
{
|
|
DummyRead(); //1 dummy read
|
|
#ifndef DUMMYCPU
|
|
ProcessCpuCycle(); //1 write cycle
|
|
_memoryManager->WriteVdc(3, _operand);
|
|
#endif
|
|
}
|
|
|
|
void PceCpu::TMA()
|
|
{
|
|
DummyRead();
|
|
DummyRead();
|
|
#ifndef DUMMYCPU
|
|
SetA(_memoryManager->GetMprValue(GetOperand()));
|
|
#endif
|
|
}
|
|
|
|
void PceCpu::TAM()
|
|
{
|
|
DummyRead();
|
|
DummyRead();
|
|
DummyRead();
|
|
#ifndef DUMMYCPU
|
|
_memoryManager->SetMprValue(GetOperand(), A());
|
|
#endif
|
|
}
|
|
|
|
void PceCpu::StartBlockTransfer()
|
|
{
|
|
DummyRead();
|
|
Push(Y());
|
|
DummyRead();
|
|
Push(X());
|
|
DummyRead();
|
|
Push(A());
|
|
DummyRead();
|
|
}
|
|
|
|
void PceCpu::EndBlockTransfer()
|
|
{
|
|
_state.A = Pop();
|
|
_state.X = Pop();
|
|
_state.Y = Pop();
|
|
}
|
|
|
|
void PceCpu::TAI()
|
|
{
|
|
StartBlockTransfer();
|
|
|
|
uint16_t src = _operand;
|
|
uint16_t dst = _operand2;
|
|
uint16_t length = _operand3;
|
|
|
|
uint32_t count = 0;
|
|
do {
|
|
DummyRead();
|
|
uint8_t value = MemoryRead(src);
|
|
DummyRead();
|
|
|
|
DummyRead();
|
|
MemoryWrite(dst, value);
|
|
DummyRead();
|
|
|
|
src += (count & 0x01) ? -1 : 1;
|
|
dst++;
|
|
|
|
count++;
|
|
length--;
|
|
} while(length);
|
|
|
|
EndBlockTransfer();
|
|
}
|
|
|
|
void PceCpu::TDD()
|
|
{
|
|
StartBlockTransfer();
|
|
|
|
uint16_t src = _operand;
|
|
uint16_t dst = _operand2;
|
|
uint16_t length = _operand3;
|
|
|
|
do {
|
|
DummyRead();
|
|
uint8_t value = MemoryRead(src);
|
|
DummyRead();
|
|
|
|
DummyRead();
|
|
MemoryWrite(dst, value);
|
|
DummyRead();
|
|
|
|
src--;
|
|
dst--;
|
|
|
|
length--;
|
|
} while(length);
|
|
|
|
EndBlockTransfer();
|
|
}
|
|
|
|
void PceCpu::TIA()
|
|
{
|
|
StartBlockTransfer();
|
|
|
|
uint16_t src = _operand;
|
|
uint16_t dst = _operand2;
|
|
uint16_t length = _operand3;
|
|
|
|
uint32_t count = 0;
|
|
do {
|
|
DummyRead();
|
|
uint8_t value = MemoryRead(src);
|
|
DummyRead();
|
|
|
|
DummyRead();
|
|
MemoryWrite(dst, value);
|
|
DummyRead();
|
|
|
|
src++;
|
|
dst += (count & 0x01) ? -1 : 1;
|
|
|
|
count++;
|
|
length--;
|
|
} while(length);
|
|
|
|
EndBlockTransfer();
|
|
}
|
|
|
|
void PceCpu::TII()
|
|
{
|
|
StartBlockTransfer();
|
|
|
|
uint16_t src = _operand;
|
|
uint16_t dst = _operand2;
|
|
uint16_t length = _operand3;
|
|
|
|
do {
|
|
DummyRead();
|
|
uint8_t value = MemoryRead(src);
|
|
DummyRead();
|
|
|
|
DummyRead();
|
|
MemoryWrite(dst, value);
|
|
DummyRead();
|
|
|
|
src++;
|
|
dst++;
|
|
|
|
length--;
|
|
} while(length);
|
|
|
|
EndBlockTransfer();
|
|
}
|
|
|
|
void PceCpu::TIN()
|
|
{
|
|
StartBlockTransfer();
|
|
|
|
uint16_t src = _operand;
|
|
uint16_t dst = _operand2;
|
|
uint16_t length = _operand3;
|
|
|
|
do {
|
|
DummyRead();
|
|
uint8_t value = MemoryRead(src);
|
|
DummyRead();
|
|
|
|
DummyRead();
|
|
MemoryWrite(dst, value);
|
|
DummyRead();
|
|
|
|
src++;
|
|
|
|
length--;
|
|
} while(length);
|
|
|
|
EndBlockTransfer();
|
|
}
|
|
|
|
void PceCpu::BBR(uint8_t bit)
|
|
{
|
|
DummyRead();
|
|
DummyRead();
|
|
|
|
uint8_t value = MemoryRead(PceCpu::ZeroPage + (_operand & 0xFF));
|
|
if((value & (1 << bit)) == 0) {
|
|
DummyRead();
|
|
DummyRead();
|
|
SetPC(PC() + (int8_t)(_operand >> 8));
|
|
}
|
|
}
|
|
|
|
void PceCpu::BBS(uint8_t bit)
|
|
{
|
|
DummyRead();
|
|
DummyRead();
|
|
|
|
uint8_t value = MemoryRead(PceCpu::ZeroPage + (_operand & 0xFF));
|
|
if((value & (1 << bit)) != 0) {
|
|
DummyRead();
|
|
DummyRead();
|
|
SetPC(PC() + (int8_t)(_operand >> 8));
|
|
}
|
|
}
|
|
|
|
void PceCpu::RMB(uint8_t bit)
|
|
{
|
|
uint8_t value = MemoryRead(_operand);
|
|
value &= ~(1 << bit);
|
|
DummyRead();
|
|
DummyRead();
|
|
MemoryWrite(_operand, value);
|
|
}
|
|
|
|
void PceCpu::SMB(uint8_t bit)
|
|
{
|
|
uint8_t value = MemoryRead(_operand);
|
|
value |= (1 << bit);
|
|
DummyRead();
|
|
DummyRead();
|
|
MemoryWrite(_operand, value);
|
|
}
|