Added logging for operand decoding

This commit is contained in:
william 2023-12-23 17:10:31 -05:00
parent acce479cfa
commit 9c7b882f46
5 changed files with 70 additions and 23 deletions

View File

@ -24,18 +24,11 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="0c3b231e-0637-4ac1-8964-c60fc9e9e691" name="Changes" comment="CPU"> <list default="true" id="0c3b231e-0637-4ac1-8964-c60fc9e9e691" name="Changes" comment="CPU">
<change afterPath="$PROJECT_DIR$/tests/smb.nes" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cpu/cpu.c" beforeDir="false" afterPath="$PROJECT_DIR$/cpu/cpu.c" afterDir="false" /> <change beforePath="$PROJECT_DIR$/cpu/cpu.c" beforeDir="false" afterPath="$PROJECT_DIR$/cpu/cpu.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cpu/cpu.h" beforeDir="false" afterPath="$PROJECT_DIR$/cpu/cpu.h" afterDir="false" /> <change beforePath="$PROJECT_DIR$/cpu/cpu.h" beforeDir="false" afterPath="$PROJECT_DIR$/cpu/cpu.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cpu/memory.c" beforeDir="false" afterPath="$PROJECT_DIR$/cpu/memory.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cpu/op.c" beforeDir="false" afterPath="$PROJECT_DIR$/cpu/op.c" afterDir="false" /> <change beforePath="$PROJECT_DIR$/cpu/op.c" beforeDir="false" afterPath="$PROJECT_DIR$/cpu/op.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cpu/op.h" beforeDir="false" afterPath="$PROJECT_DIR$/cpu/op.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/include/cpu.h" beforeDir="false" afterPath="$PROJECT_DIR$/include/cpu.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/include/rom.h" beforeDir="false" afterPath="$PROJECT_DIR$/include/rom.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.c" beforeDir="false" afterPath="$PROJECT_DIR$/main.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/rom/ines.c" beforeDir="false" afterPath="$PROJECT_DIR$/rom/ines.c" afterDir="false" /> <change beforePath="$PROJECT_DIR$/rom/ines.c" beforeDir="false" afterPath="$PROJECT_DIR$/rom/ines.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/rom/rom.c" beforeDir="false" afterPath="$PROJECT_DIR$/rom/rom.c" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />

View File

@ -1,3 +1,4 @@
#include <log.h>
#include "../include/cpu.h" #include "../include/cpu.h"
#include "cpu.h" #include "cpu.h"
#include "memory.h" #include "memory.h"
@ -23,6 +24,7 @@
CpuRegisters registers; CpuRegisters registers;
Mapper mapper; Mapper mapper;
unsigned int wait_cycle_count = 0;
void cpu_init() { void cpu_init() {
registers.program_counter = 0xc000; registers.program_counter = 0xc000;
@ -45,11 +47,12 @@ void cpu_step() {
} }
void cpu_add_cycles(unsigned int cycle_count) { void cpu_add_cycles(unsigned int cycle_count) {
wait_cycle_count += cycle_count;
log_trace("Waiting for %d cycles", cycle_count);
} }
// === Registers === // === Registers ===
CpuRegisters* cpu_get_registers() { CpuRegisters *cpu_get_registers() {
return &registers; return &registers;
} }
@ -118,3 +121,14 @@ void cpu_stack_pop_context() {
pc += lo; pc += lo;
registers.program_counter = pc; registers.program_counter = pc;
} }
char *operand_name(Operand *operand) {
switch (operand->type) {
case OPERAND_TYPE_ACCUMULATOR:
return "Accumulator";
case OPERAND_TYPE_IMMEDIATE:
return "Immediate";
case OPERAND_TYPE_ADDRESS:
return "Address";
}
}

View File

@ -42,6 +42,8 @@ typedef struct {
bool is_page_crossing; bool is_page_crossing;
} Operand; } Operand;
char* operand_name(Operand *operand);
CpuRegisters* cpu_get_registers(); CpuRegisters* cpu_get_registers();
byte cpu_get_flag(byte mask); byte cpu_get_flag(byte mask);
void cpu_set_flag(bool set, byte mask); void cpu_set_flag(bool set, byte mask);

View File

