Overhaul Spc700 implementation, add apu callbacks
This commit is contained in:
@@ -5,12 +5,90 @@ namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
// Immediate
|
||||
uint8_t Spc700::imm() {
|
||||
PC++;
|
||||
return read(PC);
|
||||
// adressing modes
|
||||
|
||||
// uint16_t adrDp() {
|
||||
// return ReadOpcode() | (PSW.P << 8);
|
||||
// }
|
||||
|
||||
uint16_t Spc700::ind() {
|
||||
read(PC);
|
||||
return X | (PSW.P << 8);
|
||||
}
|
||||
|
||||
uint16_t Spc700::idx() {
|
||||
uint8_t pointer = ReadOpcode();
|
||||
callbacks_.idle(false);
|
||||
return read_word(((pointer + X) & 0xff) | (PSW.P << 8));
|
||||
}
|
||||
|
||||
uint16_t Spc700::dpx() {
|
||||
uint16_t res = ((ReadOpcode() + X) & 0xff) | (PSW.P << 8);
|
||||
callbacks_.idle(false);
|
||||
return res;
|
||||
}
|
||||
|
||||
uint16_t Spc700::dp_y() {
|
||||
uint16_t res = ((ReadOpcode() + Y) & 0xff) | (PSW.P << 8);
|
||||
callbacks_.idle(false);
|
||||
return res;
|
||||
}
|
||||
|
||||
uint16_t Spc700::abs_x() {
|
||||
uint16_t res = (ReadOpcodeWord() + X) & 0xffff;
|
||||
callbacks_.idle(false);
|
||||
return res;
|
||||
}
|
||||
|
||||
uint16_t Spc700::abs_y() {
|
||||
uint16_t res = (ReadOpcodeWord() + Y) & 0xffff;
|
||||
callbacks_.idle(false);
|
||||
return res;
|
||||
}
|
||||
|
||||
uint16_t Spc700::idy() {
|
||||
uint8_t pointer = ReadOpcode();
|
||||
uint16_t adr = read_word(pointer | (PSW.P << 8));
|
||||
callbacks_.idle(false);
|
||||
return (adr + Y) & 0xffff;
|
||||
}
|
||||
|
||||
// uint16_t adrDpDp(uint8_t* srcVal) {
|
||||
// *srcVal = read(spc, ReadOpcode() | (PSW.P << 8));
|
||||
// return ReadOpcode() | (PSW.P << 8);
|
||||
// }
|
||||
|
||||
uint16_t Spc700::dp_imm(uint8_t* srcVal) {
|
||||
*srcVal = ReadOpcode();
|
||||
return ReadOpcode() | (PSW.P << 8);
|
||||
}
|
||||
|
||||
uint16_t Spc700::ind_ind(uint8_t* srcVal) {
|
||||
read(PC);
|
||||
*srcVal = read(Y | (PSW.P << 8));
|
||||
return X | (PSW.P << 8);
|
||||
}
|
||||
|
||||
uint8_t Spc700::abs_bit(uint16_t* adr) {
|
||||
uint16_t adrBit = ReadOpcodeWord();
|
||||
*adr = adrBit & 0x1fff;
|
||||
return adrBit >> 13;
|
||||
}
|
||||
|
||||
uint16_t Spc700::dp_word(uint16_t* low) {
|
||||
uint8_t adr = ReadOpcode();
|
||||
*low = adr | (PSW.P << 8);
|
||||
return ((adr + 1) & 0xff) | (PSW.P << 8);
|
||||
}
|
||||
|
||||
uint16_t Spc700::ind_p() {
|
||||
read(PC);
|
||||
return X++ | (PSW.P << 8);
|
||||
}
|
||||
|
||||
// Immediate
|
||||
uint16_t Spc700::imm() { return PC++; }
|
||||
|
||||
// Direct page
|
||||
uint8_t Spc700::dp() {
|
||||
PC++;
|
||||
@@ -18,12 +96,6 @@ uint8_t Spc700::dp() {
|
||||
return read((PSW.P << 8) + offset);
|
||||
}
|
||||
|
||||
uint8_t& Spc700::mutable_dp() {
|
||||
PC++;
|
||||
uint8_t offset = read(PC);
|
||||
return mutable_read((PSW.P << 8) + offset);
|
||||
}
|
||||
|
||||
uint8_t Spc700::get_dp_addr() {
|
||||
PC++;
|
||||
uint8_t offset = read(PC);
|
||||
@@ -47,23 +119,24 @@ uint8_t Spc700::dp_plus_y() {
|
||||
// Indexed indirect (add index before 16-bit lookup).
|
||||
uint16_t Spc700::dp_plus_x_indirect() {
|
||||
PC++;
|
||||
uint16_t addr = read_16(PC + X);
|
||||
uint16_t addr = read_word(PC + X);
|
||||
return addr;
|
||||
}
|
||||
|
||||
// Indirect indexed (add index after 16-bit lookup).
|
||||
uint16_t Spc700::dp_indirect_plus_y() {
|
||||
PC++;
|
||||
uint16_t offset = read_16(PC);
|
||||
uint16_t offset = read_word(PC);
|
||||
return offset + Y;
|
||||
}
|
||||
|
||||
uint16_t Spc700::abs() {
|
||||
PC++;
|
||||
uint16_t addr = read(PC) | (read(PC) << 8);
|
||||
return addr;
|
||||
uint16_t Spc700::dp_dp(uint8_t* src) {
|
||||
*src = read(ReadOpcode() | (PSW.P << 8));
|
||||
return ReadOpcode() | (PSW.P << 8);
|
||||
}
|
||||
|
||||
uint16_t Spc700::abs() { return ReadOpcodeWord(); }
|
||||
|
||||
int8_t Spc700::rel() {
|
||||
PC++;
|
||||
return static_cast<int8_t>(read(PC));
|
||||
|
||||
@@ -5,10 +5,39 @@ namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
void Spc700::MOV(uint8_t& dest, uint8_t operand) {
|
||||
dest = operand;
|
||||
PSW.Z = (operand == 0);
|
||||
PSW.N = (operand & 0x80);
|
||||
// opcode functions
|
||||
|
||||
void Spc700::MOVX(uint16_t adr) {
|
||||
X = read(adr);
|
||||
PSW.Z = (X == 0);
|
||||
PSW.N = (X & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::MOVY(uint16_t adr) {
|
||||
Y = read(adr);
|
||||
PSW.Z = (Y == 0);
|
||||
PSW.N = (Y & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::MOVS(uint16_t adr) {
|
||||
read(adr);
|
||||
write(adr, A);
|
||||
}
|
||||
|
||||
void Spc700::MOVSX(uint16_t adr) {
|
||||
read(adr);
|
||||
write(adr, X);
|
||||
}
|
||||
|
||||
void Spc700::MOVSY(uint16_t adr) {
|
||||
read(adr);
|
||||
write(adr, Y);
|
||||
}
|
||||
|
||||
void Spc700::MOV(uint16_t adr) {
|
||||
A = read(adr);
|
||||
PSW.Z = (A == 0);
|
||||
PSW.N = (A & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::MOV_ADDR(uint16_t address, uint8_t operand) {
|
||||
@@ -17,75 +46,198 @@ void Spc700::MOV_ADDR(uint16_t address, uint8_t operand) {
|
||||
PSW.N = (operand & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::ADC(uint8_t& dest, uint8_t operand) {
|
||||
uint16_t result = dest + operand + PSW.C;
|
||||
PSW.V = ((A ^ result) & (operand ^ result) & 0x80);
|
||||
void Spc700::ADC(uint16_t adr) {
|
||||
uint8_t value = read(adr);
|
||||
uint16_t result = A + value + PSW.C;
|
||||
PSW.V = ((A ^ result) & (adr ^ result) & 0x80);
|
||||
PSW.C = (result > 0xFF);
|
||||
PSW.H = ((A ^ adr ^ result) & 0x10);
|
||||
A = result & 0xFF;
|
||||
PSW.Z = ((A & 0xFF) == 0);
|
||||
PSW.N = (A & 0x80);
|
||||
}
|
||||
|
||||
// void spc_adcm(uint16_t dst, uint8_t value) {
|
||||
// uint8_t applyOn = read(dst);
|
||||
// int result = applyOn + value + PSW.C;
|
||||
// spc->v =
|
||||
// (applyOn & 0x80) == (value & 0x80) && (value & 0x80) != (result &
|
||||
// 0x80);
|
||||
// PSW.H = ((applyOn & 0xf) + (value & 0xf) + PSW.C) > 0xf;
|
||||
// PSW.C = result > 0xff;
|
||||
// spc_write(dst, result);
|
||||
// spc_setZN(result);
|
||||
// }
|
||||
|
||||
void Spc700::ADCM(uint16_t& dest, uint8_t operand) {
|
||||
uint8_t applyOn = read(dest);
|
||||
int result = applyOn + operand + PSW.C;
|
||||
PSW.V = (applyOn & 0x80) == (operand & 0x80) &&
|
||||
(operand & 0x80) != (result & 0x80);
|
||||
PSW.H = ((applyOn & 0xf) + (operand & 0xf) + PSW.C) > 0xf;
|
||||
PSW.C = result > 0xff;
|
||||
write(dest, result);
|
||||
PSW.Z = ((result & 0xFF) == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
PSW.H = ((A ^ operand ^ result) & 0x10);
|
||||
dest = result & 0xFF;
|
||||
// dest = result & 0xFF;
|
||||
}
|
||||
|
||||
void Spc700::SBC(uint8_t& dest, uint8_t operand) {
|
||||
uint16_t result = dest - operand - (1 - PSW.C);
|
||||
PSW.V = ((dest ^ result) & (dest ^ operand) & 0x80);
|
||||
PSW.C = (result < 0x100);
|
||||
PSW.Z = ((result & 0xFF) == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
PSW.H = ((dest ^ operand ^ result) & 0x10);
|
||||
dest = result & 0xFF;
|
||||
// void spc_sbcm(uint16_t dst, uint8_t value) {
|
||||
// value ^= 0xff;
|
||||
// uint8_t applyOn = read(dst);
|
||||
// int result = applyOn + value + PSW.C;
|
||||
// spc->v = (applyOn & 0x80) == (value & 0x80) && (value & 0x80) != (result &
|
||||
// 0x80); PSW.H = ((applyOn & 0xf) + (value & 0xf) + PSW.C) > 0xf; PSW.C =
|
||||
// result > 0xff; spc_write(dst, result); spc_setZN(result);
|
||||
// }
|
||||
|
||||
void Spc700::SBC(uint16_t adr) {
|
||||
uint8_t value = read(adr) ^ 0xff;
|
||||
int result = A + value + PSW.C;
|
||||
PSW.V = (A & 0x80) == (value & 0x80) && (value & 0x80) != (result & 0x80);
|
||||
PSW.H = ((A & 0xf) + (value & 0xf) + PSW.C) > 0xf;
|
||||
PSW.C = result > 0xff;
|
||||
A = result;
|
||||
PSW.Z = ((A & 0xFF) == 0);
|
||||
PSW.N = (A & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::CMP(uint8_t& dest, uint8_t operand) {
|
||||
uint16_t result = dest - operand;
|
||||
PSW.C = (result < 0x100);
|
||||
PSW.Z = ((result & 0xFF) == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::AND(uint8_t& dest, uint8_t operand) {
|
||||
dest &= operand;
|
||||
PSW.Z = (dest == 0);
|
||||
PSW.N = (dest & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::OR(uint8_t& dest, uint8_t operand) {
|
||||
dest |= operand;
|
||||
PSW.Z = (dest == 0);
|
||||
PSW.N = (dest & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::EOR(uint8_t& dest, uint8_t operand) {
|
||||
dest ^= operand;
|
||||
PSW.Z = (dest == 0);
|
||||
PSW.N = (dest & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::ASL(uint8_t operand) {
|
||||
PSW.C = (operand & 0x80);
|
||||
operand <<= 1;
|
||||
PSW.Z = (operand == 0);
|
||||
PSW.N = (operand & 0x80);
|
||||
// A = value;
|
||||
}
|
||||
|
||||
void Spc700::LSR(uint8_t& operand) {
|
||||
PSW.C = (operand & 0x01);
|
||||
operand >>= 1;
|
||||
PSW.Z = (operand == 0);
|
||||
PSW.N = (operand & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::ROL(uint8_t operand, bool isImmediate) {
|
||||
uint8_t value = isImmediate ? imm() : operand;
|
||||
uint8_t carry = PSW.C;
|
||||
PSW.C = (value & 0x80);
|
||||
value <<= 1;
|
||||
value |= carry;
|
||||
PSW.Z = (value == 0);
|
||||
void Spc700::SBCM(uint16_t& dest, uint8_t operand) {
|
||||
uint8_t value = read(dest) - operand - (1 - PSW.C);
|
||||
PSW.V = ((read(dest) ^ value) & (read(dest) ^ operand) & 0x80);
|
||||
PSW.C = (value < 0x100);
|
||||
PSW.Z = ((value & 0xFF) == 0);
|
||||
PSW.N = (value & 0x80);
|
||||
// operand = value;
|
||||
PSW.H = ((read(dest) ^ operand ^ value) & 0x10);
|
||||
write(dest, value);
|
||||
}
|
||||
|
||||
void Spc700::CMPX(uint16_t adr) {
|
||||
uint8_t value = read(adr) ^ 0xff;
|
||||
int result = X + value + 1;
|
||||
PSW.C = result > 0xff;
|
||||
PSW.Z = (result == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::CMPY(uint16_t adr) {
|
||||
uint8_t value = read(adr) ^ 0xff;
|
||||
int result = Y + value + 1;
|
||||
PSW.C = result > 0xff;
|
||||
PSW.Z = (result == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::CMPM(uint16_t dst, uint8_t value) {
|
||||
value ^= 0xff;
|
||||
int result = read(dst) + value + 1;
|
||||
PSW.C = result > 0xff;
|
||||
callbacks_.idle(false);
|
||||
PSW.Z = (result == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::CMP(uint16_t adr) {
|
||||
uint8_t value = read(adr) ^ 0xff;
|
||||
int result = A + value + 1;
|
||||
PSW.C = result > 0xff;
|
||||
PSW.Z = ((result & 0xFF) == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
}
|
||||
|
||||
// void spc_andm(uint16_t dst, uint8_t value) {
|
||||
// uint8_t result = read(dst) & value;
|
||||
// spc_write(dst, result);
|
||||
// spc_setZN(result);
|
||||
// }
|
||||
|
||||
void Spc700::AND(uint16_t adr) {
|
||||
A &= read(adr);
|
||||
PSW.Z = (A == 0);
|
||||
PSW.N = (A & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::ANDM(uint16_t dest, uint8_t operand) {
|
||||
uint8_t result = read(dest) & operand;
|
||||
write(dest, result);
|
||||
PSW.Z = (result == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
}
|
||||
|
||||
// void spc_or(uint16_t adr) {
|
||||
// A |= read(adr);
|
||||
// spc_setZN(A);
|
||||
// }
|
||||
|
||||
// void spc_orm(uint16_t dst, uint8_t value) {
|
||||
// uint8_t result = read(dst) | value;
|
||||
// spc_write(dst, result);
|
||||
// spc_setZN(result);
|
||||
// }
|
||||
|
||||
void Spc700::OR(uint16_t adr) {
|
||||
A |= read(adr);
|
||||
PSW.Z = (A == 0);
|
||||
PSW.N = (A & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::ORM(uint16_t dst, uint8_t value) {
|
||||
uint8_t result = read(dst) | value;
|
||||
write(dst, result);
|
||||
PSW.Z = (result == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::EOR(uint16_t adr) {
|
||||
A ^= read(adr);
|
||||
PSW.Z = (A == 0);
|
||||
PSW.N = (A & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::EORM(uint16_t dest, uint8_t operand) {
|
||||
uint8_t result = read(dest) ^ operand;
|
||||
write(dest, result);
|
||||
PSW.Z = (result == 0);
|
||||
PSW.N = (result & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::ASL(uint16_t operand) {
|
||||
uint8_t val = read(operand);
|
||||
write(operand, val);
|
||||
PSW.C = (val & 0x80);
|
||||
val <<= 1;
|
||||
PSW.Z = (val == 0);
|
||||
PSW.N = (val & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::LSR(uint16_t adr) {
|
||||
uint8_t val = read(adr);
|
||||
PSW.C = (val & 0x01);
|
||||
val >>= 1;
|
||||
write(adr, val);
|
||||
PSW.Z = (val == 0);
|
||||
PSW.N = (val & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::ROR(uint16_t adr) {
|
||||
uint8_t val = read(adr);
|
||||
bool newC = val & 1;
|
||||
val = (val >> 1) | (PSW.C << 7);
|
||||
PSW.C = newC;
|
||||
write(adr, val);
|
||||
PSW.Z = (val == 0);
|
||||
PSW.N = (val & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::ROL(uint16_t adr) {
|
||||
uint8_t val = read(adr);
|
||||
bool newC = val & 0x80;
|
||||
val = (val << 1) | PSW.C;
|
||||
PSW.C = newC;
|
||||
write(adr, val);
|
||||
|
||||
PSW.Z = (val == 0);
|
||||
PSW.N = (val & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::XCN(uint8_t operand, bool isImmediate) {
|
||||
@@ -96,14 +248,16 @@ void Spc700::XCN(uint8_t operand, bool isImmediate) {
|
||||
// operand = value;
|
||||
}
|
||||
|
||||
void Spc700::INC(uint8_t& operand) {
|
||||
operand++;
|
||||
PSW.Z = (operand == 0);
|
||||
PSW.N = (operand & 0x80);
|
||||
void Spc700::INC(uint16_t adr) {
|
||||
uint8_t val = read(adr) + 1;
|
||||
write(adr, val);
|
||||
PSW.Z = (val == 0);
|
||||
PSW.N = (val & 0x80);
|
||||
}
|
||||
|
||||
void Spc700::DEC(uint8_t& operand) {
|
||||
operand--;
|
||||
void Spc700::DEC(uint16_t operand) {
|
||||
uint8_t val = read(operand) - 1;
|
||||
write(operand, val);
|
||||
PSW.Z = (operand == 0);
|
||||
PSW.N = (operand & 0x80);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user