diff --git a/src/app/emu/audio/spc700.cc b/src/app/emu/audio/spc700.cc index 36d9c5b7..2dd0dc28 100644 --- a/src/app/emu/audio/spc700.cc +++ b/src/app/emu/audio/spc700.cc @@ -27,24 +27,6 @@ void Spc700::Reset(bool hard) { reset_wanted_ = true; } -void Spc700::BootIplRom() { - PC = 0xFFC0; - A = 0; - X = 0; - Y = 0; - int i = 0; - while (PC != 0xFFC0 + 0x3F) { - uint8_t opcode = read(PC); - ExecuteInstructions(opcode); - PC++; - i++; - - if (i > 1000) { - break; - } - } -} - void Spc700::RunOpcode() { if (reset_wanted_) { // based on 6502, brk without writes diff --git a/src/app/emu/audio/spc700.h b/src/app/emu/audio/spc700.h index 736bf7f1..8b039194 100644 --- a/src/app/emu/audio/spc700.h +++ b/src/app/emu/audio/spc700.h @@ -130,8 +130,6 @@ class Spc700 { void Reset(bool hard = false); - void BootIplRom(); - void RunOpcode(); void ExecuteInstructions(uint8_t opcode); diff --git a/src/app/emu/cpu/cpu.cc b/src/app/emu/cpu/cpu.cc index 0bddf99a..4b1fc591 100644 --- a/src/app/emu/cpu/cpu.cc +++ b/src/app/emu/cpu/cpu.cc @@ -66,7 +66,7 @@ void Cpu::RunOpcode() { SetSP(sp); - SetInterruptFlag(true); + E = 1; SetInterruptFlag(true); SetDecimalFlag(false); SetFlags(status); // updates x and m flags, clears @@ -346,21 +346,21 @@ void Cpu::ExecuteInstruction(uint8_t opcode) { case 0x90: // BCC Branch if carry clear { operand = FetchByte(); - BCC(operand); + DoBranch(!GetCarryFlag()); break; } case 0xB0: // BCS Branch if carry set { operand = FetchByte(); - BCS(operand); + DoBranch(GetCarryFlag()); break; } case 0xF0: // BEQ Branch if equal (zero set) { operand = FetchByte(); - BEQ(operand); + DoBranch(GetZeroFlag()); break; } @@ -398,29 +398,27 @@ void Cpu::ExecuteInstruction(uint8_t opcode) { case 0x30: // BMI Branch if minus (negative set) { - operand = FetchByte(); - BMI(operand); + DoBranch(GetNegativeFlag()); break; } case 0xD0: // BNE Branch if not equal (zero clear) { - operand = FetchSignedByte(); - BNE(operand); + DoBranch(!GetZeroFlag()); break; } case 0x10: // BPL Branch if plus (negative clear) { - operand = FetchSignedByte(); - BPL(operand); + operand = FetchByte(); + DoBranch(!GetNegativeFlag()); break; } case 0x80: // BRA Branch always { operand = FetchByte(); - BRA(operand); + DoBranch(true); break; } @@ -431,7 +429,7 @@ void Cpu::ExecuteInstruction(uint8_t opcode) { } case 0x82: // BRL Branch always long - { // operand = FetchSignedWord(); + { operand = FetchWord(); BRL(operand); break; @@ -440,14 +438,14 @@ void Cpu::ExecuteInstruction(uint8_t opcode) { case 0x50: // BVC Branch if overflow clear { operand = FetchByte(); - BVC(operand); + DoBranch(!GetOverflowFlag()); break; } case 0x70: // BVS Branch if overflow set { operand = FetchByte(); - BVS(operand); + DoBranch(GetOverflowFlag()); break; } @@ -796,7 +794,7 @@ void Cpu::ExecuteInstruction(uint8_t opcode) { } case 0x5C: // JMP Absolute Long { - JML(AbsoluteLong()); + JML(FetchWord()); break; } case 0x6C: // JMP Absolute Indirect @@ -827,7 +825,7 @@ void Cpu::ExecuteInstruction(uint8_t opcode) { case 0x22: // JSL Absolute Long { - JSL(AbsoluteLong()); + JSL(FetchWord()); break; } @@ -1023,8 +1021,16 @@ void Cpu::ExecuteInstruction(uint8_t opcode) { break; } + case 0x42: + WDM(); + break; + + case 0x44: + MVP(); + break; + case 0x54: - // MVN(); + MVN(); break; case 0xEA: // NOP @@ -1604,14 +1610,12 @@ uint8_t Cpu::GetInstructionLength(uint8_t opcode) { case 0x00: // BRK case 0x02: // COP PC = next_pc_; + PB = next_pb_; return 0; - // TODO: Handle JMPs in logging. case 0x20: // JSR Absolute case 0x4C: // JMP Absolute case 0x6C: // JMP Absolute Indirect - case 0x5C: // JMP Absolute Indexed Indirect - case 0x22: // JSL Absolute Long case 0x7C: // JMP Absolute Indexed Indirect case 0xFC: // JSR Absolute Indexed Indirect case 0xDC: // JMP Absolute Indirect Long @@ -1620,6 +1624,12 @@ uint8_t Cpu::GetInstructionLength(uint8_t opcode) { PC = next_pc_; return 0; + case 0x22: // JSL Absolute Long + case 0x5C: // JMP Absolute Indexed Indirect + PC = next_pc_; + PB = next_pb_; + return 0; + case 0x80: // BRA Relative PC += next_pc_; return 2; diff --git a/src/app/emu/cpu/cpu.h b/src/app/emu/cpu/cpu.h index cb566516..c3cb0cf4 100644 --- a/src/app/emu/cpu/cpu.h +++ b/src/app/emu/cpu/cpu.h @@ -250,6 +250,16 @@ class Cpu : public Loggable, public core::ExperimentFlags { return (high << 16) | low; } + void DoBranch(bool check) { + if (!check) CheckInt(); + uint8_t value = FetchByte(); + if (check) { + CheckInt(); + callbacks_.idle(false); // taken branch: 1 extra cycle + next_pc_ += (int8_t)value; + } + } + // ========================================================================== // Addressing Modes @@ -519,13 +529,13 @@ class Cpu : public Loggable, public core::ExperimentFlags { void JMP(uint16_t address); // JML: Jump long - void JML(uint32_t address); + void JML(uint16_t address); // JSR: Jump to subroutine void JSR(uint16_t address); // JSL: Jump to subroutine long - void JSL(uint32_t address); + void JSL(uint16_t address); // LDA: Load accumulator void LDA(uint16_t address, bool immediate = false, bool direct_page = false, @@ -541,10 +551,10 @@ class Cpu : public Loggable, public core::ExperimentFlags { void LSR(uint16_t address, bool accumulator = false); // MVN: Block move next - void MVN(uint16_t source, uint16_t dest, uint16_t length); + void MVN(); // MVP: Block move previous - void MVP(uint16_t source, uint16_t dest, uint16_t length); + void MVP(); // NOP: No operation void NOP(); @@ -769,6 +779,7 @@ class Cpu : public Loggable, public core::ExperimentFlags { uint16_t last_call_frame_; uint16_t next_pc_; + uint8_t next_pb_; memory::CpuCallbacks callbacks_; memory::Memory& memory; diff --git a/src/app/emu/cpu/internal/instructions.cc b/src/app/emu/cpu/internal/instructions.cc index ccd116ed..0d12671a 100644 --- a/src/app/emu/cpu/internal/instructions.cc +++ b/src/app/emu/cpu/internal/instructions.cc @@ -10,13 +10,12 @@ namespace emu { /** * 65816 Instruction Set - * - * TODO: STP, WDM */ void Cpu::ADC(uint16_t operand) { bool C = GetCarryFlag(); if (GetAccumulatorSize()) { // 8-bit mode + CheckInt(); uint16_t result = static_cast(A & 0xFF) + static_cast(operand) + (C ? 1 : 0); SetCarryFlag(result > 0xFF); // Update the carry flag @@ -50,6 +49,7 @@ void Cpu::ADC(uint16_t operand) { void Cpu::AND(uint32_t value, bool isImmediate) { uint16_t operand; if (GetAccumulatorSize()) { // 8-bit mode + CheckInt(); operand = isImmediate ? value : ReadByte(value); A &= operand; SetZeroFlag(A == 0); @@ -71,13 +71,24 @@ void Cpu::ANDAbsoluteLong(uint32_t address) { } void Cpu::ASL(uint16_t address) { - uint8_t value = ReadByte(address); - SetCarryFlag(!(value & 0x80)); // Set carry flag if bit 7 is set - value <<= 1; // Shift left - value &= 0xFE; // Clear bit 0 - WriteByte(address, value); - SetNegativeFlag(!value); - SetZeroFlag(value); + if (GetAccumulatorSize()) { // 8-bit mode + uint8_t value = ReadByte(address); + callbacks_.idle(false); + SetCarryFlag(value & 0x80); + value <<= 1; + CheckInt(); + WriteByte(address, value); + SetZeroFlag(value == 0); + SetNegativeFlag(value & 0x80); + } else { // 16-bit mode + uint16_t value = ReadWord(address); + callbacks_.idle(false); + SetCarryFlag(value & 0x8000); + value <<= 1; + WriteWord(address, value); + SetZeroFlag(value == 0); + SetNegativeFlag(value & 0x8000); + } } void Cpu::BCC(int8_t offset) { @@ -99,6 +110,7 @@ void Cpu::BEQ(int8_t offset) { } void Cpu::BIT(uint16_t address) { + CheckInt(); uint8_t value = ReadByte(address); SetNegativeFlag(value & 0x80); SetOverflowFlag(value & 0x40); @@ -107,39 +119,43 @@ void Cpu::BIT(uint16_t address) { void Cpu::BMI(int8_t offset) { if (GetNegativeFlag()) { // If the negative flag is set - next_pc_ = offset; + next_pc_ = PC + offset; } } void Cpu::BNE(int8_t offset) { if (!GetZeroFlag()) { // If the zero flag is clear // PC += offset; - next_pc_ = offset; + next_pc_ = PC + offset; } } void Cpu::BPL(int8_t offset) { if (!GetNegativeFlag()) { // If the negative flag is clear - next_pc_ = offset; + next_pc_ = PC + offset; } } -void Cpu::BRA(int8_t offset) { next_pc_ = offset; } +void Cpu::BRA(int8_t offset) { next_pc_ = PC + offset; } void Cpu::BRK() { // ReadOpcode(); - next_pc_ += 2; // Increment the program counter by 2 - ReadByte(PC); // Read the next byte + next_pc_ = PC + 2; // Increment the program counter by 2 + ReadByte(PC); // Read the next byte PushByte(PB); PushByte(PC); // ,false PushByte(status); SetInterruptFlag(true); SetDecimalFlag(false); - PB = 0; - PC = ReadWord(0xFFE6); // ,true + next_pb_ = 0; + next_pc_ = ReadWord(0xFFE6); // ,true } -void Cpu::BRL(int16_t offset) { next_pc_ = offset; } +void Cpu::BRL(int16_t offset) { + next_pc_ = PC + offset; + CheckInt(); + callbacks_.idle(false); +} void Cpu::BVC(int8_t offset) { if (!GetOverflowFlag()) { // If the overflow flag is clear @@ -153,19 +169,32 @@ void Cpu::BVS(int8_t offset) { } } -void Cpu::CLC() { status &= ~0x01; } +void Cpu::CLC() { + AdrImp(); + status &= ~0x01; +} -void Cpu::CLD() { status &= ~0x08; } +void Cpu::CLD() { + AdrImp(); + status &= ~0x08; +} -void Cpu::CLI() { status &= ~0x04; } +void Cpu::CLI() { + AdrImp(); + status &= ~0x04; +} -void Cpu::CLV() { status &= ~0x40; } +void Cpu::CLV() { + AdrImp(); + status &= ~0x40; +} // n Set if MSB of result is set; else cleared // z Set if result is zero; else cleared // c Set if no borrow; else cleared void Cpu::CMP(uint32_t value, bool isImmediate) { if (GetAccumulatorSize()) { // 8-bit + CheckInt(); uint8_t result; if (isImmediate) { result = A - (value & 0xFF); @@ -191,7 +220,7 @@ void Cpu::CMP(uint32_t value, bool isImmediate) { } void Cpu::COP() { - next_pc_ += 2; // Increment the program counter by 2 + next_pc_ = PC + 2; // Increment the program counter by 2 PushWord(next_pc_); PushByte(status); SetInterruptFlag(true); @@ -201,10 +230,13 @@ void Cpu::COP() { next_pc_ = ReadWord(0xFFE4); } SetDecimalFlag(false); + next_pb_ = 0; + next_pc_ = ReadWord(0xFFE4); } void Cpu::CPX(uint32_t value, bool isImmediate) { if (GetIndexSize()) { // 8-bit + CheckInt(); uint8_t memory_value = isImmediate ? value : ReadByte(value); compare(X, memory_value); } else { // 16-bit @@ -215,6 +247,7 @@ void Cpu::CPX(uint32_t value, bool isImmediate) { void Cpu::CPY(uint32_t value, bool isImmediate) { if (GetIndexSize()) { // 8-bit + CheckInt(); uint8_t memory_value = isImmediate ? value : ReadByte(value); compare(Y, memory_value); } else { // 16-bit @@ -225,6 +258,7 @@ void Cpu::CPY(uint32_t value, bool isImmediate) { void Cpu::DEC(uint32_t address, bool accumulator) { if (accumulator) { + AdrImp(); if (GetAccumulatorSize()) { // 8-bit A = (A - 1) & 0xFF; SetZeroFlag(A == 0); @@ -240,12 +274,15 @@ void Cpu::DEC(uint32_t address, bool accumulator) { if (GetAccumulatorSize()) { uint8_t value = ReadByte(address); value--; + callbacks_.idle(false); + CheckInt(); WriteByte(address, value); SetZeroFlag(value == 0); SetNegativeFlag(value & 0x80); } else { uint16_t value = ReadWord(address); value--; + callbacks_.idle(false); WriteWord(address, value); SetZeroFlag(value == 0); SetNegativeFlag(value & 0x8000); @@ -253,6 +290,7 @@ void Cpu::DEC(uint32_t address, bool accumulator) { } void Cpu::DEX() { + AdrImp(); if (GetIndexSize()) { // 8-bit X = static_cast(X - 1); SetZeroFlag(X == 0); @@ -265,6 +303,7 @@ void Cpu::DEX() { } void Cpu::DEY() { + AdrImp(); if (GetIndexSize()) { // 8-bit Y = static_cast(Y - 1); SetZeroFlag(Y == 0); @@ -278,6 +317,7 @@ void Cpu::DEY() { void Cpu::EOR(uint32_t address, bool isImmediate) { if (GetAccumulatorSize()) { + CheckInt(); A ^= isImmediate ? address : ReadByte(address); SetZeroFlag(A == 0); SetNegativeFlag(A & 0x80); @@ -290,6 +330,7 @@ void Cpu::EOR(uint32_t address, bool isImmediate) { void Cpu::INC(uint32_t address, bool accumulator) { if (accumulator) { + AdrImp(); if (GetAccumulatorSize()) { // 8-bit A = (A + 1) & 0xFF; SetZeroFlag(A == 0); @@ -305,12 +346,15 @@ void Cpu::INC(uint32_t address, bool accumulator) { if (GetAccumulatorSize()) { uint8_t value = ReadByte(address); value++; + callbacks_.idle(false); + CheckInt(); WriteByte(address, value); SetNegativeFlag(value & 0x80); SetZeroFlag(value == 0); } else { uint16_t value = ReadWord(address); value++; + callbacks_.idle(false); WriteWord(address, value); SetNegativeFlag(value & 0x8000); SetZeroFlag(value == 0); @@ -318,6 +362,7 @@ void Cpu::INC(uint32_t address, bool accumulator) { } void Cpu::INX() { + AdrImp(); if (GetIndexSize()) { // 8-bit X = static_cast(X + 1); SetZeroFlag(X == 0); @@ -330,6 +375,7 @@ void Cpu::INX() { } void Cpu::INY() { + AdrImp(); if (GetIndexSize()) { // 8-bit Y = static_cast(Y + 1); SetZeroFlag(Y == 0); @@ -345,21 +391,26 @@ void Cpu::JMP(uint16_t address) { next_pc_ = address; // Set program counter to the new address } -void Cpu::JML(uint32_t address) { - next_pc_ = static_cast(address & 0xFFFF); - // Set the PBR to the upper 8 bits of the address - PB = static_cast((address >> 16) & 0xFF); +void Cpu::JML(uint16_t address) { + CheckInt(); + next_pc_ = address; + uint8_t new_pb = ReadByte(PC + 2); + next_pb_ = new_pb; } void Cpu::JSR(uint16_t address) { + callbacks_.idle(false); PushWord(PC); // Push the program counter onto the stack next_pc_ = address; // Set program counter to the new address } -void Cpu::JSL(uint32_t address) { - PushLong(PC); // Push the program counter onto the stack as a long - // value (24 bits) +void Cpu::JSL(uint16_t address) { + PushByte(PB); + callbacks_.idle(false); + uint8_t new_pb = ReadByte(PC + 2); + PushWord(PC); next_pc_ = address; // Set program counter to the new address + next_pb_ = new_pb; } void Cpu::LDA(uint16_t address, bool isImmediate, bool direct_page, @@ -369,6 +420,7 @@ void Cpu::LDA(uint16_t address, bool isImmediate, bool direct_page, bank = 0; } if (GetAccumulatorSize()) { + CheckInt(); A = isImmediate ? address : ReadByte((bank << 16) | address); SetZeroFlag(A == 0); SetNegativeFlag(A & 0x80); @@ -381,6 +433,7 @@ void Cpu::LDA(uint16_t address, bool isImmediate, bool direct_page, void Cpu::LDX(uint16_t address, bool isImmediate) { if (GetIndexSize()) { + CheckInt(); X = isImmediate ? address : ReadByte(address); SetZeroFlag(X == 0); SetNegativeFlag(X & 0x80); @@ -393,6 +446,7 @@ void Cpu::LDX(uint16_t address, bool isImmediate) { void Cpu::LDY(uint16_t address, bool isImmediate) { if (GetIndexSize()) { + CheckInt(); Y = isImmediate ? address : ReadByte(address); SetZeroFlag(Y == 0); SetNegativeFlag(Y & 0x80); @@ -405,6 +459,7 @@ void Cpu::LDY(uint16_t address, bool isImmediate) { void Cpu::LSR(uint16_t address, bool accumulator) { if (accumulator) { + AdrImp(); if (GetAccumulatorSize()) { // 8-bit SetCarryFlag(A & 0x01); A >>= 1; @@ -418,46 +473,73 @@ void Cpu::LSR(uint16_t address, bool accumulator) { } return; } - uint8_t value = ReadByte(address); - SetCarryFlag(value & 0x01); - value >>= 1; - WriteByte(address, value); - SetNegativeFlag(false); - SetZeroFlag(value == 0); -} -void Cpu::MVN(uint16_t source, uint16_t dest, uint16_t length) { - for (uint16_t i = 0; i < length; i++) { - WriteByte(dest, ReadByte(source)); - source++; - dest++; + if (GetAccumulatorSize()) { + uint8_t value = ReadByte(address); + callbacks_.idle(false); + SetCarryFlag(value & 0x01); + value >>= 1; + CheckInt(); + WriteByte(address, value); + SetNegativeFlag(false); + SetZeroFlag(value == 0); + } else { + uint16_t value = ReadWord(address); + SetCarryFlag(value & 0x0001); + value >>= 1; + WriteWord(address, value); + SetNegativeFlag(false); + SetZeroFlag(value == 0); } } -void Cpu::MVP(uint16_t source, uint16_t dest, uint16_t length) { - for (uint16_t i = 0; i < length; i++) { - WriteByte(dest, ReadByte(source)); - source--; - dest--; +void Cpu::MVN() { + uint8_t dest = ReadByte(PC + 1); + uint8_t src = ReadByte(PC + 2); + next_pc_ = PC + 3; + DB = dest; + WriteByte((dest << 16) | Y, ReadByte((src << 16) | X)); + A--; + X++; + Y++; + if (A != 0xFFFF) { + next_pc_ -= 3; } + if (GetIndexSize()) { + X &= 0xFF; + Y &= 0xFF; + } + callbacks_.idle(false); + CheckInt(); + callbacks_.idle(false); +} + +void Cpu::MVP() { + uint8_t dest = ReadByte(PC + 1); + uint8_t src = ReadByte(PC + 2); + next_pc_ = PC + 3; + DB = dest; + WriteByte((dest << 16) | Y, ReadByte((src << 16) | X)); + A--; + X--; + Y--; + if (A != 0xFFFF) { + next_pc_ -= 3; + } + if (GetIndexSize()) { + X &= 0xFF; + Y &= 0xFF; + } + callbacks_.idle(false); + CheckInt(); + callbacks_.idle(false); } void Cpu::NOP() { AdrImp(); } -// void cpu_ora(uint32_t low, uint32_t high) { -// if (cpu->mf) { -// CheckInt(); -// uint8_t value = cpu_read(cpu, low); -// cpu->a = (cpu->a & 0xff00) | ((cpu->a | value) & 0xff); -// } else { -// uint16_t value = cpu_readWord(cpu, low, high, true); -// cpu->a |= value; -// } -// cpu_setZN(cpu, cpu->a, cpu->mf); -// } - void Cpu::ORA(uint16_t address, bool isImmediate) { if (GetAccumulatorSize()) { + CheckInt(); A |= isImmediate ? address : ReadByte(address); SetZeroFlag(A == 0); SetNegativeFlag(A & 0x80); @@ -615,6 +697,7 @@ void Cpu::REP() { void Cpu::ROL(uint32_t address, bool accumulator) { if (accumulator) { + AdrImp(); if (GetAccumulatorSize()) { // 8-bit uint8_t carry = GetCarryFlag() ? 0x01 : 0x00; SetCarryFlag(A & 0x80); @@ -633,18 +716,33 @@ void Cpu::ROL(uint32_t address, bool accumulator) { return; } - uint8_t value = ReadByte(address); - uint8_t carry = GetCarryFlag() ? 0x01 : 0x00; - SetCarryFlag(value & 0x80); - value <<= 1; - value |= carry; - WriteByte(address, value); - SetNegativeFlag(value & 0x80); - SetZeroFlag(value == 0); + if (GetAccumulatorSize()) { + uint8_t value = ReadByte(address); + callbacks_.idle(false); + uint8_t carry = GetCarryFlag() ? 0x01 : 0x00; + SetCarryFlag(value & 0x80); + value <<= 1; + value |= carry; + CheckInt(); + WriteByte(address, value); + SetNegativeFlag(value & 0x80); + SetZeroFlag(value == 0); + } else { + uint16_t value = ReadWord(address); + callbacks_.idle(false); + uint8_t carry = GetCarryFlag() ? 0x01 : 0x00; + SetCarryFlag(value & 0x8000); + value <<= 1; + value |= carry; + WriteWord(address, value); + SetNegativeFlag(value & 0x8000); + SetZeroFlag(value == 0); + } } void Cpu::ROR(uint32_t address, bool accumulator) { if (accumulator) { + AdrImp(); if (GetAccumulatorSize()) { // 8-bit uint8_t carry = GetCarryFlag() ? 0x80 : 0x00; SetCarryFlag(A & 0x01); @@ -663,27 +761,54 @@ void Cpu::ROR(uint32_t address, bool accumulator) { return; } - uint8_t value = ReadByte(address); - uint8_t carry = GetCarryFlag() ? 0x80 : 0x00; - SetCarryFlag(value & 0x01); - value >>= 1; - value |= carry; - WriteByte(address, value); - SetNegativeFlag(value & 0x80); - SetZeroFlag(value == 0); + if (GetAccumulatorSize()) { + uint8_t value = ReadByte(address); + callbacks_.idle(false); + uint8_t carry = GetCarryFlag() ? 0x80 : 0x00; + SetCarryFlag(value & 0x01); + value >>= 1; + value |= carry; + CheckInt(); + WriteByte(address, value); + SetNegativeFlag(value & 0x80); + SetZeroFlag(value == 0); + } else { + uint16_t value = ReadWord(address); + callbacks_.idle(false); + uint8_t carry = GetCarryFlag() ? 0x8000 : 0x00; + SetCarryFlag(value & 0x0001); + value >>= 1; + value |= carry; + WriteWord(address, value); + SetNegativeFlag(value & 0x8000); + SetZeroFlag(value == 0); + } } void Cpu::RTI() { + callbacks_.idle(false); + callbacks_.idle(false); status = PopByte(); - PC = PopWord(); + next_pc_ = PopWord(); + CheckInt(); + next_pb_ = PopByte(); } void Cpu::RTL() { + callbacks_.idle(false); + callbacks_.idle(false); next_pc_ = PopWord(); - PB = PopByte(); + CheckInt(); + next_pb_ = PopByte(); } -void Cpu::RTS() { last_call_frame_ = PopWord(); } +void Cpu::RTS() { + callbacks_.idle(false); + callbacks_.idle(false); + last_call_frame_ = PopWord(); + CheckInt(); + callbacks_.idle(false); +} void Cpu::SBC(uint32_t value, bool isImmediate) { uint16_t operand; @@ -702,6 +827,7 @@ void Cpu::SBC(uint32_t value, bool isImmediate) { SetZeroFlag(A == 0); SetNegativeFlag(A & 0x8000); } else { // 8-bit mode + CheckInt(); operand = isImmediate ? value : ReadByte(value); uint8_t result = A - operand - (GetCarryFlag() ? 0 : 1); SetCarryFlag(!(result > 0xFF)); // Update the carry flag @@ -718,11 +844,20 @@ void Cpu::SBC(uint32_t value, bool isImmediate) { } } -void Cpu::SEC() { status |= 0x01; } +void Cpu::SEC() { + AdrImp(); + status |= 0x01; +} -void Cpu::SED() { status |= 0x08; } +void Cpu::SED() { + AdrImp(); + status |= 0x08; +} -void Cpu::SEI() { status |= 0x04; } +void Cpu::SEI() { + AdrImp(); + status |= 0x04; +} void Cpu::SEP() { auto byte = FetchByte(); @@ -733,6 +868,7 @@ void Cpu::SEP() { void Cpu::STA(uint32_t address) { if (GetAccumulatorSize()) { + CheckInt(); WriteByte(address, static_cast(A)); } else { WriteWord(address, A); @@ -747,6 +883,7 @@ void Cpu::STP() { void Cpu::STX(uint16_t address) { if (GetIndexSize()) { + CheckInt(); WriteByte(address, static_cast(X)); } else { WriteWord(address, X); @@ -755,6 +892,7 @@ void Cpu::STX(uint16_t address) { void Cpu::STY(uint16_t address) { if (GetIndexSize()) { + CheckInt(); WriteByte(address, static_cast(Y)); } else { WriteWord(address, Y); @@ -763,6 +901,7 @@ void Cpu::STY(uint16_t address) { void Cpu::STZ(uint16_t address) { if (GetAccumulatorSize()) { + CheckInt(); WriteByte(address, 0x00); } else { WriteWord(address, 0x0000); @@ -770,46 +909,82 @@ void Cpu::STZ(uint16_t address) { } void Cpu::TAX() { - X = A; + AdrImp(); + if (GetIndexSize()) { + X = A & 0xFF; + } else { + X = A; + } SetZeroFlag(X == 0); SetNegativeFlag(X & 0x80); } void Cpu::TAY() { - Y = A; + AdrImp(); + if (GetIndexSize()) { + Y = A & 0xFF; + } else { + Y = A; + } SetZeroFlag(Y == 0); SetNegativeFlag(Y & 0x80); } void Cpu::TCD() { + AdrImp(); D = A; SetZeroFlag(D == 0); SetNegativeFlag(D & 0x80); } -void Cpu::TCS() { SetSP(A); } +void Cpu::TCS() { + AdrImp(); + SetSP(A); +} void Cpu::TDC() { + AdrImp(); A = D; SetZeroFlag(A == 0); SetNegativeFlag(A & 0x80); } void Cpu::TRB(uint16_t address) { - uint8_t value = ReadByte(address); - SetZeroFlag((A & value) == 0); - value &= ~A; - WriteByte(address, value); + if (GetAccumulatorSize()) { + uint8_t value = ReadByte(address); + callbacks_.idle(false); + SetZeroFlag((A & value) == 0); + value &= ~A; + CheckInt(); + WriteByte(address, value); + } else { + uint16_t value = ReadWord(address); + callbacks_.idle(false); + SetZeroFlag((A & value) == 0); + value &= ~A; + WriteWord(address, value); + } } void Cpu::TSB(uint16_t address) { - uint8_t value = ReadByte(address); - SetZeroFlag((A & value) == 0); - value |= A; - WriteByte(address, value); + if (GetAccumulatorSize()) { + uint8_t value = ReadByte(address); + callbacks_.idle(false); + SetZeroFlag((A & value) == 0); + value |= A; + CheckInt(); + WriteByte(address, value); + } else { + uint16_t value = ReadWord(address); + callbacks_.idle(false); + SetZeroFlag((A & value) == 0); + value |= A; + WriteWord(address, value); + } } void Cpu::TSC() { + AdrImp(); A = SP(); SetZeroFlag(A == 0); SetNegativeFlag(A & 0x80); @@ -817,14 +992,22 @@ void Cpu::TSC() { void Cpu::TSX() { AdrImp(); - X = SP(); + if (GetIndexSize()) { + X = SP() & 0xFF; + } else { + X = SP(); + } SetZeroFlag(X == 0); SetNegativeFlag(X & 0x80); } void Cpu::TXA() { AdrImp(); - A = X; + if (GetAccumulatorSize()) { + A = X & 0xFF; + } else { + A = X; + } SetZeroFlag(A == 0); SetNegativeFlag(A & 0x80); } @@ -836,14 +1019,22 @@ void Cpu::TXS() { void Cpu::TXY() { AdrImp(); - Y = X; + if (GetIndexSize()) { + Y = X & 0xFF; + } else { + Y = X; + } SetZeroFlag(X == 0); SetNegativeFlag(X & 0x80); } void Cpu::TYA() { AdrImp(); - A = Y; + if (GetAccumulatorSize()) { + A = Y & 0xFF; + } else { + A = Y; + } SetZeroFlag(A == 0); SetNegativeFlag(A & 0x80); } @@ -865,6 +1056,11 @@ void Cpu::WAI() { callbacks_.idle(false); } +void Cpu::WDM() { + CheckInt(); + ReadByte(PC); +} + void Cpu::XBA() { uint8_t lowByte = A & 0xFF; uint8_t highByte = (A >> 8) & 0xFF; diff --git a/src/app/emu/memory/dma.h b/src/app/emu/memory/dma.h index 38c37238..d905c162 100644 --- a/src/app/emu/memory/dma.h +++ b/src/app/emu/memory/dma.h @@ -25,7 +25,7 @@ void TransferByte(SNES* snes, MemoryImpl* memory, uint16_t aAdr, uint8_t aBank, uint8_t Read(MemoryImpl* memory, uint16_t address); void Write(MemoryImpl* memory, uint16_t address, uint8_t data); void StartDma(MemoryImpl* memory, uint8_t val, bool hdma); -void DoDma(MemoryImpl* memory, int cycles); +void DoDma(SNES* snes, MemoryImpl* memory, int cycles); } // namespace dma } // namespace memory