@ -61,45 +61,79 @@
IS_UNOFFICIAL_OP_CODE_(op, line, 0x1b, ABSOLUTE_INDEXED_Y) \ IS_UNOFFICIAL_OP_CODE_(op, line, 0x1b, ABSOLUTE_INDEXED_Y) \
IS_UNOFFICIAL_OP_CODE_(op, line, 0x1f, ABSOLUTE_INDEXED_X) IS_UNOFFICIAL_OP_CODE_(op, line, 0x1f, ABSOLUTE_INDEXED_X)
char* addr_mode_name(AddressingMode addr_mode) {
switch (addr_mode) {
case ADDR_MODE_ABSOLUTE:
return "Absolute";
case ADDR_MODE_ABSOLUTE_JUMP:
return "Absolute Jump";
case ADDR_MODE_ABSOLUTE_INDEXED_X:
return "Absolute Indexed X";
case ADDR_MODE_ABSOLUTE_INDEXED_Y:
return "Absolute Indexed Y";
case ADDR_MODE_ACCUMULATOR:
return "Accumulator";
case ADDR_MODE_IMMEDIATE:
return "Immediate";
case ADDR_MODE_IMPLICIT:
return "Implicit";
case ADDR_MODE_INDIRECT_X:
return "Indirect X";
case ADDR_MODE_INDIRECT_JUMP:
return "Indirect Jump";
case ADDR_MODE_INDIRECT_Y:
return "Indirect Y";
case ADDR_MODE_RELATIVE:
return "Relative";
case ADDR_MODE_ZERO_PAGE:
return "Zero Page";
case ADDR_MODE_ZERO_PAGE_INDEXED_X:
return "Zero Page X";
case ADDR_MODE_ZERO_PAGE_INDEXED_Y:
return "Zero Page Y";
}
}
address decode_operand_addr(AddressingMode addr_mode, bool *page_crossing) { address decode_operand_addr(AddressingMode addr_mode, bool *page_crossing) {
CpuRegisters *registers = cpu_get_registers(); CpuRegisters *registers = cpu_get_registers();
address operand_addr;
if (addr_mode == ADDR_MODE_ZERO_PAGE) { if (addr_mode == ADDR_MODE_ZERO_PAGE) {
return cpu_get_next_byte(); operand_addr = cpu_get_next_byte();
} else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_X) { } else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_X) {
return (cpu_get_next_byte() + registers->x) & 0xff; operand_addr = (cpu_get_next_byte() + registers->x) & 0xff;
} else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_Y) { } else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_Y) {
return (cpu_get_next_byte() + registers->y) & 0xff; operand_addr = (cpu_get_next_byte() + registers->y) & 0xff;
} else if (addr_mode == ADDR_MODE_ABSOLUTE || addr_mode == ADDR_MODE_ABSOLUTE_JUMP) { } else if (addr_mode == ADDR_MODE_ABSOLUTE || addr_mode == ADDR_MODE_ABSOLUTE_JUMP) {
return cpu_get_next_word(); operand_addr = cpu_get_next_word();
} else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_X) { } else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_X) {
word addr = cpu_get_next_word(); word addr = cpu_get_next_word();
word new_addr = addr + registers->x; word new_addr = addr + registers->x;
*page_crossing = (addr & 0xff00) != (new_addr & 0xff00); *page_crossing = (addr & 0xff00) != (new_addr & 0xff00);
return new_addr; operand_addr = new_addr;
} else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_Y) { } else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_Y) {
word addr = cpu_get_next_word(); word addr = cpu_get_next_word();
word new_addr = addr + registers->y; word new_addr = addr + registers->y;
*page_crossing = (addr & 0xff00) != (new_addr & 0xff00); *page_crossing = (addr & 0xff00) != (new_addr & 0xff00);
return new_addr; operand_addr = new_addr;
} else if (addr_mode == ADDR_MODE_INDIRECT_JUMP) { } else if (addr_mode == ADDR_MODE_INDIRECT_JUMP) {
word addr = cpu_get_next_word(); word addr = cpu_get_next_word();
if ((addr & 0xff) == 0xff) { if ((addr & 0xff) == 0xff) {
// Error in NES CPU for JMP op // Error in NES CPU for JMP op
word result = cpu_peek_byte(addr); word result = cpu_peek_byte(addr);
result += cpu_peek_byte(addr & 0xff00) << 8; result += cpu_peek_byte(addr & 0xff00) << 8;
return result; operand_addr = result;
} }
return cpu_peek_word(addr); operand_addr = cpu_peek_word(addr);
} else if (addr_mode == ADDR_MODE_INDIRECT_X) { } else if (addr_mode == ADDR_MODE_INDIRECT_X) {
byte addr = cpu_get_next_byte(); byte addr = cpu_get_next_byte();
word result = cpu_peek_byte((addr + registers->x) & 0xff); word result = cpu_peek_byte((addr + registers->x) & 0xff);
result += cpu_peek_byte((addr + registers->x + 1) & 0xff) << 8; result += cpu_peek_byte((addr + registers->x + 1) & 0xff) << 8;
return result; operand_addr = result;
} else if (addr_mode == ADDR_MODE_INDIRECT_Y) { } else if (addr_mode == ADDR_MODE_INDIRECT_Y) {
byte arg_addr = cpu_get_next_byte(); byte arg_addr = cpu_get_next_byte();
word addr = cpu_peek_byte(arg_addr) + (cpu_peek_byte((arg_addr + 1) & 0xff) << 8); word addr = cpu_peek_byte(arg_addr) + (cpu_peek_byte((arg_addr + 1) & 0xff) << 8);
@ -107,10 +141,13 @@ address decode_operand_addr(AddressingMode addr_mode, bool *page_crossing) {
*page_crossing = (addr & 0xff00) != (new_addr & 0xff00); *page_crossing = (addr & 0xff00) != (new_addr & 0xff00);
return new_addr; operand_addr = new_addr;
} else { } else {
assert(false); assert(false);
} }
log_trace("Operand address: %#02x, PC: %d, Addressing mode: %s", operand_addr, *page_crossing, addr_mode_name(addr_mode));
return operand_addr;
} }
Operand decode_operand(AddressingMode addr_mode) { Operand decode_operand(AddressingMode addr_mode) {
@ -129,6 +166,7 @@ Operand decode_operand(AddressingMode addr_mode) {
operand.value = decode_operand_addr(addr_mode, &operand.is_page_crossing); operand.value = decode_operand_addr(addr_mode, &operand.is_page_crossing);
} }
log_trace("Operand type: %s, value: %#02x", operand_name(&operand), operand.value);
return operand; return operand;
} }

