Renamed gui to simulator as a better structure.

This commit is contained in:
2026-06-09 08:16:53 +02:00
parent 2df6a14610
commit f8ef6f030f
12 changed files with 153 additions and 34 deletions
+37
View File
@@ -0,0 +1,37 @@
package simulator
import "core:log"
import rl "vendor:raylib"
PADDING :: 10
gui_control_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) {
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
// Small text area
// Control bar buttons
btn_w : f32 = 80
btn_h : f32 = rect.height - (PADDING * 2)
gap : f32 = 6
cursor : f32 = rect.x + PADDING
if btn(&cursor, rect, btn_h, btn_w, gap, "RUN") {
log.info("RUN clicked")
sim.paused = false
sim.running = true
}
if btn(&cursor, rect, btn_h, btn_w, gap, "PAUSE") {
log.info("PAUSE clicked")
sim.paused = true
sim.running = false
}
if btn(&cursor, rect, btn_h, btn_w, gap, "STEP") { log.info("STEP clicked") }
}
btn :: proc(cursor: ^f32, rect: rl.Rectangle, h, w, gap: f32, label: cstring) -> bool {
r := rl.Rectangle{cursor^, rect.y + PADDING, w, h}
cursor^ += w + gap
return rl.GuiButton(r, label)
}
+135
View File
@@ -0,0 +1,135 @@
package simulator
import emu "../machine"
import rl "vendor:raylib"
// Initial window size
WINDOW_WIDTH :: 1920
WINDOW_HEIGHT :: 1080
// @TODO: If this grows lets move it into its own file
SIDEBAR_PERCENT :: 0.20
DISPLAY_PERCENT :: 0.30
CONTROLBAR_PERCENT :: 0.05
Layout :: struct {
control_bar : rl.Rectangle,
left_panel : rl.Rectangle,
display : rl.Rectangle,
right_panel : rl.Rectangle,
status_bar : rl.Rectangle,
}
// Initialize main the gui 'window'
run_gui :: proc(sim: ^Simulator) {
rl.SetConfigFlags({.WINDOW_RESIZABLE})
rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "raylib")
rl.InitAudioDevice()
rl.SetTargetFPS(60)
beep := rl.LoadSound("./beep.wav")
// Load fonts
font := rl.LoadFontEx("./assets/fonts/Inter_18pt-Regular.ttf", 18, nil, 0)
rl.SetTextureFilter(font.texture, .BILINEAR)
sim.font = font
// Initialize style system first
rl.GuiLoadStyleDefault()
// Then load dark theme
rl.GuiLoadStyle("./assets/raygui_styles/style_dark.rgs")
// Then override font AFTER (style load resets it)
rl.GuiSetFont(font)
rl.GuiSetStyle(.DEFAULT, cast(i32)rl.GuiDefaultProperty.TEXT_SIZE, 18)
// Draw each of the components in its own window within the main window
for !rl.WindowShouldClose() {
// Recalculate layout each frame based on current window size
// Pass these down to gui functions so they can setup their sizes?
screen_width := f32(rl.GetScreenWidth())
screen_height := f32(rl.GetScreenHeight())
sidebar_width := screen_width * 0.20
// set all the layout structs dynamically with the screen size
layout := calc_layout(screen_width, screen_height)
rl.BeginDrawing()
rl.ClearBackground(rl.BLACK)
// Cycle the machine to update memory etc
// if (sim.is_running) else don't run machine, here we can start,pause etc
if (!sim.paused) {
emu.run_machine(sim.machine, 12)
// 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)
}
}
gui_control_bar(layout.control_bar, sim)
// gui_left_panel(layout.left_panel, s.machine)
// gui_right_panel(layout.right_panel, s.machine)
// Screen is just drawing the display buffer just needs that as arg
// Not the whole sim struct
gui_screen(layout.display, sim.machine)
gui_status_bar(layout.status_bar, sim)
rl.EndDrawing()
}
rl.UnloadFont(sim.font)
rl.UnloadFont(font)
rl.UnloadSound(beep)
rl.CloseAudioDevice()
rl.CloseWindow()
}
// @TODO: If this grows lets move it into its own file
calc_layout :: proc(screen_width: f32, screen_height: f32) -> Layout {
control_bar_height := screen_height * CONTROLBAR_PERCENT
sidebar_width := screen_width * SIDEBAR_PERCENT
sidebar_height := screen_height - control_bar_height
display_height := screen_height * DISPLAY_PERCENT - control_bar_height
return Layout {
control_bar = rl.Rectangle {
x = 0,
y = 0,
width = screen_width,
height = control_bar_height
},
left_panel = rl.Rectangle {
x = 0,
y = control_bar_height,
width = sidebar_width,
height = sidebar_height
},
display = rl.Rectangle {
x = sidebar_width,
y = control_bar_height,
width = screen_width - (sidebar_width * 2),
height = display_height
},
right_panel = rl.Rectangle {
x = screen_width - sidebar_width,
y = control_bar_height,
width = sidebar_width,
height = sidebar_height
},
status_bar = rl.Rectangle {
x = 0,
y = screen_height - control_bar_height,
width = screen_width,
height = control_bar_height
},
}
}
+8
View File
@@ -0,0 +1,8 @@
package simulator
import m "../machine"
import rl "vendor:raylib"
gui_left_panel :: proc(rect: rl.Rectangle, s: ^m.System) {
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
}
+8
View File
@@ -0,0 +1,8 @@
package simulator
import m "../machine"
import rl "vendor:raylib"
gui_right_panel :: proc(rect: rl.Rectangle, s: ^m.System) {
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
}
+49
View File
@@ -0,0 +1,49 @@
package simulator
import m "../machine"
import rl "vendor:raylib"
gui_screen :: proc(rect: rl.Rectangle, s: ^m.System) {
// Make sure screen is staying in its aspect ratio
chip8_aspect := f32(64.0 / 32.0)
available_aspect := rect.width / rect.height
screen_rect := rect
if available_aspect > chip8_aspect {
// Area is too wide
screen_rect.width = rect.height * chip8_aspect
screen_rect.x = rect.x + (rect.width - screen_rect.width) / 2
} else {
// Area is too tall
screen_rect.height = rect.width / chip8_aspect
screen_rect.y = rect.y + (rect.height - screen_rect.height) / 2
}
pixel_size := min(int(screen_rect.width / 64), int(screen_rect.height / 32))
pixel_size = max(pixel_size, 1)
actual_width := pixel_size * 64
actual_height := pixel_size * 32
display_x := i32(screen_rect.x) + i32(int(screen_rect.width) - actual_width) / 2
display_y := i32(screen_rect.y) + i32(int(screen_rect.height) - actual_height) / 2
// Debug borders
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
rl.DrawRectangleLinesEx(screen_rect, 2, rl.WHITE)
render_display(&s.display, display_x, display_y, i32(pixel_size))
}
@(private = "file")
render_display :: proc(display_buffer: ^[32][64]u8, offset_x, offset_y, scale: i32) {
rl.DrawRectangle(offset_x, offset_y, 64 * scale, 32 * scale, rl.BLACK)
for y in 0..<len(display_buffer) {
for x in 0..<len(display_buffer[0]) {
if display_buffer[y][x] == 0x01 {
rl.DrawRectangle(i32(x) * scale + offset_x, i32(y) * scale + offset_y, scale, scale, rl.WHITE)
}
}
}
}
+25
View File
@@ -0,0 +1,25 @@
package simulator
import emu "../machine"
import rl "vendor:raylib"
Simulator :: struct {
font: rl.Font,
machine: ^emu.System,
running: bool,
paused: bool,
cycles_per_second: int
}
// Requires an initilized emulatore System Struct
run_simulator :: proc(s: ^emu.System) {
sim := Simulator {
machine = s,
running = true,
paused = false,
cycles_per_second = 12
}
run_gui(&sim)
}
+46
View File
@@ -0,0 +1,46 @@
package simulator
import "core:fmt"
import rl "vendor:raylib"
gui_status_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) {
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
cursor: f32 = rect.x + PADDING
cy := rect.y + rect.height * 0.5
if sim.running && !sim.paused {
status_icon(&cursor, cy, rl.GREEN, .CIRCLE, "Running", sim.font)
} else {
status_icon(&cursor, cy, rl.RED, .SQUARE, "Paused", sim.font)
}
status_divider(&cursor, cy)
status_text(&cursor, cy, fmt.ctprintf("FPS: %d", rl.GetFPS()), sim.font)
}
StatusIconShape :: enum { CIRCLE, SQUARE }
status_icon :: proc(cursor: ^f32, cy: f32, color: rl.Color, shape: StatusIconShape, label: cstring, font: rl.Font) {
size: f32 = 10
ix := cursor^ + size * 0.5
switch shape {
case .CIRCLE: rl.DrawCircleV({ix, cy}, size * 0.5, color)
case .SQUARE: rl.DrawRectangleV({ix - size*0.5, cy - size*0.5}, {size, size}, color)
}
cursor^ += size + 6
rl.DrawTextEx(font, label, {cursor^, cy - f32(font.baseSize) * 0.5}, f32(font.baseSize), 1, rl.RAYWHITE)
cursor^ += rl.MeasureTextEx(font, label, f32(font.baseSize), 1).x + PADDING
}
status_divider :: proc(cursor: ^f32, cy: f32) {
rl.DrawLineV({cursor^, cy - 8}, {cursor^, cy + 8}, rl.DARKGRAY)
cursor^ += PADDING
}
status_text :: proc(cursor: ^f32, cy: f32, text: cstring, font: rl.Font) {
rl.DrawTextEx(font, text, {cursor^, cy - f32(font.baseSize) * 0.5}, f32(font.baseSize), 1, rl.RAYWHITE)
cursor^ += rl.MeasureTextEx(font, text, f32(font.baseSize), 1).x + PADDING
}