dynamically show list of available roms
This commit is contained in:
parent
7446790256
commit
4c2cc5135e
Binary file not shown.
@ -12,16 +12,17 @@ const assert = std.debug.assert;
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const StringList = std.ArrayList([]const u8);
|
const StringList = std.ArrayList([]const u8);
|
||||||
|
|
||||||
const example_roms = roms.listROMs();
|
const rom_list = roms.listROMs();
|
||||||
|
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
|
|
||||||
chip: *ChipContext,
|
chip: *ChipContext,
|
||||||
raylib_chip: *RaylibChip,
|
raylib_chip: *RaylibChip,
|
||||||
chip_sound: rl.Sound,
|
chip_sound: rl.Sound,
|
||||||
rom: ?ROM = null,
|
|
||||||
|
|
||||||
is_gui_open: bool = true,
|
is_gui_open: bool = true,
|
||||||
|
selected_rom_index: i32 = 3,
|
||||||
|
rom_list_scroll_index: i32 = 0,
|
||||||
|
|
||||||
pub fn genSinWave(wave: *rl.Wave, frequency: f32) void {
|
pub fn genSinWave(wave: *rl.Wave, frequency: f32) void {
|
||||||
assert(wave.sampleSize == 16); // Only 16 bits are supported
|
assert(wave.sampleSize == 16); // Only 16 bits are supported
|
||||||
@ -68,7 +69,7 @@ pub fn init(allocator: Allocator) !Self {
|
|||||||
.chip_sound = chip_sound,
|
.chip_sound = chip_sound,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.set_rom(example_roms[3]);
|
self.set_rom(3);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -81,8 +82,9 @@ pub fn deinit(self: *Self) void {
|
|||||||
self.allocator.destroy(self.chip);
|
self.allocator.destroy(self.chip);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_rom(self: *Self, rom: ROM) void {
|
pub fn set_rom(self: *Self, index: i32) void {
|
||||||
self.rom = rom;
|
self.selected_rom_index = index;
|
||||||
|
const rom = rom_list[@intCast(index)];
|
||||||
self.chip.reset();
|
self.chip.reset();
|
||||||
self.chip.set_memory(0x200, rom.data);
|
self.chip.set_memory(0x200, rom.data);
|
||||||
}
|
}
|
||||||
@ -115,10 +117,67 @@ pub fn draw(self: *Self) void {
|
|||||||
render_height
|
render_height
|
||||||
);
|
);
|
||||||
|
|
||||||
self.draw_gui();
|
self.drawGui(self.allocator) catch @panic("GUI OOM");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_gui(self: *Self) void {
|
fn GuiListView(
|
||||||
|
allocator: Allocator,
|
||||||
|
bounds: rl.Rectangle,
|
||||||
|
items: []const []const u8,
|
||||||
|
scroll_index: *i32,
|
||||||
|
active: *i32,
|
||||||
|
) !i32 {
|
||||||
|
var needed_size: usize = 0;
|
||||||
|
needed_size += items.len-1; // N-1 character are needed for the separators
|
||||||
|
for (items) |item| {
|
||||||
|
needed_size += item.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
var str_buffer = try allocator.allocSentinel(u8, needed_size, 0);
|
||||||
|
defer allocator.free(str_buffer);
|
||||||
|
|
||||||
|
var idx: usize = 0;
|
||||||
|
for (0.., items) |i, item| {
|
||||||
|
@memcpy(str_buffer[idx..(idx+item.len)], item);
|
||||||
|
idx += item.len;
|
||||||
|
|
||||||
|
if (i != items.len-1) {
|
||||||
|
str_buffer[idx] = ';';
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gui.GuiListView(bounds, str_buffer, scroll_index, active);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn GuiListViewMinWidth(allocator: Allocator, height: i32, items: []const []const u8) !i32 {
|
||||||
|
const border_width = gui.GuiGetStyle(.DEFAULT , @intFromEnum(gui.GuiControlProperty.BORDER_WIDTH));
|
||||||
|
const item_spacing = gui.GuiGetStyle(.LISTVIEW, @intFromEnum(gui.GuiListViewProperty.LIST_ITEMS_SPACING));
|
||||||
|
const item_height = gui.GuiGetStyle(.LISTVIEW, @intFromEnum(gui.GuiListViewProperty.LIST_ITEMS_HEIGHT));
|
||||||
|
const font_size = gui.GuiGetStyle(.DEFAULT , @intFromEnum(gui.GuiDefaultProperty.TEXT_SIZE));
|
||||||
|
const scrollbar_width = gui.GuiGetStyle(.LISTVIEW, @intFromEnum(gui.GuiListViewProperty.SCROLLBAR_WIDTH));
|
||||||
|
|
||||||
|
var max_item_width: i32 = 0;
|
||||||
|
for (items) |item| {
|
||||||
|
const item_z = try allocator.dupeZ(u8, item);
|
||||||
|
defer allocator.free(item_z);
|
||||||
|
const item_width = rl.MeasureText(item_z, font_size);
|
||||||
|
|
||||||
|
max_item_width = @max(max_item_width, item_width);
|
||||||
|
}
|
||||||
|
|
||||||
|
const item_count: i32 = @intCast(items.len);
|
||||||
|
const need_scrollbar = ((item_height + item_spacing)*item_count > height);
|
||||||
|
|
||||||
|
var min_width = max_item_width + 2*item_spacing + border_width;
|
||||||
|
if (need_scrollbar) {
|
||||||
|
min_width += scrollbar_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
return min_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drawGui(self: *Self, allocator: Allocator) !void {
|
||||||
if (rl.IsKeyPressed(.KEY_TAB)) {
|
if (rl.IsKeyPressed(.KEY_TAB)) {
|
||||||
self.is_gui_open = !self.is_gui_open;
|
self.is_gui_open = !self.is_gui_open;
|
||||||
}
|
}
|
||||||
@ -137,12 +196,34 @@ pub fn draw_gui(self: *Self) void {
|
|||||||
const window_width: f32 = 300;
|
const window_width: f32 = 300;
|
||||||
const window_height: f32 = 100;
|
const window_height: f32 = 100;
|
||||||
const window = rl.Rectangle{
|
const window = rl.Rectangle{
|
||||||
.x = (screen_width-window_width)/2,
|
.x = @trunc((screen_width-window_width)/2),
|
||||||
.y = (screen_height-window_height)/2,
|
.y = @trunc((screen_height-window_height)/2),
|
||||||
.width = window_width,
|
.width = window_width,
|
||||||
.height = window_height
|
.height = window_height
|
||||||
};
|
};
|
||||||
if (gui.GuiWindowBox(window, "CHIP-8 Settings") == 1) {
|
if (gui.GuiWindowBox(window, "CHIP-8 Settings") == 1) {
|
||||||
self.is_gui_open = false;
|
self.is_gui_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rl.rlPushMatrix();
|
||||||
|
rl.rlTranslatef(window.x, window.y, 0);
|
||||||
|
|
||||||
|
const rom_list_names = try allocator.alloc([]const u8, rom_list.len);
|
||||||
|
defer allocator.free(rom_list_names);
|
||||||
|
|
||||||
|
for (0.., rom_list) |i, rom| {
|
||||||
|
rom_list_names[i] = rom.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const list_height = 100;
|
||||||
|
const list_width = try GuiListViewMinWidth(allocator, list_height, rom_list_names) + 20;
|
||||||
|
_ = try GuiListView(
|
||||||
|
allocator,
|
||||||
|
.{.x=10,.y=24, .width=@floatFromInt(list_width), .height=list_height},
|
||||||
|
rom_list_names,
|
||||||
|
&self.rom_list_scroll_index,
|
||||||
|
&self.selected_rom_index
|
||||||
|
);
|
||||||
|
|
||||||
|
rl.rlPopMatrix();
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,6 @@ pub fn main() anyerror!void {
|
|||||||
var scene = try MainScene.init(allocator);
|
var scene = try MainScene.init(allocator);
|
||||||
defer scene.deinit();
|
defer scene.deinit();
|
||||||
|
|
||||||
const font_size = 24;
|
|
||||||
const font_ttf_default_numchars = 95; // TTF font generation default charset: 95 glyphs (ASCII 32..126)
|
|
||||||
const font = rl.LoadFontEx("src/assets/fonts/generic-mono.otf", font_size, null, font_ttf_default_numchars);
|
|
||||||
defer rl.UnloadFont(font);
|
|
||||||
|
|
||||||
while (!rl.WindowShouldClose()) {
|
while (!rl.WindowShouldClose()) {
|
||||||
var dt = rl.GetFrameTime();
|
var dt = rl.GetFrameTime();
|
||||||
scene.update(dt);
|
scene.update(dt);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
const std = @import("std");
|
||||||
const options = @import("options");
|
const options = @import("options");
|
||||||
const rom_count = options.roms.len;
|
const rom_count = options.roms.len;
|
||||||
|
|
||||||
@ -10,8 +11,12 @@ pub fn listROMs() [options.roms.len]ROM {
|
|||||||
var roms: [options.roms.len]ROM = undefined;
|
var roms: [options.roms.len]ROM = undefined;
|
||||||
|
|
||||||
for (0.., options.roms) |i, file| {
|
for (0.., options.roms) |i, file| {
|
||||||
|
const extension = std.mem.lastIndexOfScalar(u8, file, '.') orelse file.len;
|
||||||
|
const slash = std.mem.lastIndexOfScalar(u8, file, '/') orelse -1;
|
||||||
|
|
||||||
|
const name = file[(slash+1)..extension];
|
||||||
roms[i] = ROM{
|
roms[i] = ROM{
|
||||||
.name = file,
|
.name = name,
|
||||||
.data = @embedFile(file)
|
.data = @embedFile(file)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user