9#include "absl/strings/str_format.h"
57 uint32_t current_pc = (
PB << 16) |
PC;
74 sp = (sp & 0xff) | 0x100;
87 uint8_t high_byte =
ReadByte(0xfffd);
88 PC = low_byte | (high_byte << 8);
89 LOG_DEBUG(
"CPU",
"Reset vector: $FFFC=$%02X $FFFD=$%02X -> PC=$%04X",
90 low_byte, high_byte,
PC);
94 static int stopped_log_count = 0;
95 if (stopped_log_count++ < 5) {
96 LOG_DEBUG(
"CPU",
"CPU is STOPPED at $%02X:%04X (STP instruction executed)",
PB,
PC);
102 static int waiting_log_count = 0;
103 if (waiting_log_count++ < 5) {
104 LOG_DEBUG(
"CPU",
"CPU is WAITING at $%02X:%04X - irq_wanted=%d nmi_wanted=%d int_flag=%d",
127 static int instruction_count = 0;
129 uint16_t cur_pc =
PC - 1;
132 static bool entered_bank00 =
false;
133 static bool logged_first_nmi =
false;
135 if (
PB == 0x00 && !entered_bank00) {
136 LOG_INFO(
"CPU_AUDIO",
"=== ENTERED BANK $00 at PC=$%04X (instruction #%d) ===",
137 cur_pc, instruction_count);
138 entered_bank00 =
true;
143 LOG_INFO(
"CPU_AUDIO",
"=== FIRST NMI TRIGGERED at PC=$%02X:%04X ===",
PB, cur_pc);
144 logged_first_nmi =
true;
149 static bool logged_routines[0x10000] = {
false};
152 if (cur_pc >= 0x0080 && cur_pc <= 0x00FF) {
153 if (cur_pc == 0x0080 || cur_pc == 0x0090 || cur_pc == 0x00A0) {
154 if (!logged_routines[cur_pc]) {
155 LOG_INFO(
"CPU_AUDIO",
"NMI code: PC=$00:%04X A=$%02X X=$%04X Y=$%04X",
156 cur_pc,
A & 0xFF,
X,
Y);
157 logged_routines[cur_pc] =
true;
165 if (cur_pc >= 0x8888 && cur_pc <= 0x88FF) {
167 if (cur_pc == 0x8888) {
168 LOG_INFO(
"CPU_AUDIO",
">>> LoadSongBank ENTRY at $8888! A=$%02X X=$%04X",
174 static int exec_count_8888 = 0;
175 if (exec_count_8888++ < 100 && !logged_routines[cur_pc]) {
176 LOG_INFO(
"CPU_AUDIO",
" LoadSongBank: PC=$%04X A=$%02X X=$%04X Y=$%04X SP=$%04X [exec #%d]",
177 cur_pc,
A & 0xFF,
X,
Y,
SP(), exec_count_8888);
178 logged_routines[cur_pc] =
true;
182 if (cur_pc >= 0x88A0 && cur_pc <= 0x88B0) {
183 static int setup_count = 0;
184 if (setup_count++ < 20) {
185 LOG_INFO(
"CPU_AUDIO",
"Handshake setup area: PC=$%04X A=$%02X", cur_pc,
A & 0xFF);
191 static int handshake_log_count = 0;
192 if (cur_pc == 0x88B3 || cur_pc == 0x88B6) {
193 if (handshake_log_count++ < 20 || handshake_log_count % 500 == 0) {
195 LOG_INFO(
"CPU_AUDIO",
"Handshake wait: PC=$%04X A=$%02X F4=$%02X X=$%04X [loop #%d]",
196 cur_pc,
A & 0xFF, f4_val,
X, handshake_log_count);
203 bool should_log = instruction_count < 50;
205 LOG_DEBUG(
"CPU",
"Boot #%d: $%02X:%04X opcode=$%02X",
206 instruction_count,
PB,
PC - 1, opcode);
210 static uint16_t last_stuck_pc = 0xFFFF;
211 static int stuck_count = 0;
212 if (instruction_count >= 200) {
213 if (
PC - 1 == last_stuck_pc) {
215 if (stuck_count == 100 || stuck_count == 1000 || stuck_count == 10000) {
216 LOG_DEBUG(
"CPU",
"Stuck at $%02X:%04X opcode=$%02X for %d iterations",
217 PB,
PC - 1, opcode, stuck_count);
220 if (stuck_count > 50) {
221 LOG_DEBUG(
"CPU",
"Moved from $%02X:%04X (was stuck %d times) to $%02X:%04X",
222 PB, last_stuck_pc, stuck_count,
PB,
PC - 1);
225 last_stuck_pc =
PC - 1;
251 uint16_t cache_pc =
PC;
252 uint32_t operand = 0;
253 bool immediate =
false;
258 uint32_t vector = (
E) ? 0xfffe : 0xffe6;
271 uint32_t high =
AdrIdx(&low);
276 uint32_t vector = (
E) ? 0xfff4 : 0xffe4;
289 uint32_t high =
AdrSr(&low);
295 uint32_t high =
AdrDp(&low);
301 uint32_t high =
AdrDp(&low);
307 uint32_t high =
AdrDp(&low);
313 uint32_t high =
AdrIdl(&low);
333 A = (
A & 0xff00) | ((
A << 1) & 0xff);
366 uint32_t high =
AdrAbl(&low);
376 uint32_t high =
AdrIdy(&low,
false);
382 uint32_t high =
AdrIdp(&low);
388 uint32_t high =
AdrIsy(&low);
394 uint32_t high =
AdrDp(&low);
400 uint32_t high =
AdrDpx(&low);
406 uint32_t high =
AdrDpx(&low);
412 uint32_t high =
AdrIly(&low);
423 uint32_t high =
AdrAby(&low,
false);
430 A = (
A & 0xff00) | ((
A + 1) & 0xff);
450 uint32_t high =
AdrAbx(&low,
false);
456 uint32_t high =
AdrAbx(&low,
true);
462 uint32_t high =
AdrAlx(&low);
475 uint32_t high =
AdrIdx(&low);
491 uint32_t high =
AdrSr(&low);
497 uint32_t high =
AdrDp(&low);
503 uint32_t high =
AdrDp(&low);
509 uint32_t high =
AdrDp(&low);
515 uint32_t high =
AdrIdl(&low);
537 A = (
A & 0xff00) | (result & 0xff);
572 uint32_t high =
AdrAbl(&low);
582 uint32_t high =
AdrIdy(&low,
false);
588 uint32_t high =
AdrIdp(&low);
594 uint32_t high =
AdrIsy(&low);
600 uint32_t high =
AdrDpx(&low);
606 uint32_t high =
AdrDpx(&low);
612 uint32_t high =
AdrDpx(&low);
618 uint32_t high =
AdrIly(&low);
629 uint32_t high =
AdrAby(&low,
false);
636 A = (
A & 0xff00) | ((
A - 1) & 0xff);
651 uint32_t high =
AdrAbx(&low,
false);
657 uint32_t high =
AdrAbx(&low,
false);
663 uint32_t high =
AdrAbx(&low,
true);
669 uint32_t high =
AdrAlx(&low);
684 uint32_t high =
AdrIdx(&low);
695 uint32_t high =
AdrSr(&low);
721 uint32_t high =
AdrDp(&low);
727 uint32_t high =
AdrDp(&low);
733 uint32_t high =
AdrIdl(&low);
757 A = (
A & 0xff00) | ((
A >> 1) & 0x7f);
788 uint32_t high =
AdrAbl(&low);
798 uint32_t high =
AdrIdy(&low,
false);
804 uint32_t high =
AdrIdp(&low);
810 uint32_t high =
AdrIsy(&low);
836 uint32_t high =
AdrDpx(&low);
842 uint32_t high =
AdrDpx(&low);
848 uint32_t high =
AdrIly(&low);
859 uint32_t high =
AdrAby(&low,
false);
888 uint32_t high =
AdrAbx(&low,
false);
894 uint32_t high =
AdrAbx(&low,
true);
900 uint32_t high =
AdrAlx(&low);
914 uint32_t high =
AdrIdx(&low);
926 uint32_t high =
AdrSr(&low);
932 uint32_t high =
AdrDp(&low);
938 uint32_t high =
AdrDp(&low);
944 uint32_t high =
AdrDp(&low);
950 uint32_t high =
AdrIdl(&low);
977 A = (
A & 0xff00) | ((
A >> 1) & 0x7f) | (C << 7);
979 A = (
A >> 1) | (C << 15);
1012 uint32_t high =
AdrAbl(&low);
1022 uint32_t high =
AdrIdy(&low,
false);
1028 uint32_t high =
AdrIdp(&low);
1034 uint32_t high =
AdrIsy(&low);
1040 uint32_t high =
AdrDpx(&low);
1046 uint32_t high =
AdrDpx(&low);
1052 uint32_t high =
AdrDpx(&low);
1058 uint32_t high =
AdrIly(&low);
1069 uint32_t high =
AdrAby(&low,
false);
1095 ((
PB << 16) | ((adr +
X + 1) & 0xffff)),
true);
1100 uint32_t high =
AdrAbx(&low,
false);
1106 uint32_t high =
AdrAbx(&low,
true);
1112 uint32_t high =
AdrAlx(&low);
1122 uint32_t high =
AdrIdx(&low);
1134 uint32_t high =
AdrSr(&low);
1140 uint32_t high =
AdrDp(&low);
1146 uint32_t high =
AdrDp(&low);
1152 uint32_t high =
AdrDp(&low);
1158 uint32_t high =
AdrIdl(&low);
1186 A = (
A & 0xff00) | (
X & 0xff);
1219 uint32_t high =
AdrAbl(&low);
1229 uint32_t high =
AdrIdy(&low,
true);
1235 uint32_t high =
AdrIdp(&low);
1241 uint32_t high =
AdrIsy(&low);
1247 uint32_t high =
AdrDpx(&low);
1253 uint32_t high =
AdrDpx(&low);
1259 uint32_t high =
AdrDpy(&low);
1265 uint32_t high =
AdrIly(&low);
1272 A = (
A & 0xff00) | (
Y & 0xff);
1281 uint32_t high =
AdrAby(&low,
true);
1308 uint32_t high =
AdrAbx(&low,
true);
1314 uint32_t high =
AdrAbx(&low,
true);
1320 uint32_t high =
AdrAlx(&low);
1332 uint32_t high =
AdrIdx(&low);
1344 uint32_t high =
AdrSr(&low);
1350 uint32_t high =
AdrDp(&low);
1356 uint32_t high =
AdrDp(&low);
1362 uint32_t high =
AdrDp(&low);
1368 uint32_t high =
AdrIdl(&low);
1426 uint32_t high =
AdrAbl(&low);
1436 uint32_t high =
AdrIdy(&low,
false);
1442 uint32_t high =
AdrIdp(&low);
1448 uint32_t high =
AdrIsy(&low);
1454 uint32_t high =
AdrDpx(&low);
1460 uint32_t high =
AdrDpx(&low);
1466 uint32_t high =
AdrDpy(&low);
1472 uint16_t cur_pc =
PC - 1;
1473 if (
PB == 0x00 && (cur_pc == 0x88CF || cur_pc == 0x88D4)) {
1478 uint32_t ptr = dp0 | (dp1 << 8) | (dp2 << 16);
1479 LOG_DEBUG(
"CPU",
"LDA [$00],Y at PC=$%04X: DP=$%04X, [$00]=$%02X:$%04X, Y=$%04X",
1480 cur_pc,
D, dp2, (uint16_t)(dp0 | (dp1 << 8)),
Y);
1481 LOG_DEBUG(
"CPU",
" -> Reading 16-bit value from address $%06X", ptr +
Y);
1484 uint32_t high =
AdrIly(&low);
1487 if (
PB == 0x00 && (cur_pc == 0x88CF || cur_pc == 0x88D4)) {
1488 LOG_DEBUG(
"CPU",
" -> Read value A=$%04X",
A);
1499 uint32_t high =
AdrAby(&low,
false);
1525 uint32_t high =
AdrAbx(&low,
false);
1531 uint32_t high =
AdrAbx(&low,
false);
1537 uint32_t high =
AdrAby(&low,
false);
1543 uint32_t high =
AdrAlx(&low);
1555 uint32_t high =
AdrIdx(&low);
1568 uint32_t high =
AdrSr(&low);
1574 uint32_t high =
AdrDp(&low);
1580 uint32_t high =
AdrDp(&low);
1586 uint32_t high =
AdrDp(&low);
1592 uint32_t high =
AdrIdl(&low);
1648 uint32_t high =
AdrAbl(&low);
1658 uint32_t high =
AdrIdy(&low,
false);
1664 uint32_t high =
AdrIdp(&low);
1670 uint32_t high =
AdrIsy(&low);
1676 uint32_t high =
AdrDp(&low);
1682 uint32_t high =
AdrDpx(&low);
1688 uint32_t high =
AdrDpx(&low);
1694 uint32_t high =
AdrIly(&low);
1705 uint32_t high =
AdrAby(&low,
false);
1727 PC =
ReadWord(adr, ((adr + 1) & 0xffff),
false);
1734 uint32_t high =
AdrAbx(&low,
false);
1740 uint32_t high =
AdrAbx(&low,
true);
1746 uint32_t high =
AdrAlx(&low);
1758 uint32_t high =
AdrIdx(&low);
1771 uint32_t high =
AdrSr(&low);
1777 uint32_t high =
AdrDp(&low);
1783 uint32_t high =
AdrDp(&low);
1789 uint32_t high =
AdrDp(&low);
1795 uint32_t high =
AdrIdl(&low);
1821 uint8_t low =
A & 0xff;
1822 uint8_t high =
A >> 8;
1823 A = (low << 8) | high;
1850 uint32_t high =
AdrAbl(&low);
1860 uint32_t high =
AdrIdy(&low,
false);
1866 uint32_t high =
AdrIdp(&low);
1872 uint32_t high =
AdrIsy(&low);
1882 uint32_t high =
AdrDpx(&low);
1888 uint32_t high =
AdrDpx(&low);
1894 uint32_t high =
AdrIly(&low);
1905 uint32_t high =
AdrAby(&low,
false);
1935 uint16_t value =
ReadWord((
PB << 16) | ((adr +
X) & 0xffff),
1936 (
PB << 16) | ((adr +
X + 1) & 0xffff),
true);
1942 uint32_t high =
AdrAbx(&low,
false);
1948 uint32_t high =
AdrAbx(&low,
true);
1954 uint32_t high =
AdrAlx(&low);
1961 LogInstructions(cache_pc, opcode, operand, immediate, accumulator_mode);
1965bool immediate,
bool accumulator_mode) {
1967 uint32_t full_address = (
PB << 16) |
PC;
1970 std::vector<uint8_t> operand_bytes;
1971 std::string operand_str;
1978 if (accumulator_mode) {
1980 operand_bytes.push_back(operand & 0xFF);
1981 operand_str += absl::StrFormat(
"$%02X", operand & 0xFF);
1984 operand_bytes.push_back(operand & 0xFF);
1985 operand_bytes.push_back((operand >> 8) & 0xFF);
1986 operand_str += absl::StrFormat(
"$%04X", operand);
void Stx(uint32_t low, uint32_t high)
debug::DisassemblyViewer & disassembly_viewer()
bool GetNegativeFlag() const
uint32_t AdrAby(uint32_t *low, bool write)
bool GetInterruptFlag() const
uint32_t AdrAbl(uint32_t *low)
void Asl(uint32_t low, uint32_t high)
uint32_t AdrIdy(uint32_t *low, bool write)
void Inc(uint32_t low, uint32_t high)
uint32_t AdrSr(uint32_t *low)
void SetZN(uint16_t value, bool byte)
void Ldy(uint32_t low, uint32_t high)
uint32_t Immediate(uint32_t *low, bool xFlag)
uint16_t ReadWord(uint32_t address)
void Sta(uint32_t low, uint32_t high)
uint8_t ReadByte(uint32_t address)
uint32_t AdrIdl(uint32_t *low)
void Cpy(uint32_t low, uint32_t high)
void SetDecimalFlag(bool set)
uint32_t AdrAbx(uint32_t *low, bool write)
uint32_t AdrDp(uint32_t *low)
void Bit(uint32_t low, uint32_t high)
std::function< bool(uint32_t pc)> on_breakpoint_hit_
void And(uint32_t low, uint32_t high)
void SetZeroFlag(bool set)
void WriteByte(uint32_t address, uint8_t value)
void ORA(uint32_t low, uint32_t high)
uint32_t AdrIdp(uint32_t *low)
void Sbc(uint32_t low, uint32_t high)
void Trb(uint32_t low, uint32_t high)
void Lda(uint32_t low, uint32_t high)
void Cpx(uint32_t low, uint32_t high)
void Rol(uint32_t low, uint32_t high)
uint32_t AdrDpy(uint32_t *low)
void Tsb(uint32_t low, uint32_t high)
void Dec(uint32_t low, uint32_t high)
void SetFlags(uint8_t val)
void Ldx(uint32_t low, uint32_t high)
void PushByte(uint8_t value)
void PushWord(uint16_t value, bool int_check=false)
int GetAccumulatorSize() const
uint32_t AdrIly(uint32_t *low)
void LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand, bool immediate, bool accumulator_mode)
void SetOverflowFlag(bool set)
void ExecuteInstruction(uint8_t opcode)
uint32_t AdrIdx(uint32_t *low)
uint32_t Absolute(uint32_t *low)
uint32_t AdrAlx(uint32_t *low)
void Reset(bool hard=false)
uint16_t PopWord(bool int_check=false)
void SetCarryFlag(bool set)
void SetInterruptFlag(bool set)
bool GetCarryFlag() const
void DoBranch(bool check)
void Eor(uint32_t low, uint32_t high)
void SetSP(uint16_t value)
uint32_t AdrIsy(uint32_t *low)
debug::DisassemblyViewer * disassembly_viewer_
void Stz(uint32_t low, uint32_t high)
void Cmp(uint32_t low, uint32_t high)
uint16_t ReadOpcodeWord(bool int_check=false)
void Ror(uint32_t low, uint32_t high)
bool GetOverflowFlag() const
void Sty(uint32_t low, uint32_t high)
void Lsr(uint32_t low, uint32_t high)
uint32_t AdrDpx(uint32_t *low)
void Adc(uint32_t low, uint32_t high)
std::function< void(uint32_t address, uint8_t opcode, const std::vector< uint8_t > &operands, const std::string &mnemonic, const std::string &operand_str)> on_instruction_executed_
Advanced disassembly viewer with sparse storage and interactive features.
const std::unordered_map< uint8_t, std::string > opcode_to_mnemonic
#define LOG_DEBUG(category, format,...)
#define LOG_INFO(category, format,...)
Main namespace for the application.
std::function< void(bool waiting)> idle
std::function< uint8_t(uint32_t)> read_byte