From c3367cdf3e35f92fbc2d5f7d9f28a25367cb8a48 Mon Sep 17 00:00:00 2001 From: Jason Hilder Date: Sat, 13 Jun 2026 09:29:53 +0200 Subject: [PATCH] Added left panel rom loader. Left panel has tinyfieldialogs to open a file picker, so you can swap out roms, required a reset machine function aswell. --- src/machine/cpu.odin | 2 +- src/machine/machine.odin | 15 ++++++++++++ src/main.odin | 7 ------ src/simulator/left_panel.odin | 45 ++++++++++++++++++++++++++--------- 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/machine/cpu.odin b/src/machine/cpu.odin index e371a2d..ea1c5c8 100644 --- a/src/machine/cpu.odin +++ b/src/machine/cpu.odin @@ -333,4 +333,4 @@ op_mem_get :: proc(s: ^System, vx_idx: u16) { for loop_idx in 0..=vx_idx { s.v[loop_idx] = s.memory[s.i + loop_idx] } -} \ No newline at end of file +} diff --git a/src/machine/machine.odin b/src/machine/machine.odin index af72f61..b342400 100644 --- a/src/machine/machine.odin +++ b/src/machine/machine.odin @@ -68,3 +68,18 @@ run_machine :: proc(s: ^System, cycles: int) { cycle(s) } } + +new_machine :: proc() -> System { + s: System + s.pc = 0x200 + s.current_key = -1 + // load fonts into the memory + for v, i in FONT_SET { + s.memory[i] = v + } + return s +} + +reset_machine :: proc(s: ^System) { + s^ = new_machine() +} diff --git a/src/main.odin b/src/main.odin index 7e4bdc7..bcca549 100644 --- a/src/main.odin +++ b/src/main.odin @@ -23,13 +23,6 @@ main :: proc() { // Init the emu 8 "cpu" system := emu.init() - // @TODO: move this into a gui component - // load rom, hardcoded for now, will eventually be cli or gui - err := emu.load_rom(&system, "./test_roms/7-beep.ch8") - if err != nil { - panic("failed to load rom!") - } - // Initilize sim, gui etc sim.run_simulator(&system) diff --git a/src/simulator/left_panel.odin b/src/simulator/left_panel.odin index 26abbb2..c6ba6e5 100644 --- a/src/simulator/left_panel.odin +++ b/src/simulator/left_panel.odin @@ -4,6 +4,9 @@ import "core:log" import "core:strings" import rl "vendor:raylib" +import emu "../machine" +import tfd "../../external/tinyfiledialogs" + gui_left_panel :: proc(rect: rl.Rectangle, sim: ^Simulator) { // ── Top panel and components ── top_panel := rl.Rectangle { @@ -16,13 +19,12 @@ gui_left_panel :: proc(rect: rl.Rectangle, sim: ^Simulator) { // Dropzone/file loader file_loader_rect := rl.Rectangle { - top_panel.x + PANEL_PADDING, - top_panel.y + PANEL_HEADER, - top_panel.width - PANEL_PADDING * 2, + top_panel.x, + top_panel.y, + top_panel.width, (top_panel.height / 3) - PANEL_HEADER - PANEL_PADDING * 2, } - rl.GuiPanel(file_loader_rect, "Rom / File") - gui_file_loader(file_loader_rect) + gui_file_loader(file_loader_rect, sim) // ── Bottom panel and components ── bottom_panel := rl.Rectangle { @@ -35,7 +37,9 @@ gui_left_panel :: proc(rect: rl.Rectangle, sim: ^Simulator) { gui_key_pad(bottom_panel, sim.machine.keypad, sim.font) } -gui_file_loader :: proc(rect: rl.Rectangle) { +gui_file_loader :: proc(rect: rl.Rectangle, sim: ^Simulator) { + rl.GuiPanel(rect, "Rom / File") + // drop-zone occupies the panel's content area, minus space for the button drop_zone := rl.Rectangle { rect.x + PANEL_PADDING, @@ -47,10 +51,10 @@ gui_file_loader :: proc(rect: rl.Rectangle) { // centered drop-zone text text: cstring = "Drop a CHIP-8 ROM here" - text_width := rl.MeasureText(text, DROP_FONT_SIZE) + text_width := rl.MeasureText(text, BIG_FONT_SIZE) text_x := drop_zone.x + (drop_zone.width - f32(text_width)) / 2 - text_y := drop_zone.y + (drop_zone.height - f32(DROP_FONT_SIZE)) / 2 - rl.DrawText(text, i32(text_x), i32(text_y), DROP_FONT_SIZE, rl.GRAY) + text_y := drop_zone.y + (drop_zone.height - f32(BIG_FONT_SIZE)) / 2 + rl.DrawTextEx(sim.font, text, {text_x, text_y}, BIG_FONT_SIZE, 1, rl.WHITE) // open rom button below drop-zone btn_rect := rl.Rectangle { @@ -61,7 +65,23 @@ gui_file_loader :: proc(rect: rl.Rectangle) { } if rl.GuiButton(btn_rect, "Open ROM") { - // @TODO: get tinyfiledialog working here + ret := tfd.openFileDialog("Open File Dialog", nil, 0, nil, nil, 0,) + rom_path := string(ret) + if rom_path == "" do return + + // reset machine state + emu.reset_machine(sim.machine) + + // load new rom + err := emu.load_rom(sim.machine, rom_path) + if err != nil { + // @TODO: update status bar here + panic("failed to load rom!") + } + + sim.rom_loaded = true + sim.running = true + sim.paused = false } // Handle file drop @@ -96,6 +116,7 @@ gui_key_pad :: proc(rect: rl.Rectangle, display: [16]bool, font: rl.Font) { label: string, index: int, } + keys := [16]Key { {"1", 1}, {"2", 2}, {"3", 3}, {"C", 12}, {"4", 4}, {"5", 5}, {"6", 6}, {"D", 13}, @@ -122,7 +143,9 @@ gui_key_pad :: proc(rect: rl.Rectangle, display: [16]bool, font: rl.Font) { if display[val.index] { rl.DrawRectangleRec(irect, rl.BLACK) } rl.DrawRectangleLinesEx(irect, 1, rl.GRAY) - rl.DrawTextEx( font, str, + rl.DrawTextEx( + font, + str, rl.Vector2{irect.x + btn_width / 2, irect.y + btn_height / 2}, KEYPAD_FONT_SIZE, 1,