Files
octal_cookie/src/simulator/gui_tab_memory.odin
T
jasonhilder 6d706a34cd Dropped tab layout, floating info window and clean
No longer using tabs, all info in one bottom panel.
Added a floating info window, can open from control bar.
Cleanup vertical widths for scroll bars in some panes.
2026-06-24 10:31:09 +02:00

125 lines
3.8 KiB
Odin

package simulator
import "core:fmt"
import "core:strings"
import rl "vendor:raylib"
MEM_INDICATOR_W :: 14
MEM_ADDRESS_W :: 72
MEM_ROW_H :: 20
MEM_BYTES_PER_ROW :: 16
MEM_TOTAL_ROWS :: 256
MEM_FONT_ROWS :: 5
MEM_ROM_START :: 512
MEM_VIRTUAL_ROWS :: MEM_FONT_ROWS + 1 + (256 - 32)
MEM_COL_LABELS := [16]string{"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"}
byte_col_w :: proc(rect: rl.Rectangle) -> f32 {
used := f32(MEM_INDICATOR_W + MEM_ADDRESS_W + 12)
return (rect.width - used) / 16
}
gui_tab_memory :: proc(rect: rl.Rectangle, sim: ^Simulator) {
rl.DrawRectangleRec(rect, rl.DARKGRAY)
// Header background
rl.DrawRectangle(i32(rect.x), i32(rect.y), i32(rect.width), i32(PANEL_HEADER), rl.BLACK)
// Header: Address label
rl.DrawTextEx(sim.font, "Address", {rect.x + MEM_INDICATOR_W, rect.y + 4}, 18, 1, rl.WHITE)
// Header: column labels 0-F
col_w := byte_col_w(rect)
for col in 0..<16 {
x := rect.x + MEM_INDICATOR_W + MEM_ADDRESS_W + f32(col) * col_w
label := strings.clone_to_cstring(MEM_COL_LABELS[col], context.temp_allocator)
rl.DrawTextEx(sim.font, label, {x, rect.y + 4}, 18, 1, rl.WHITE)
}
// Header separator
rl.DrawLine(
i32(rect.x), i32(rect.y + PANEL_HEADER),
i32(rect.x + rect.width), i32(rect.y + PANEL_HEADER),
rl.GRAY,
)
// Scroll panel area (below header)
panel_rect := rl.Rectangle{
rect.x,
rect.y + PANEL_HEADER,
rect.width,
rect.height - PANEL_HEADER,
}
content_rect := rl.Rectangle{
0, 0,
rect.width - 15,
f32(MEM_VIRTUAL_ROWS) * MEM_ROW_H,
}
view : rl.Rectangle
rl.GuiScrollPanel(panel_rect, nil, content_rect, &sim.mem_scroll, &view)
rl.BeginScissorMode(i32(view.x), i32(view.y), i32(view.width), i32(view.height))
draw_row := 0
// Font rows (0x000 - 0x04F)
for row in 0..<MEM_FONT_ROWS {
addr := row * MEM_BYTES_PER_ROW
row_y := panel_rect.y + f32(draw_row) * MEM_ROW_H + sim.mem_scroll.y
draw_memory_row(rect, sim, draw_row, addr, row_y)
draw_row += 1
}
divider_y := panel_rect.y + f32(draw_row) * MEM_ROW_H + sim.mem_scroll.y
rl.DrawRectangle(i32(rect.x), i32(divider_y), i32(rect.width), MEM_ROW_H, rl.ColorAlpha(rl.BLACK, 0.4))
rl.DrawTextEx(
sim.font,
"---- reserved (0x0050 - 0x01FF) ----",
{rect.x + MEM_INDICATOR_W, divider_y + 2},
16, 1, rl.DARKGRAY,
)
draw_row += 1
// ROM rows (0x200 onwards)
for i := 0; MEM_ROM_START + i * MEM_BYTES_PER_ROW < 4096; i += 1 {
addr := MEM_ROM_START + i * MEM_BYTES_PER_ROW
row_y := panel_rect.y + f32(draw_row) * MEM_ROW_H + sim.mem_scroll.y
draw_memory_row(rect, sim, draw_row, addr, row_y)
draw_row += 1
}
rl.EndScissorMode()
}
draw_memory_row :: proc(rect: rl.Rectangle, sim: ^Simulator, visual_row: int, addr: int, row_y: f32) {
col_w := byte_col_w(rect)
if visual_row % 2 == 0 {
rl.DrawRectangle(i32(rect.x), i32(row_y), i32(rect.width), MEM_ROW_H, rl.ColorAlpha(rl.BLACK, 0.2))
}
addr_str := fmt.tprintf("%04X", addr)
rl.DrawTextEx(
sim.font,
strings.clone_to_cstring(addr_str, context.temp_allocator),
{rect.x + MEM_INDICATOR_W, row_y + 2},
16, 1, rl.RAYWHITE,
)
for col in 0..<16 {
byte_val := sim.machine.memory[addr + col]
byte_str := fmt.tprintf("%02X", byte_val)
x := rect.x + MEM_INDICATOR_W + MEM_ADDRESS_W + f32(col) * col_w
color := rl.RAYWHITE if byte_val != 0 else rl.GRAY
rl.DrawTextEx(
sim.font,
strings.clone_to_cstring(byte_str, context.temp_allocator),
{x, row_y + 2},
16, 1, color,
)
}
}