View File

@ -128,11 +128,11 @@ bool rom_ines_read_trainer(FILE *file, INesHeader *header) {
bool rom_ines_read_prg_rom(FILE *file, INesHeader *header, Rom *rom) { bool rom_ines_read_prg_rom(FILE *file, INesHeader *header, Rom *rom) {
unsigned int prg_rom_size = header->prg_rom_size * 16384; unsigned int prg_rom_size = header->prg_rom_size * 16384;
rom->prg_rom = (char *) malloc(prg_rom_size * sizeof(char)); rom->prg_rom = (byte *) malloc(prg_rom_size * sizeof(byte));
log_debug("Reading %d bytes PRG ROM", prg_rom_size); log_debug("Reading %d bytes PRG ROM", prg_rom_size);
if (fread(rom->prg_rom, sizeof(char), prg_rom_size, file) < prg_rom_size) { if (fread(rom->prg_rom, sizeof(byte), prg_rom_size, file) < prg_rom_size) {
log_error("Failed to read PRG ROM"); log_error("Failed to read PRG ROM");
return false; return false;
} }
@ -147,11 +147,11 @@ bool rom_ines_read_chr_rom(FILE *file, INesHeader *header, Rom *rom) {
} }
unsigned int chr_rom_size = header->chr_rom_size * 8192; unsigned int chr_rom_size = header->chr_rom_size * 8192;
rom->chr_rom = (char *) malloc(chr_rom_size * sizeof(char)); rom->chr_rom = (byte *) malloc(chr_rom_size * sizeof(byte));
log_debug("Reading %d bytes CHR ROM", chr_rom_size); log_debug("Reading %d bytes CHR ROM", chr_rom_size);
if (fread(rom->chr_rom, sizeof(char), chr_rom_size, file) < chr_rom_size) { if (fread(rom->chr_rom, sizeof(byte), chr_rom_size, file) < chr_rom_size) {
log_error("Failed to read CHR ROM"); log_error("Failed to read CHR ROM");
return false; return false;
} }