nesemu/cpu/cpu.c

158 lines
4.1 KiB
C
Raw Normal View History

2024-04-30 12:28:43 -04:00
//#include "log.h"
2024-01-06 14:27:09 -05:00
#include <assert.h>
#include <string.h>
2023-11-26 12:11:49 -05:00
#include "../include/cpu.h"
#include "cpu.h"
#include "memory.h"
2023-12-23 16:35:23 -05:00
#include "op.h"
2024-01-09 15:56:54 -05:00
#include "decoding.h"
2024-04-30 12:28:43 -04:00
#include "log.h"
2023-11-26 12:11:49 -05:00
2023-09-21 23:53:14 -04:00
/*
* =====================================================================================
*
* Filename: cpu.c
*
* Description: 6502 CPU emulator
*
* Version: 1.0
* Created: 2023-09-21 10:10:26 PM
* Revision: none
* Compiler: gcc
*
* Author: William Nolin,
* Organization:
*
* =====================================================================================
*/
2024-01-06 14:27:09 -05:00
void cpu_init(CPU *cpu) {
cpu->program_counter = 0x8000;
cpu->stack_pointer = 0xfd;
cpu->accumulator = 0x00;
cpu->x = 0x00;
cpu->y = 0x00;
cpu->status = 0x04;
cpu->oam_dma_triggered = false;
2024-05-04 22:16:12 -04:00
cpu->nmi_requested = false;
2024-01-06 14:27:09 -05:00
}
void print_registers(CPU cpu, byte op, unsigned long cycle_count) {
log_debug("%#02x %#02x %s \t A:%#02x X:%#02x Y:%#02x F:%#02x SP:%#02x \t [%d]",
cpu.program_counter,
op,
get_op_code_name(op),
cpu.accumulator,
cpu.x,
cpu.y,
cpu.status,
cpu.stack_pointer,
cycle_count);
}
2024-05-04 22:16:12 -04:00
void cpu_process_nmi(System *system) {
cpu_stack_push_context(system);
address handler_addr = mem_get_word(system, 0xfffa);
log_debug("NMI %#04x", handler_addr);
system->cpu.nmi_requested = false;
system->cpu.program_counter = handler_addr;
}
2024-01-06 14:27:09 -05:00
void oam_dma_upload(System *system) {
byte page_high_addr = *system->ppu.oam_dma_register;
address page_addr = ((address) page_high_addr) << 8;
byte n = 0xff;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
byte *ram_source = &system->ram[page_addr];
byte *oam_destination = system->ppu.oam;
2023-12-23 16:35:23 -05:00
2024-01-06 14:27:09 -05:00
memcpy(oam_destination, ram_source, n);
log_debug("OAM DMA %#04x", page_addr);
cpu_add_cycles(system, 513); // TODO
2023-12-23 16:35:23 -05:00
}
2024-01-06 14:27:09 -05:00
void cpu_cycle(System *system) {
2024-05-04 22:16:12 -04:00
if (system->cpu.nmi_requested) {
cpu_process_nmi(system);
}
2024-01-06 14:27:09 -05:00
if (system->cpu.oam_dma_triggered) {
oam_dma_upload(system);
system->cpu.oam_dma_triggered = false;
return;
2023-12-23 16:35:23 -05:00
}
2024-05-04 22:16:12 -04:00
CPU cpu = system->cpu;
2024-01-06 14:27:09 -05:00
byte op = cpu_get_next_byte(system);
2024-05-04 22:16:12 -04:00
print_registers(cpu, op, system->cycle_count);
2024-01-06 14:27:09 -05:00
process_op_code(system, op);
2023-11-26 12:11:49 -05:00
}
2024-01-06 14:27:09 -05:00
void cpu_add_cycles(System *system, unsigned int cycle_count) {
system->cycle_count += cycle_count;
2023-11-26 12:11:49 -05:00
}
2024-01-06 14:27:09 -05:00
// === Registers ===
bool system_get_flag(System *system, byte mask) {
return cpu_get_flag(&system->cpu, mask);
2023-11-26 12:11:49 -05:00
}
void system_set_flag(System *system, byte mask, bool set) {
2023-11-26 12:11:49 -05:00
if (set) {
2024-01-06 14:27:09 -05:00
system->cpu.status |= mask;
2023-11-26 12:11:49 -05:00
} else {
2024-01-06 14:27:09 -05:00
system->cpu.status &= ~mask;
2023-11-26 12:11:49 -05:00
}
}
2023-09-22 14:39:25 -04:00
2024-01-06 14:27:09 -05:00
byte cpu_get_next_byte(System *system) {
byte next_byte = mem_get_byte(system, system->cpu.program_counter);
system->cpu.program_counter++;
2023-11-26 12:11:49 -05:00
return next_byte;
}
2024-01-06 14:27:09 -05:00
word cpu_get_next_word(System *system) {
word next_word = mem_get_word(system, system->cpu.program_counter);
system->cpu.program_counter += 2;
2023-11-26 12:11:49 -05:00
return next_word;
}
2023-09-21 23:53:14 -04:00
2024-01-06 14:27:09 -05:00
void cpu_stack_push(System *system, byte value) {
assert(system->cpu.stack_pointer > 0);
2023-09-21 23:53:14 -04:00
2024-01-06 14:27:09 -05:00
address mem_addr = CPU_STACK_ADDR | system->cpu.stack_pointer;
mem_set_byte(system, mem_addr, value);
system->cpu.stack_pointer--;
2023-11-26 12:11:49 -05:00
}
2024-01-06 14:27:09 -05:00
byte cpu_stack_pop(System *system) {
assert(system->cpu.stack_pointer < 0xff);
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
system->cpu.stack_pointer++;
address mem_addr = CPU_STACK_ADDR | system->cpu.stack_pointer;
byte value = mem_get_byte(system, mem_addr);
2023-11-26 12:11:49 -05:00
return value;
}
2024-01-06 14:27:09 -05:00
void cpu_stack_push_context(System *system) {
cpu_stack_push(system, system->cpu.program_counter >> 8);
cpu_stack_push(system, system->cpu.program_counter & 0xff);
cpu_stack_push(system, system->cpu.status);
2023-11-26 12:11:49 -05:00
}
2024-01-06 14:27:09 -05:00
void cpu_stack_pop_context(System *system) {
byte value = cpu_stack_pop(system);
value &= 0xef; // The B mask cannot be set as it is a CPU signal
value |= 0x20; // This value is always set
system->cpu.status = value;
2023-11-26 12:11:49 -05:00
2024-01-06 14:27:09 -05:00
byte lo = cpu_stack_pop(system);
address pc = cpu_stack_pop(system) << 8;
2023-11-26 12:11:49 -05:00
pc += lo;
2024-01-06 14:27:09 -05:00
system->cpu.program_counter = pc;
2023-11-26 12:11:49 -05:00
}