#include "Chip8.h" #include #include #include #include #include "bitops.h" Chip8::Chip8(): machine_state{std::make_shared()}, graphics{machine_state}, interpreter{machine_state, 0}, target_cycle_time{1.0 / 700.0}, last_update_time{0}, accumulator{0}, run{false}, step{false} {} bool Chip8::init() { if (!graphics.init()) { return false; } last_update_time = SDL_GetTicks(); accumulator = 0; const auto rom = read_rom("roms/1-chip8-logo.ch8"); interpreter.load_rom(rom); return true; } void Chip8::set_keyboard_state(std::span keyboard_state) { this->keyboard_state = keyboard_state; } std::vector Chip8::read_rom(const std::string& path) { std::ifstream rom_file(path, std::ios::binary); rom_file.seekg(0, std::ios::end); const std::streampos file_size = rom_file.tellg(); rom_file.seekg(0, std::ios::beg); std::cout << "ROM size: " << file_size << std::endl; std::vector rom(file_size); rom.insert( rom.begin(), std::istreambuf_iterator(rom_file), std::istreambuf_iterator() ); return rom; } void Chip8::load_keyboard() { machine_state->keyboard = keyboard_state[SDL_SCANCODE_X] ? bit_set(machine_state->keyboard, 0x0) : bit_clear(machine_state->keyboard, 0x0); machine_state->keyboard = keyboard_state[SDL_SCANCODE_1] ? bit_set(machine_state->keyboard, 0x1) : bit_clear(machine_state->keyboard, 0x1); machine_state->keyboard = keyboard_state[SDL_SCANCODE_2] ? bit_set(machine_state->keyboard, 0x2) : bit_clear(machine_state->keyboard, 0x2); machine_state->keyboard = keyboard_state[SDL_SCANCODE_3] ? bit_set(machine_state->keyboard, 0x3) : bit_clear(machine_state->keyboard, 0x3); machine_state->keyboard = keyboard_state[SDL_SCANCODE_Q] ? bit_set(machine_state->keyboard, 0x4) : bit_clear(machine_state->keyboard, 0x4); machine_state->keyboard = keyboard_state[SDL_SCANCODE_W] ? bit_set(machine_state->keyboard, 0x5) : bit_clear(machine_state->keyboard, 0x5); machine_state->keyboard = keyboard_state[SDL_SCANCODE_E] ? bit_set(machine_state->keyboard, 0x6) : bit_clear(machine_state->keyboard, 0x6); machine_state->keyboard = keyboard_state[SDL_SCANCODE_A] ? bit_set(machine_state->keyboard, 0x7) : bit_clear(machine_state->keyboard, 0x7); machine_state->keyboard = keyboard_state[SDL_SCANCODE_S] ? bit_set(machine_state->keyboard, 0x8) : bit_clear(machine_state->keyboard, 0x8); machine_state->keyboard = keyboard_state[SDL_SCANCODE_D] ? bit_set(machine_state->keyboard, 0x9) : bit_clear(machine_state->keyboard, 0x9); machine_state->keyboard = keyboard_state[SDL_SCANCODE_Z] ? bit_set(machine_state->keyboard, 0xA) : bit_clear(machine_state->keyboard, 0xA); machine_state->keyboard = keyboard_state[SDL_SCANCODE_C] ? bit_set(machine_state->keyboard, 0xB) : bit_clear(machine_state->keyboard, 0xB); machine_state->keyboard = keyboard_state[SDL_SCANCODE_4] ? bit_set(machine_state->keyboard, 0xC) : bit_clear(machine_state->keyboard, 0xC); machine_state->keyboard = keyboard_state[SDL_SCANCODE_R] ? bit_set(machine_state->keyboard, 0xD) : bit_clear(machine_state->keyboard, 0xD); machine_state->keyboard = keyboard_state[SDL_SCANCODE_F] ? bit_set(machine_state->keyboard, 0xE) : bit_clear(machine_state->keyboard, 0xE); machine_state->keyboard = keyboard_state[SDL_SCANCODE_V] ? bit_set(machine_state->keyboard, 0xF) : bit_clear(machine_state->keyboard, 0xF); } void Chip8::update() { load_keyboard(); std::stringstream buffer; buffer << std::format( "PC: {:03X} | SP: {:02X} | I {:02X} | DT {:02X} | ST {:02X} | INST: {:02X}{:02X} | V0-VF: ", machine_state->pc, machine_state->sp, machine_state->i, machine_state->dt, machine_state->st, machine_state->memory[machine_state->pc], machine_state->memory[machine_state->pc + 1] ); for (int i = 0; i < 16; ++i) { buffer << std::format("{:02X}", machine_state->v[i]); if (i < 15) buffer << ","; } buffer << " | "; if (run) { execute_instructions(); } else if (step) { execute_instruction(); step = false; last_update_time = SDL_GetTicks(); } else { last_update_time = SDL_GetTicks(); } graphics.draw(); } void Chip8::execute_instructions() { const auto current_time = SDL_GetTicks(); const auto delta_time = static_cast(current_time - last_update_time) / 1000.0; last_update_time = current_time; accumulator += delta_time; while (accumulator >= target_cycle_time) { execute_instruction(); accumulator -= target_cycle_time; } } void Chip8::execute_instruction() { interpreter.run(); } void Chip8::on_keydown(SDL_Scancode scancode) { if (scancode == SDL_SCANCODE_F1) { run = !run; } else if (scancode == SDL_SCANCODE_F2) { step = true; } }