0b5006f985
Added a tick_timer proc so the code handles the step neatly. Added some new struct fields to accomodate this and moved danglings struct defs into the simulator definition.
199 lines
5.0 KiB
Odin
199 lines
5.0 KiB
Odin
package simulator
|
|
|
|
import emu "../machine"
|
|
import rl "vendor:raylib"
|
|
|
|
// Window
|
|
WINDOW_WIDTH :: 1920
|
|
WINDOW_HEIGHT :: 1080
|
|
|
|
// Layout proportions
|
|
// Sidebar takes 20% of screen width on each side; display takes the rest.
|
|
// The center column splits vertically: 40% display, 60% debug panel.
|
|
SIDEBAR_PERCENT :: f32(0.20)
|
|
DISPLAY_V_RATIO :: f32(0.40)
|
|
// Fixed heights
|
|
CONTROL_BAR_H :: f32(50)
|
|
STATUS_BAR_H :: f32(30)
|
|
// Layout constants
|
|
PADDING_X :: f32(10)
|
|
PADDING_Y :: f32(8)
|
|
PANEL_HEADER :: f32(24)
|
|
// Buttons
|
|
BUTTON_HEIGHT :: 30
|
|
BUTTON_WIDTH :: 120
|
|
// Fonts
|
|
BIG_FONT_SIZE :: 20
|
|
KEYPAD_FONT_SIZE :: 18
|
|
|
|
Layout :: struct {
|
|
control_bar : rl.Rectangle,
|
|
file_loader : rl.Rectangle,
|
|
keypad : rl.Rectangle,
|
|
display : rl.Rectangle,
|
|
bottom_panel : rl.Rectangle,
|
|
cpu : 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("./assets/sounds/beep.wav")
|
|
|
|
// Load fonts
|
|
font := rl.LoadFontEx("./assets/fonts/Inter_18pt-Regular.ttf", 18, nil, 0)
|
|
rl.SetTextureFilter(font.texture, .BILINEAR)
|
|
sim.font = font
|
|
|
|
rl.GuiLoadStyleDefault()
|
|
rl.GuiLoadStyle("./assets/raygui_styles/genesis.rgs")
|
|
|
|
rl.GuiSetFont(font)
|
|
rl.GuiSetStyle(.DEFAULT, 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.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)
|
|
}
|
|
|
|
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
|
|
// ------------------------------------------
|
|
gui_control_bar(layout.control_bar, sim)
|
|
|
|
// Left
|
|
// ------------------------------------------
|
|
gui_file_loader(layout.file_loader, sim)
|
|
gui_key_pad(layout.keypad, sim.machine.keypad, sim.font)
|
|
|
|
// Center
|
|
// ------------------------------------------
|
|
gui_screen(layout.display, sim)
|
|
|
|
// Right
|
|
// ------------------------------------------
|
|
gui_cpu(layout.cpu, sim)
|
|
|
|
// Bottom
|
|
// ------------------------------------------
|
|
gui_bottom_tabs(layout.bottom_panel, sim)
|
|
gui_status_bar(layout.status_bar, sim)
|
|
|
|
rl.EndDrawing()
|
|
}
|
|
|
|
rl.UnloadFont(sim.font)
|
|
rl.UnloadSound(beep)
|
|
rl.CloseAudioDevice()
|
|
rl.CloseWindow()
|
|
}
|
|
|
|
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 {
|
|
// Control bar is a fixed height frozen at top of gui, all items start below it.
|
|
y_pos := CONTROL_BAR_H
|
|
x_pos := f32(0)
|
|
|
|
// Usable gui vertical space
|
|
visible_height := screen_height - CONTROL_BAR_H - STATUS_BAR_H
|
|
sidebar_width := screen_width * SIDEBAR_PERCENT
|
|
display_width := screen_width - (sidebar_width * 2) - sidebar_width
|
|
display_height := visible_height * DISPLAY_V_RATIO
|
|
keypad_height := (y_pos + visible_height - visible_height / 2)
|
|
|
|
x_center := sidebar_width
|
|
y_center := screen_width - sidebar_width * 2
|
|
|
|
return Layout {
|
|
// Left Area
|
|
control_bar = rl.Rectangle{
|
|
x = 0,
|
|
y = 0,
|
|
width = screen_width,
|
|
height = CONTROL_BAR_H,
|
|
},
|
|
file_loader = rl.Rectangle{
|
|
x = 0,
|
|
y = y_pos,
|
|
width = sidebar_width,
|
|
height = keypad_height - y_pos
|
|
},
|
|
keypad = rl.Rectangle{
|
|
x = 0,
|
|
y = keypad_height,
|
|
width = sidebar_width,
|
|
height = visible_height / 2
|
|
},
|
|
|
|
// ------------------------------------------
|
|
// Center Area
|
|
display = rl.Rectangle{
|
|
x = sidebar_width,
|
|
y = y_pos,
|
|
width = display_width,
|
|
height = display_height,
|
|
},
|
|
|
|
// ------------------------------------------
|
|
// Bottom Area
|
|
bottom_panel = rl.Rectangle{
|
|
x = sidebar_width,
|
|
y = y_pos + display_height,
|
|
width = screen_width - sidebar_width,
|
|
height = visible_height - display_height,
|
|
},
|
|
|
|
// ------------------------------------------
|
|
// Right Area
|
|
cpu = rl.Rectangle {
|
|
x = sidebar_width + display_width,
|
|
y = y_pos,
|
|
width = sidebar_width * 2,
|
|
height = display_height
|
|
},
|
|
|
|
// ------------------------------------------
|
|
// Bottom Area
|
|
status_bar = rl.Rectangle{
|
|
x = x_pos,
|
|
y = y_pos + visible_height,
|
|
width = screen_width,
|
|
height = STATUS_BAR_H,
|
|
},
|
|
}
|
|
}
|