Added logging for operand decoding
This commit is contained in:
parent
acce479cfa
commit
9c7b882f46
|
@ -24,18 +24,11 @@
|
|||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<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$/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/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.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/rom.c" beforeDir="false" afterPath="$PROJECT_DIR$/rom/rom.c" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
|
|
18
cpu/cpu.c
18
cpu/cpu.c
|
@ -1,3 +1,4 @@
|
|||
#include <log.h>
|
||||
#include "../include/cpu.h"
|
||||
#include "cpu.h"
|
||||
#include "memory.h"
|
||||
|
@ -23,6 +24,7 @@
|
|||
|
||||
CpuRegisters registers;
|
||||
Mapper mapper;
|
||||
unsigned int wait_cycle_count = 0;
|
||||
|
||||
void cpu_init() {
|
||||
registers.program_counter = 0xc000;
|
||||
|
@ -45,11 +47,12 @@ void cpu_step() {
|
|||
}
|
||||
|
||||
void cpu_add_cycles(unsigned int cycle_count) {
|
||||
|
||||
wait_cycle_count += cycle_count;
|
||||
log_trace("Waiting for %d cycles", cycle_count);
|
||||
}
|
||||
|
||||
// === Registers ===
|
||||
CpuRegisters* cpu_get_registers() {
|
||||
CpuRegisters *cpu_get_registers() {
|
||||
return ®isters;
|
||||
}
|
||||
|
||||
|
@ -117,4 +120,15 @@ void cpu_stack_pop_context() {
|
|||
address pc = cpu_stack_pop() << 8;
|
||||
pc += lo;
|
||||
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";
|
||||
}
|
||||
}
|
|
@ -42,6 +42,8 @@ typedef struct {
|
|||
bool is_page_crossing;
|
||||
} Operand;
|
||||
|
||||
char* operand_name(Operand *operand);
|
||||
|
||||
CpuRegisters* cpu_get_registers();
|
||||
byte cpu_get_flag(byte mask);
|
||||
void cpu_set_flag(bool set, byte mask);
|
||||
|
|
58
cpu/op.c
58
cpu/op.c
|
@ -61,45 +61,79 @@
|
|||
IS_UNOFFICIAL_OP_CODE_(op, line, 0x1b, ABSOLUTE_INDEXED_Y) \
|
||||
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) {
|
||||
CpuRegisters *registers = cpu_get_registers();
|
||||
address operand_addr;
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
return cpu_get_next_word();
|
||||
operand_addr = cpu_get_next_word();
|
||||
} else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_X) {
|
||||
word addr = cpu_get_next_word();
|
||||
word new_addr = addr + registers->x;
|
||||
|
||||
*page_crossing = (addr & 0xff00) != (new_addr & 0xff00);
|
||||
|
||||
return new_addr;
|
||||
operand_addr = new_addr;
|
||||
} else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_Y) {
|
||||
word addr = cpu_get_next_word();
|
||||
word new_addr = addr + registers->y;
|
||||
|
||||
*page_crossing = (addr & 0xff00) != (new_addr & 0xff00);
|
||||
|
||||
return new_addr;
|
||||
operand_addr = new_addr;
|
||||
} else if (addr_mode == ADDR_MODE_INDIRECT_JUMP) {
|
||||
word addr = cpu_get_next_word();
|
||||
if ((addr & 0xff) == 0xff) {
|
||||
// Error in NES CPU for JMP op
|
||||
word result = cpu_peek_byte(addr);
|
||||
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) {
|
||||
byte addr = cpu_get_next_byte();
|
||||
word result = cpu_peek_byte((addr + registers->x) & 0xff);
|
||||
result += cpu_peek_byte((addr + registers->x + 1) & 0xff) << 8;
|
||||
return result;
|
||||
operand_addr = result;
|
||||
} else if (addr_mode == ADDR_MODE_INDIRECT_Y) {
|
||||
byte arg_addr = cpu_get_next_byte();
|
||||
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);
|
||||
|
||||
return new_addr;
|
||||
operand_addr = new_addr;
|
||||
} else {
|
||||
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) {
|
||||
|
@ -129,6 +166,7 @@ Operand decode_operand(AddressingMode addr_mode) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
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);
|
||||
|
||||
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");
|
||||
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;
|
||||
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);
|
||||
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue