20static constexpr uint64_t kApuCyclesNumerator = 32040 * 32;
21static constexpr uint64_t kApuCyclesDenominator = 1364 * 262 * 60;
24static constexpr uint64_t kApuCyclesNumeratorPal = 32040 * 32;
25static constexpr uint64_t kApuCyclesDenominatorPal = 1364 * 312 * 50;
33static const uint8_t bootRom[0x40] = {
34 0xcd, 0xef, 0xbd, 0xe8, 0x00, 0xc6, 0x1d, 0xd0, 0xfc, 0x8f, 0xaa,
35 0xf4, 0x8f, 0xbb, 0xf5, 0x78, 0xcc, 0xf4, 0xd0, 0xfb, 0x2f, 0x19,
36 0xeb, 0xf4, 0xd0, 0xfc, 0x7e, 0xf4, 0xd0, 0x0b, 0xe4, 0xf5, 0xcb,
37 0xf4, 0xd7, 0x00, 0xfc, 0xd0, 0xf3, 0xab, 0x01, 0x10, 0xef, 0x7e,
38 0xf4, 0x10, 0xeb, 0xba, 0xf6, 0xda, 0x00, 0xba, 0xf4, 0xc4, 0xf4,
39 0xdd, 0x5d, 0xd0, 0xdb, 0x1f, 0x00, 0x00, 0xc0, 0xff};
42static uint64_t g_last_master_cycles = 0;
43static void ResetCycleTracking() { g_last_master_cycles = 0; }
47 for (
int i = 0; i < 0x10000; i++) {
56 for (
int i = 0; i < 0x10000; i++) {
67 for (
int i = 0; i < 3; i++) {
80 LOG_DEBUG(
"APU",
"Reset complete - IPL ROM readable, PC will be at $%04X",
86 uint64_t master_delta = master_cycles - g_last_master_cycles;
87 g_last_master_cycles = master_cycles;
91 uint64_t numerator =
memory_.
pal_timing() ? kApuCyclesNumeratorPal : kApuCyclesNumerator;
92 uint64_t denominator =
memory_.
pal_timing() ? kApuCyclesDenominatorPal : kApuCyclesDenominator;
94 const uint64_t target_apu_cycles =
cycles_ + (master_delta * numerator) / denominator;
97 static uint64_t last_log_cycle = 0;
98 static uint16_t last_pc = 0;
99 static int stuck_counter = 0;
100 static bool logged_transfer_state =
false;
102 while (
cycles_ < target_apu_cycles) {
109 static uint64_t last_ipl_log = 0;
110 if (
rom_readable_ && current_pc >= 0xFFD6 && current_pc <= 0xFFED) {
111 if (
cycles_ - last_ipl_log > 10000) {
112 LOG_DEBUG(
"APU",
"IPL ROM loop: PC=$%04X Y=$%02X Ports: F4=$%02X F5=$%02X F6=$%02X F7=$%02X",
114 LOG_DEBUG(
"APU",
" Out ports: F4=$%02X F5=$%02X F6=$%02X F7=$%02X ZP: $00=$%02X $01=$%02X",
121 if (current_pc == last_pc) {
123 if (stuck_counter > 10000 &&
cycles_ - last_log_cycle > 10000) {
124 LOG_DEBUG(
"APU",
"SPC700 stuck at PC=$%04X for %d iterations",
125 current_pc, stuck_counter);
126 LOG_DEBUG(
"APU",
"Port Status: F4=$%02X F5=$%02X F6=$%02X F7=$%02X",
128 LOG_DEBUG(
"APU",
"Out Ports: F4=$%02X F5=$%02X F6=$%02X F7=$%02X",
131 LOG_DEBUG(
"APU",
"SPC700 Y=$%02X, ZP $00=$%02X $01=$%02X",
133 if (!logged_transfer_state &&
ram[0x00] == 0x19 &&
ram[0x01] == 0x00) {
134 LOG_DEBUG(
"APU",
"Uploaded byte at $0019 = $%02X",
ram[0x0019]);
135 logged_transfer_state =
true;
143 last_pc = current_pc;
155 for (
int i = 0; i < spc_cycles; ++i) {
168 for (
int i = 0; i < 3; i++) {
169 if (
timer_[i].cycles == 0) {
170 timer_[i].cycles = i == 2 ? 16 : 128;
187 static int port_read_count = 0;
208 if (port_read_count < 10) {
209 LOG_DEBUG(
"APU",
"SPC read port $%04X (F%d) = $%02X at PC=$%04X",
222 uint8_t ret =
timer_[adr - 0xfd].counter;
223 timer_[adr - 0xfd].counter = 0;
228 return bootRom[adr - 0xffc0];
234 static int port_write_count = 0;
242 for (
int i = 0; i < 3; i++) {
243 if (!
timer_[i].enabled && (val & (1 << i))) {
247 timer_[i].enabled = val & (1 << i);
260 LOG_DEBUG(
"APU",
"Control register $F1 = $%02X - IPL ROM %s at PC=$%04X",
297 if (port_write_count < 10) {
298 LOG_DEBUG(
"APU",
"SPC wrote port $%04X (F%d) = $%02X at PC=$%04X [APU_cycles=%llu]",
309 if (
ram[0x00] < 0x80) {
312 LOG_DEBUG(
"APU",
"Detected small transfer start: dest=$%02X%02X, size=%d",
327 timer_[adr - 0xfa].target = val;
std::array< Timer, 3 > timer_
uint8_t SpcRead(uint16_t address)
uint8_t Read(uint16_t address)
debug::ApuHandshakeTracker * handshake_tracker_
void Write(uint16_t address, uint8_t data)
void SpcIdle(bool waiting)
void RunCycles(uint64_t cycles)
void SpcWrite(uint16_t address, uint8_t data)
std::vector< uint8_t > ram
std::array< uint8_t, 4 > out_ports_
std::array< uint8_t, 6 > in_ports_
uint8_t Read(uint8_t adr)
void Write(uint8_t adr, uint8_t val)
auto pal_timing() const -> bool override
void Reset(bool hard=false)
uint16_t read_word(uint16_t address)
void OnSpcPCChange(uint16_t old_pc, uint16_t new_pc)
void OnSpcPortWrite(uint8_t port, uint8_t value, uint16_t pc)
#define LOG_DEBUG(category, format,...)
Main namespace for the application.