diff --git a/src/simulator/gui.odin b/src/simulator/gui.odin index b433ddc..677fe42 100644 --- a/src/simulator/gui.odin +++ b/src/simulator/gui.odin @@ -67,23 +67,19 @@ run_gui :: proc(sim: ^Simulator) { layout := calc_layout(screen_width, screen_height) rl.BeginDrawing() - rl.ClearBackground(rl.BLACK) + rl.ClearBackground(rl.Color{0x18, 0x18, 0x18, 0xFF}) if (!sim.paused) { // Cycle the machine to update memory etc emu.run_machine(sim.machine, 12) + tick_timers(sim, beep) + } - // Handle delay timer - if sim.machine.delay_timer > 0 do sim.machine.delay_timer -= 1 - - // Current sound file is around 1s so stop - // immediately when timer is 0 - if sim.machine.sound_timer > 0 { - sim.machine.sound_timer -= 1 - if !rl.IsSoundPlaying(beep) do rl.PlaySound(beep) - } else { - rl.StopSound(beep) - } + if(sim.paused && sim.step) { + // Cycle the machine to update memory etc + emu.run_machine(sim.machine, 1) + tick_timers(sim, beep) + sim.step = false } // Top @@ -115,9 +111,16 @@ run_gui :: proc(sim: ^Simulator) { rl.UnloadSound(beep) rl.CloseAudioDevice() rl.CloseWindow() +} - // Free any allocated memory for the simulator - delete(sim.disasm) +tick_timers :: proc(sim: ^Simulator, beep: rl.Sound) { + if sim.machine.delay_timer > 0 do sim.machine.delay_timer -= 1 + if sim.machine.sound_timer > 0 { + sim.machine.sound_timer -= 1 + if !rl.IsSoundPlaying(beep) do rl.PlaySound(beep) + } else { + rl.StopSound(beep) + } } calc_layout :: proc(screen_width: f32, screen_height: f32) -> Layout { diff --git a/src/simulator/gui_control_bar.odin b/src/simulator/gui_control_bar.odin index b037b2c..3ab68f0 100644 --- a/src/simulator/gui_control_bar.odin +++ b/src/simulator/gui_control_bar.odin @@ -1,6 +1,8 @@ package simulator import "core:log" + +import emu "../machine" import rl "vendor:raylib" gui_control_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) { @@ -15,7 +17,6 @@ gui_control_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) { if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PADDING_X, "RUN") { if sim.rom_loaded { sim.paused = false - sim.running = true } else { log.info("no rom selected, can't run") } @@ -23,12 +24,26 @@ gui_control_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) { if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PADDING_X, "PAUSE") { sim.paused = true - sim.running = false + } + + if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PADDING_X, "STEP") { + if !sim.step do sim.step = true } if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PADDING_X, "RESET") { - + sim.paused = true + sim.disasm_count = 0 + emu.reset_machine(sim.machine) } + + // @TODO: Get this working + slider_rect := rl.Rectangle{ + x = rect.width - 100 - 50, + y = rect.y + 15, + width = 100, + height = 15 + } + rl.GuiSlider(slider_rect, "Speed ", nil, &sim.speed_value, 0, 100) } btn :: proc(cursor: ^f32, rect: rl.Rectangle, h, w, gap: f32, label: cstring) -> bool { diff --git a/src/simulator/gui_file_loader.odin b/src/simulator/gui_file_loader.odin index fc20d07..a71eb55 100644 --- a/src/simulator/gui_file_loader.odin +++ b/src/simulator/gui_file_loader.odin @@ -7,12 +7,6 @@ import rl "vendor:raylib" import emu "../machine" import tfd "../../external/tinyfiledialogs" -Instruction :: struct { - address: u16, - raw: u16, - str: string -} - gui_file_loader :: proc(rect: rl.Rectangle, sim: ^Simulator) { rl.DrawRectangleLinesEx(rect, 1, rl.GRAY) diff --git a/src/simulator/gui_status_bar.odin b/src/simulator/gui_status_bar.odin index 14a1bf3..798ff3b 100644 --- a/src/simulator/gui_status_bar.odin +++ b/src/simulator/gui_status_bar.odin @@ -12,7 +12,7 @@ gui_status_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) { cursor: f32 = rect.x + PADDING_X cy := rect.y + rect.height * 0.5 - if sim.running && !sim.paused { + if !sim.paused { status_icon(&cursor, cy, rl.GREEN, .CIRCLE, "Running", sim.font) } else { status_icon(&cursor, cy, rl.RED, .SQUARE, "Paused", sim.font) diff --git a/src/simulator/simulator.odin b/src/simulator/simulator.odin index 86f6ee9..c9d7c3d 100644 --- a/src/simulator/simulator.odin +++ b/src/simulator/simulator.odin @@ -3,18 +3,32 @@ package simulator import emu "../machine" import rl "vendor:raylib" +// CHIP-8 ROM can be at most 3584 bytes (4096 - 0x200 reserved) +// Each instruction is 2 bytes, 3584 / 2 = 1792 instructions. +MAX_INSTRUCTIONS :: 1792 + +Instruction :: struct { + address: u16, + raw: u16, + str: [32]u8 +} + Simulator :: struct { // Emulator machine: ^emu.System, rom_loaded: bool, - running: bool, paused: bool, + step: bool, cycles_per_second: int, + speed_value: f32, // GUI font: rl.Font, active_tab: i32, mem_scroll: rl.Vector2, - disasm: []Instruction, + // disassembly props + disasm: [MAX_INSTRUCTIONS]Instruction, + disasm_follow: bool, + disasm_count: int, disasm_scroll: rl.Vector2, } @@ -23,9 +37,10 @@ run_simulator :: proc(s: ^emu.System) { sim := Simulator { machine = s, rom_loaded = false, - running = false, paused = true, - cycles_per_second = 12 + step = false, + cycles_per_second = 12, + disasm_follow = true } run_gui(&sim)