From 4532da48c31c7e7087be4dcd22a3dd7ae8819281 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Wed, 20 May 2026 10:49:30 -0400 Subject: [PATCH] Start a control panel for buttons and disassembler output. --- src/chip8.cpp | 6 +++--- src/chip8.hpp | 17 ++++++----------- src/code_panel.cpp | 1 - src/code_panel.hpp | 1 - src/constants.hpp | 16 ++++++++++++++++ src/control_panel.cpp | 26 ++++++++++++++++++++++++++ src/control_panel.hpp | 15 +++++++++++++++ src/display.cpp | 9 +++++++-- src/display.hpp | 7 +++++-- src/main.cpp | 4 ++-- src/meson.build | 2 +- src/status_panel.cpp | 19 ++++++++++++++----- 12 files changed, 95 insertions(+), 28 deletions(-) delete mode 100644 src/code_panel.cpp delete mode 100644 src/code_panel.hpp create mode 100644 src/constants.hpp create mode 100644 src/control_panel.cpp create mode 100644 src/control_panel.hpp diff --git a/src/chip8.cpp b/src/chip8.cpp index 8671051..3490baf 100644 --- a/src/chip8.cpp +++ b/src/chip8.cpp @@ -284,8 +284,8 @@ void Chip8::OP_Dxyn() { uint8_t height = opcode & 0x00Fu; // wrap if going beyond the screen boundaries - uint8_t xPos = registers[Vx] % VIDEO_WIDTH; - uint8_t yPos = registers[Vy] % VIDEO_HEIGHT; + uint8_t xPos = registers[Vx] % CHIP8_WIDTH; + uint8_t yPos = registers[Vy] % CHIP8_HEIGHT; registers[0xF] = 0; @@ -295,7 +295,7 @@ void Chip8::OP_Dxyn() { for(size_t col = 0; col < 8; ++col) { uint8_t spritePixel = spriteByte & (0x80u >> col); - size_t pixel_at = (yPos + row) * VIDEO_WIDTH + (xPos + col); + size_t pixel_at = (yPos + row) * CHIP8_WIDTH + (xPos + col); uint32_t* screenPixel = &video[pixel_at]; diff --git a/src/chip8.hpp b/src/chip8.hpp index def9cf2..32cbbb1 100644 --- a/src/chip8.hpp +++ b/src/chip8.hpp @@ -6,25 +6,20 @@ #include #include #include - -const unsigned int START_ADDRESS = 0x200; -const unsigned int FONTSET_SIZE = 80; -const unsigned int FONTSET_START_ADDRESS = 0x50; -const unsigned int VIDEO_WIDTH = 64; -const unsigned int VIDEO_HEIGHT = 32; +#include "constants.hpp" class Chip8 { public: - uint8_t registers[16]{}; - uint8_t memory[4096]{}; + uint8_t registers[CHIP8_REGISTERS]{}; + uint8_t memory[CHIP8_RAM]{}; uint16_t index{}; uint16_t pc{}; - uint16_t stack[16]{}; + uint16_t stack[CHIP8_STACK]{}; uint8_t sp{}; uint8_t delayTimer{}; uint8_t soundTimer{}; - uint8_t keypad[16]{}; - uint32_t video[VIDEO_WIDTH * VIDEO_HEIGHT]{}; + uint8_t keypad[CHIP8_KEYS]{}; + uint32_t video[CHIP8_WIDTH * CHIP8_HEIGHT]{}; uint16_t opcode; uint8_t fontset[FONTSET_SIZE] = { diff --git a/src/code_panel.cpp b/src/code_panel.cpp deleted file mode 100644 index 7b25ad9..0000000 --- a/src/code_panel.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "code_panel.hpp" diff --git a/src/code_panel.hpp b/src/code_panel.hpp deleted file mode 100644 index 6f70f09..0000000 --- a/src/code_panel.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/src/constants.hpp b/src/constants.hpp new file mode 100644 index 0000000..1b5dca7 --- /dev/null +++ b/src/constants.hpp @@ -0,0 +1,16 @@ +#pragma once + +constexpr const int DISPLAY_WIDTH = 1000; +constexpr const int WINDOW_WIDTH = 1280; +constexpr const int WINDOW_HEIGHT = 720; + +constexpr const unsigned int START_ADDRESS = 0x200; +constexpr const unsigned int FONTSET_SIZE = 80; +constexpr const unsigned int FONTSET_START_ADDRESS = 0x50; + +constexpr const unsigned int CHIP8_WIDTH = 64; +constexpr const unsigned int CHIP8_HEIGHT = 32; +constexpr const size_t CHIP8_REGISTERS = 16; +constexpr const size_t CHIP8_RAM = 4096; +constexpr const size_t CHIP8_STACK = 16; +constexpr const size_t CHIP8_KEYS = 16; diff --git a/src/control_panel.cpp b/src/control_panel.cpp new file mode 100644 index 0000000..a243553 --- /dev/null +++ b/src/control_panel.cpp @@ -0,0 +1,26 @@ +#include "control_panel.hpp" +#include +#include "constants.hpp" + +ControlPanel::ControlPanel() { +} + +void ControlPanel::init(sf::Vector2f size) { + $gui.position(0, size.y, size.x, WINDOW_HEIGHT - size.y); + $gui.layout("[buttons|code]"); + + for(auto& [name, cell] : $gui.cells()) { + auto id = $gui.entity(name); + $gui.set(id, {}); + $gui.set(id, {guecs::to_wstring(name)}); + } + + $gui.init(); +} + +void ControlPanel::render(sf::RenderTarget& window) { + $gui.render(window); +} + +void ControlPanel::update(Chip8& vm) { +} diff --git a/src/control_panel.hpp b/src/control_panel.hpp new file mode 100644 index 0000000..86931ef --- /dev/null +++ b/src/control_panel.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include "chip8.hpp" + +struct ControlPanel { + guecs::UI $gui; + + ControlPanel(); + + void init(sf::Vector2f size); + void render(sf::RenderTarget& window); + void update(Chip8& vm); +}; diff --git a/src/display.cpp b/src/display.cpp index d51530d..359a532 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -3,13 +3,14 @@ #include #include -Display::Display(sf::RenderWindow& window, sf::Vector2f pos, sf::Vector2f size) : +Display::Display(sf::RenderWindow& window, sf::Vector2f pos, float width) : $window(window) { float border_width = 2.0f; $texture.setSmooth(false); - float ratio = (size.x - border_width * 2) / 64.0f; + float ratio = (width - border_width * 2) / 64.0f; + // rectangle position doesn't include the border because everyone hates humans sf::Vector2f border_pos{pos.x + border_width, pos.y + border_width}; @@ -24,6 +25,9 @@ Display::Display(sf::RenderWindow& window, sf::Vector2f pos, sf::Vector2f size) $border.setOutlineThickness(border_width); $border.setFillColor({0,0,0,255}); + size = $border.getLocalBounds().size; + $control.init(size); + $status.init(); } @@ -51,6 +55,7 @@ void Display::render() { $window.draw($border); $window.draw($texture_sprite); $status.render($window); + $control.render($window); $window.display(); } diff --git a/src/display.hpp b/src/display.hpp index a4339b4..b260fea 100644 --- a/src/display.hpp +++ b/src/display.hpp @@ -5,15 +5,18 @@ #include #include "chip8.hpp" #include "status_panel.hpp" +#include "control_panel.hpp" struct Display { + sf::Vector2f size{0,0}; sf::RenderWindow& $window; - sf::Texture $texture{sf::Vector2u{VIDEO_WIDTH, VIDEO_HEIGHT}}; + sf::Texture $texture{sf::Vector2u{CHIP8_WIDTH, CHIP8_HEIGHT}}; sf::Sprite $texture_sprite{$texture}; sf::RectangleShape $border; StatusPanel $status; + ControlPanel $control; - Display(sf::RenderWindow& window, sf::Vector2f pos, sf::Vector2f size); + Display(sf::RenderWindow& window, sf::Vector2f pos, float width); void handle_inputs(Chip8& vm); void update(Chip8& vm); diff --git a/src/main.cpp b/src/main.cpp index 8d7bb06..71f972a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,7 +21,7 @@ int main(int argc, char* argv[]) { Chip8 chip8; chip8.LoadROM(romFilename); - int videoPitch = sizeof(chip8.video[0]) * VIDEO_WIDTH; + int videoPitch = sizeof(chip8.video[0]) * CHIP8_WIDTH; sfml::Backend backend; guecs::init(&backend); @@ -30,7 +30,7 @@ int main(int argc, char* argv[]) { window.setFramerateLimit(framerate); window.setVerticalSyncEnabled(false); - Display display{window, {0, 0}, {1000, 1000}}; + Display display{window, {0, 0}, 1000}; Stats cycle_stats; Stats render_stats; Stats update_stats; diff --git a/src/meson.build b/src/meson.build index f210a25..ec28781 100644 --- a/src/meson.build +++ b/src/meson.build @@ -5,5 +5,5 @@ sources = files( 'stats.cpp', 'display.cpp', 'status_panel.cpp', - 'code_panel.cpp', + 'control_panel.cpp', ) diff --git a/src/status_panel.cpp b/src/status_panel.cpp index 1be1028..1cc78a0 100644 --- a/src/status_panel.cpp +++ b/src/status_panel.cpp @@ -1,8 +1,9 @@ #include "status_panel.hpp" #include +#include "constants.hpp" StatusPanel::StatusPanel() { - $gui.position(1000, 0, 1280 - 1000, 720); + $gui.position(DISPLAY_WIDTH, 0, WINDOW_WIDTH - DISPLAY_WIDTH, WINDOW_HEIGHT); $gui.layout( "[N|Reg|Stk|Key]" "[x0|r0|s0|k0]" @@ -20,7 +21,9 @@ StatusPanel::StatusPanel() { "[xC|r12|s12|k12]" "[xD|r13|s13|k13]" "[xE|r14|s14|k14]" - "[xF|r15|s15|k15]"); + "[xF|r15|s15|k15]" + "[PC|I|SP|DT|ST]" + "[pc|i|sp|dt|st]"); } void StatusPanel::init() { @@ -38,15 +41,21 @@ void StatusPanel::render(sf::RenderTarget& window) { } void StatusPanel::update(Chip8& vm) { - for(size_t i = 0; i < 16; i++) { + for(size_t i = 0; i < CHIP8_REGISTERS; i++) { $gui.show_text(fmt::format("r{}", i), fmt::format(L"{}", vm.registers[i])); } - for(size_t i = 0; i < 16; i++) { + for(size_t i = 0; i < CHIP8_STACK; i++) { $gui.show_text(fmt::format("s{}", i), fmt::format(L"{}", vm.stack[i])); } - for(size_t i = 0; i < 16; i++) { + for(size_t i = 0; i < CHIP8_KEYS; i++) { $gui.show_text(fmt::format("k{}", i), fmt::format(L"{}", vm.keypad[i])); } + + $gui.show_text("pc", fmt::format(L"{}", vm.pc)); + $gui.show_text("i", fmt::format(L"{}", vm.index)); + $gui.show_text("sp", fmt::format(L"{}", vm.sp)); + $gui.show_text("dt", fmt::format(L"{}", vm.delayTimer)); + $gui.show_text("st", fmt::format(L"{}", vm.soundTimer)); }