feat(apu): add atomic Step() function for cycle-accurate SPC700 execution
- Add Step() method that executes one complete instruction atomically - Returns exact cycle count consumed by the instruction - Handles reset and stopped states explicitly - Uses cycle lookup table from spc700_cycles.h - Maintains compatibility with existing RunOpcode() for gradual migration This implements the LakeSnes-inspired atomic execution model while adding explicit cycle return for better testability.
This commit is contained in:
@@ -27,6 +27,43 @@ void Spc700::Reset(bool hard) {
|
||||
reset_wanted_ = true;
|
||||
}
|
||||
|
||||
int Spc700::Step() {
|
||||
// Handle reset sequence (based on 6502, brk without writes)
|
||||
if (reset_wanted_) {
|
||||
reset_wanted_ = false;
|
||||
read(PC);
|
||||
read(PC);
|
||||
read(0x100 | SP--);
|
||||
read(0x100 | SP--);
|
||||
read(0x100 | SP--);
|
||||
callbacks_.idle(false);
|
||||
PSW.I = false;
|
||||
PC = read_word(0xfffe);
|
||||
last_opcode_cycles_ = 8;
|
||||
return 8;
|
||||
}
|
||||
|
||||
// Handle stopped state (SLEEP/STOP instructions)
|
||||
if (stopped_) {
|
||||
callbacks_.idle(true);
|
||||
last_opcode_cycles_ = 2;
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Fetch and execute one complete instruction
|
||||
uint8_t opcode = ReadOpcode();
|
||||
|
||||
// Set base cycle count from lookup table
|
||||
// This will be the return value; callbacks during execution will advance APU cycles
|
||||
last_opcode_cycles_ = spc700_cycles[opcode];
|
||||
|
||||
// Execute the instruction completely (atomic execution)
|
||||
ExecuteInstructions(opcode);
|
||||
|
||||
// Return the number of cycles this instruction consumed
|
||||
return last_opcode_cycles_;
|
||||
}
|
||||
|
||||
void Spc700::RunOpcode() {
|
||||
static int entry_log = 0;
|
||||
if ((PC >= 0xFFF0 && PC <= 0xFFFF) && entry_log++ < 5) {
|
||||
|
||||
@@ -138,7 +138,11 @@ class Spc700 {
|
||||
void Reset(bool hard = false);
|
||||
|
||||
void RunOpcode();
|
||||
|
||||
|
||||
// New atomic step function - executes one complete instruction and returns cycles consumed
|
||||
// This is the preferred method for cycle-accurate emulation
|
||||
int Step();
|
||||
|
||||
// Get the number of cycles consumed by the last opcode execution
|
||||
int GetLastOpcodeCycles() const { return last_opcode_cycles_; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user