Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eb702890bb | |||
| f8ef6f030f |
Binary file not shown.
Binary file not shown.
@@ -61,9 +61,9 @@ init :: proc() -> System {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
run_machine :: proc(s: ^System) {
|
run_machine :: proc(s: ^System, cycles: int) {
|
||||||
// CPU cycles
|
// CPU cycles
|
||||||
for _ in 0..<12 {
|
for _ in 0..<cycles {
|
||||||
handle_input(s)
|
handle_input(s)
|
||||||
cycle(s)
|
cycle(s)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-9
@@ -3,8 +3,8 @@ package main
|
|||||||
import "core:log"
|
import "core:log"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
|
|
||||||
import chip "machine"
|
import emu "machine"
|
||||||
import gui "gui"
|
import sim "simulator"
|
||||||
|
|
||||||
DEV :: #config(DEV, false)
|
DEV :: #config(DEV, false)
|
||||||
|
|
||||||
@@ -20,20 +20,18 @@ main :: proc() {
|
|||||||
context.allocator = mem.tracking_allocator(&track)
|
context.allocator = mem.tracking_allocator(&track)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the Chip 8 "cpu"
|
// Init the emu 8 "cpu"
|
||||||
system := chip.init()
|
system := emu.init()
|
||||||
|
|
||||||
// TODO: move this into a gui component
|
// TODO: move this into a gui component
|
||||||
// load rom, hardcoded for now, will eventually be cli or gui
|
// load rom, hardcoded for now, will eventually be cli or gui
|
||||||
err := chip.load_rom(&system, "./test_roms/7-beep.ch8")
|
err := emu.load_rom(&system, "./test_roms/7-beep.ch8")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to load rom!")
|
panic("failed to load rom!")
|
||||||
}
|
}
|
||||||
|
|
||||||
// gui will init the layout etc, it will require reference to
|
// Initilize sim, gui etc
|
||||||
// the system as it will use its display buffer etc
|
sim.run_simulator(&system)
|
||||||
// NOTE: may just need a few fields rather than whole struct check later
|
|
||||||
gui.init_gui(&system)
|
|
||||||
|
|
||||||
when DEV {
|
when DEV {
|
||||||
if len(track.allocation_map) > 0 {
|
if len(track.allocation_map) > 0 {
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
package gui
|
package simulator
|
||||||
|
|
||||||
import "core:log"
|
import "core:log"
|
||||||
import m "../machine"
|
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
PADDING :: 10
|
PADDING :: 10
|
||||||
|
|
||||||
gui_control_bar :: proc(rect: rl.Rectangle, s: ^m.System) {
|
gui_control_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) {
|
||||||
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
|
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
|
||||||
|
|
||||||
// Small text area
|
// Small text area
|
||||||
|
|
||||||
// Control bar buttons
|
// Control bar buttons
|
||||||
@@ -17,10 +15,19 @@ gui_control_bar :: proc(rect: rl.Rectangle, s: ^m.System) {
|
|||||||
gap : f32 = 6
|
gap : f32 = 6
|
||||||
cursor : f32 = rect.x + PADDING
|
cursor : f32 = rect.x + PADDING
|
||||||
|
|
||||||
if btn(&cursor, rect, btn_h, btn_w, gap, "RUN") { log.info("RUN clicked") }
|
if btn(&cursor, rect, btn_h, btn_w, gap, "RUN") {
|
||||||
if btn(&cursor, rect, btn_h, btn_w, gap, "PAUSE") { log.info("PAUSE clicked") }
|
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") }
|
if btn(&cursor, rect, btn_h, btn_w, gap, "STEP") { log.info("STEP clicked") }
|
||||||
if btn(&cursor, rect, btn_h, btn_w, gap, "STOP") { log.info("STOP clicked") }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
btn :: proc(cursor: ^f32, rect: rl.Rectangle, h, w, gap: f32, label: cstring) -> bool {
|
btn :: proc(cursor: ^f32, rect: rl.Rectangle, h, w, gap: f32, label: cstring) -> bool {
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package gui
|
package simulator
|
||||||
|
|
||||||
import m "../machine"
|
import emu "../machine"
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
// Initial window size
|
// Initial window size
|
||||||
@@ -17,14 +17,29 @@ Layout :: struct {
|
|||||||
left_panel : rl.Rectangle,
|
left_panel : rl.Rectangle,
|
||||||
display : rl.Rectangle,
|
display : rl.Rectangle,
|
||||||
right_panel : rl.Rectangle,
|
right_panel : rl.Rectangle,
|
||||||
|
status_bar : rl.Rectangle,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize main the gui 'window'
|
// Initialize main the gui 'window'
|
||||||
init_gui :: proc(s: ^m.System) {
|
run_gui :: proc(sim: ^Simulator) {
|
||||||
rl.SetConfigFlags({.WINDOW_RESIZABLE})
|
rl.SetConfigFlags({.WINDOW_RESIZABLE})
|
||||||
rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "raylib")
|
rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "raylib")
|
||||||
rl.InitAudioDevice()
|
rl.InitAudioDevice()
|
||||||
rl.SetTargetFPS(60)
|
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
|
// Draw each of the components in its own window within the main window
|
||||||
for !rl.WindowShouldClose() {
|
for !rl.WindowShouldClose() {
|
||||||
@@ -41,17 +56,39 @@ init_gui :: proc(s: ^m.System) {
|
|||||||
rl.ClearBackground(rl.BLACK)
|
rl.ClearBackground(rl.BLACK)
|
||||||
|
|
||||||
// Cycle the machine to update memory etc
|
// Cycle the machine to update memory etc
|
||||||
m.run_machine(s)
|
// if (sim.is_running) else don't run machine, here we can start,pause etc
|
||||||
|
if (!sim.paused) {
|
||||||
|
emu.run_machine(sim.machine, 12)
|
||||||
|
|
||||||
// Now draw the update data
|
// Handle delay timer
|
||||||
gui_left_panel(layout.left_panel, s)
|
if sim.machine.delay_timer > 0 do sim.machine.delay_timer -= 1
|
||||||
gui_right_panel(layout.right_panel, s)
|
|
||||||
gui_screen(layout.display, s)
|
// Current sound file is around 1s so stop
|
||||||
gui_control_bar(layout.control_bar, s)
|
// 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.EndDrawing()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rl.UnloadFont(sim.font)
|
||||||
|
rl.UnloadFont(font)
|
||||||
|
rl.UnloadSound(beep)
|
||||||
rl.CloseAudioDevice()
|
rl.CloseAudioDevice()
|
||||||
rl.CloseWindow()
|
rl.CloseWindow()
|
||||||
}
|
}
|
||||||
@@ -88,5 +125,11 @@ calc_layout :: proc(screen_width: f32, screen_height: f32) -> Layout {
|
|||||||
width = sidebar_width,
|
width = sidebar_width,
|
||||||
height = sidebar_height
|
height = sidebar_height
|
||||||
},
|
},
|
||||||
|
status_bar = rl.Rectangle {
|
||||||
|
x = 0,
|
||||||
|
y = screen_height - control_bar_height,
|
||||||
|
width = screen_width,
|
||||||
|
height = control_bar_height
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package gui
|
package simulator
|
||||||
|
|
||||||
import m "../machine"
|
import m "../machine"
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package gui
|
package simulator
|
||||||
|
|
||||||
import m "../machine"
|
import m "../machine"
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package gui
|
package simulator
|
||||||
|
|
||||||
import m "../machine"
|
import m "../machine"
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user