Compare commits
4 Commits
497a62c16d
...
paoda/upgr
| Author | SHA1 | Date | |
|---|---|---|---|
| de711a37c2 | |||
| 38fabc92c5 | |||
| f4c8bd9099 | |||
| 242060e35d |
30
README.md
30
README.md
@@ -27,35 +27,9 @@ Finally it's worth noting that ZBA uses a TOML config file it'll store in your O
|
||||
|
||||
## Compiling
|
||||
|
||||
Most recently built on Zig [v0.11.0](https://github.com/ziglang/zig/tree/0.11.0)
|
||||
Most recently built on Zig [v0.15.1](https://github.com/ziglang/zig/tree/0.15.1)
|
||||
|
||||
### Dependencies
|
||||
|
||||
Dependency | Source
|
||||
--- | ---
|
||||
known-folders | <https://github.com/ziglibs/known-folders>
|
||||
nfd-zig | <https://github.com/fabioarnold/nfd-zig>
|
||||
SDL.zig | <https://github.com/MasterQ32/SDL.zig>
|
||||
tomlz | <https://github.com/mattyhall/tomlz>
|
||||
zba-gdbstub | <https://github.com/paoda/zba-gdbstub>
|
||||
zba-util | <https://git.musuka.dev/paoda/zba-util>
|
||||
zgui | <https://github.com/michal-z/zig-gamedev/tree/main/libs/zgui>
|
||||
zig-clap | <https://github.com/Hejsil/zig-clap>
|
||||
zig-datetime | <https://github.com/frmdstryr/zig-datetime>
|
||||
`bitfield.zig` | [https://github.com/FlorenceOS/Florence](https://github.com/FlorenceOS/Florence/blob/aaa5a9e568/lib/util/bitfields.zig)
|
||||
`gl.zig` | <https://github.com/MasterQ32/zig-opengl>
|
||||
|
||||
Use `git submodule update --init` from the project root to pull the git relevant git submodules
|
||||
|
||||
Be sure to provide SDL2 using:
|
||||
|
||||
- Linux: Your distro's package manager
|
||||
- macOS: ¯\\\_(ツ)_/¯ (try [this formula](https://formulae.brew.sh/formula/sdl2)?)
|
||||
- Windows: [`vcpkg`](https://github.com/Microsoft/vcpkg) (install `sdl2:x64-windows`)
|
||||
|
||||
`SDL.zig` will provide a helpful compile error if the zig compiler is unable to find SDL2.
|
||||
|
||||
Once you've got all the dependencies, execute `zig build -Doptimize=ReleaseSafe`. The executable will be under `zig-out/bin` and the shared libraries (if enabled) under `zig-out/lib`. If working with shared libraries on windows, be sure to add all artifacts to the same directory. On Unix, you'll want to make use of `LD_PRELOAD`.
|
||||
Run `zig build -Doptimize=ReleaseSafe`. The executable will be under `zig-out/bin` and the shared libraries (if enabled) under `zig-out/lib`. If working with shared libraries on windows, be sure to add all artifacts to the same directory. On Unix, you'll want to make use of `LD_PRELOAD`.
|
||||
|
||||
## Controls
|
||||
|
||||
|
||||
@@ -58,11 +58,7 @@ pub fn build(b: *std.Build) void {
|
||||
//
|
||||
// If neither case applies to you, feel free to delete the declaration you
|
||||
// don't need and to put everything under a single module.
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "zba",
|
||||
.root_module = exe_mod,
|
||||
.use_llvm = true,
|
||||
});
|
||||
const exe = b.addExecutable(.{ .name = "zba", .root_module = exe_mod });
|
||||
|
||||
const zgui = b.dependency("zgui", .{ .shared = false, .with_implot = true, .backend = .sdl3_opengl3 });
|
||||
const sdl = b.dependency("sdl", .{ .target = target, .optimize = optimize, .preferred_linkage = .static });
|
||||
@@ -84,6 +80,7 @@ pub fn build(b: *std.Build) void {
|
||||
exe_mod.addImport("nfd", b.dependency("nfdzig", .{}).module("nfd"));
|
||||
exe_mod.addImport("zgui", zgui.module("root"));
|
||||
exe_mod.addImport("bitjuggle", b.dependency("bitjuggle", .{}).module("bitjuggle"));
|
||||
exe_mod.addImport("toml", b.dependency("toml", .{}).module("toml"));
|
||||
|
||||
exe_mod.addAnonymousImport("example.toml", .{ .root_source_file = b.path("example.toml") });
|
||||
|
||||
|
||||
@@ -11,14 +11,6 @@
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.fingerprint = 0xcb596c7fbdb20efc,
|
||||
.dependencies = .{
|
||||
// .tomlz = .{
|
||||
// .url = "git+https://github.com/paoda/tomlz#9a16dd53927ef2012478b6494bafb4475e44f4c9",
|
||||
// .hash = "12204f922cab84980e36b5c058d354ec0ee169bda401c8e0e80a463580349b476569",
|
||||
// },
|
||||
|
||||
.zba_util = .{ .path = "../zba-util" },
|
||||
.arm32 = .{ .path = "../arm32" },
|
||||
.zba_gdbstub = .{ .path = "../zba-gdbstub" },
|
||||
.known_folders = .{
|
||||
.url = "git+https://github.com/ziglibs/known-folders.git#ab5cf5feb936fa3b72c95d3ad0c0c67791937ba1",
|
||||
.hash = "known_folders-0.0.0-Fy-PJtTTAADUOhGKM0sxzG4eMkNQxRvx9e5dfHVyaeA3",
|
||||
@@ -51,5 +43,21 @@
|
||||
.url = "git+https://github.com/zig-gamedev/zgui#7fa8081c208885b85e3fdfc043cd9d9cb9559123",
|
||||
.hash = "zgui-0.6.0-dev--L6sZL7tbQAPRLYrcQAVx0V49tPHAXNxclZ-v8IP4wLr",
|
||||
},
|
||||
.toml = .{
|
||||
.url = "git+https://github.com/sam701/zig-toml?ref=zig-0.15#475b03c630c802f8b6bd3e239d8fc2279b4fadb8",
|
||||
.hash = "toml-0.3.0-bV14BfV7AQD8DkuQI7skP8ekQTaBYKTO0MY_35Cw_EXo",
|
||||
},
|
||||
.zba_util = .{
|
||||
.url = "git+https://git.musuka.dev/paoda/zba-util#d75962ac9bdf9b6f0d37e37d5097ea9bb9c16779",
|
||||
.hash = "zba_util-0.0.0-SK3QiakqAABPCct0WbLsuHFfmxwzH99FmEVznCBKzdmR",
|
||||
},
|
||||
.arm32 = .{
|
||||
.url = "git+https://git.musuka.dev/paoda/arm32#c9360e1e239300d8c80bcbc3a7494f015a82c4e1",
|
||||
.hash = "arm32-0.0.0--_LW1VwTAgAbqwOzVfjnkClkwBrB8IZ1LSz8N4EoA3U3",
|
||||
},
|
||||
.zba_gdbstub = .{
|
||||
.url = "git+https://git.musuka.dev/paoda/zba-gdbstub#7b77964e145ac874424a190ecd390596601a40d1",
|
||||
.hash = "zba_gdbstub-0.0.0-KDf2GNiPAAAR5QuteF1MsN3XGElNvHLlRJ7O4PNFvTmK",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
// const tomlz = @import("tomlz");
|
||||
const toml = @import("toml");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
@@ -7,7 +7,6 @@ const log = std.log.scoped(.Config);
|
||||
var state: Config = .{};
|
||||
|
||||
const Config = struct {
|
||||
// FIXME: tomlz expects these to be case sensitive
|
||||
host: Host = .{},
|
||||
guest: Guest = .{},
|
||||
debug: Debug = .{},
|
||||
@@ -69,7 +68,11 @@ pub fn load(allocator: Allocator, config_path: []const u8) !void {
|
||||
const contents = try file.readToEndAlloc(allocator, try file.getEndPos());
|
||||
defer allocator.free(contents);
|
||||
|
||||
// FIXME(2025-09-22): re-enable
|
||||
// state = try tomlz.parser.decode(Config, allocator, contents);
|
||||
state = .{};
|
||||
var parser = toml.Parser(Config).init(allocator);
|
||||
defer parser.deinit();
|
||||
|
||||
const parsed = try parser.parseString(contents);
|
||||
defer parsed.deinit();
|
||||
|
||||
state = parsed.value; // FIXME: should copy the struct to state
|
||||
}
|
||||
|
||||
@@ -255,8 +255,6 @@ pub const Apu = struct {
|
||||
fs: FrameSequencer,
|
||||
capacitor: f32,
|
||||
|
||||
is_buffer_full: bool,
|
||||
|
||||
pub const Tick = enum { Length, Envelope, Sweep };
|
||||
|
||||
pub fn init(sched: *Scheduler) Self {
|
||||
@@ -278,7 +276,6 @@ pub const Apu = struct {
|
||||
|
||||
.capacitor = 0,
|
||||
.fs = FrameSequencer.init(),
|
||||
.is_buffer_full = false,
|
||||
};
|
||||
|
||||
Self.initEvents(apu.sched, apu.interval());
|
||||
@@ -399,11 +396,6 @@ pub const Apu = struct {
|
||||
pub fn sampleAudio(self: *Self, late: u64) void {
|
||||
self.sched.push(.SampleAudio, self.interval() -| late);
|
||||
|
||||
// Whether the APU is busy or not is determined by the main loop in emu.zig
|
||||
// This should only ever be true (because this side of the emu is single threaded)
|
||||
// When audio sync is disaabled
|
||||
if (self.is_buffer_full) return;
|
||||
|
||||
var left: i16 = 0;
|
||||
var right: i16 = 0;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S
|
||||
if (sync.paused.load(.monotonic)) continue;
|
||||
|
||||
runFrame(scheduler, cpu);
|
||||
audioSync(audio_sync, bus_ptr.apu.stream, &bus_ptr.apu.is_buffer_full);
|
||||
if (audio_sync) audioSync(bus_ptr.apu.stream);
|
||||
|
||||
if (kind == .UnlimitedFPS) tracker.?.tick();
|
||||
}
|
||||
@@ -117,10 +117,13 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S
|
||||
// the amount of time needed for audio to catch up rather than
|
||||
// our expected wake-up time
|
||||
|
||||
audioSync(audio_sync, bus_ptr.apu.stream, &bus_ptr.apu.is_buffer_full);
|
||||
if (!audio_sync) spinLoop(&timer, wake_time);
|
||||
wake_time = new_wake_time;
|
||||
if (audio_sync) {
|
||||
audioSync(bus_ptr.apu.stream);
|
||||
} else {
|
||||
spinLoop(&timer, wake_time);
|
||||
}
|
||||
|
||||
wake_time = new_wake_time;
|
||||
if (kind == .LimitedFPS) tracker.?.tick();
|
||||
}
|
||||
},
|
||||
@@ -160,35 +163,25 @@ pub fn runFrame(sched: *Scheduler, cpu: *Arm7tdmi) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn audioSync(audio_sync: bool, stream: ?*c.SDL_AudioStream, is_buffer_full: *bool) void {
|
||||
if (stream == null) return;
|
||||
fn audioSync(stream: ?*c.SDL_AudioStream) void {
|
||||
if (stream == null) {
|
||||
@branchHint(.cold);
|
||||
return log.err("audio sync failed. no SDL_AudioStream to sync to", .{});
|
||||
}
|
||||
|
||||
const sample_size = 2 * @sizeOf(u16);
|
||||
const max_buf_size: c_int = 0x400;
|
||||
const max_sample_delay: c_int = 0x800;
|
||||
var is_behind = true;
|
||||
|
||||
_ = audio_sync;
|
||||
_ = is_buffer_full;
|
||||
while (is_behind) {
|
||||
const bytes = c.SDL_GetAudioStreamQueued(stream);
|
||||
if (bytes == -1) std.debug.panic("failed to query amount of queued bytes in audio stream: SDL Error {s}", .{c.SDL_GetError()});
|
||||
|
||||
_ = sample_size;
|
||||
_ = max_buf_size;
|
||||
is_behind = bytes > max_sample_delay * sample_size;
|
||||
std.atomic.spinLoopHint();
|
||||
}
|
||||
|
||||
// TODO(paoda): re-enable
|
||||
|
||||
// // Determine whether the APU is busy right at this moment
|
||||
// var still_full: bool = SDL.SDL_AudioStreamAvailable(stream) > sample_size * if (is_buffer_full.*) max_buf_size >> 1 else max_buf_size;
|
||||
// defer is_buffer_full.* = still_full; // Update APU Busy status right before exiting scope
|
||||
|
||||
// // If Busy is false, there's no need to sync here
|
||||
// if (!still_full) return;
|
||||
|
||||
// // TODO: Refactor!!!!
|
||||
// // while (SDL.SDL_AudioStreamAvailable(stream) > sample_size * max_buf_size >> 1)
|
||||
// // std.atomic.spinLoopHint();
|
||||
|
||||
// while (true) {
|
||||
// still_full = SDL.SDL_AudioStreamAvailable(stream) > sample_size * max_buf_size >> 1;
|
||||
// if (!audio_sync or !still_full) break;
|
||||
// }
|
||||
// FIXME(paoda, 2025-11-12): There was an is_buffer_full thing going on here that I'm sure was really important for some niche reason
|
||||
}
|
||||
|
||||
fn videoSync(timer: *Timer, wake_time: u64) u64 {
|
||||
|
||||
@@ -204,44 +204,84 @@ pub fn draw(state: *State, sync: *Synchro, dim: Dimensions, cpu: *const Arm7tdmi
|
||||
_ = zgui.begin("Dependencies", .{ .popen = &state.win_stat.show_deps });
|
||||
defer zgui.end();
|
||||
|
||||
zgui.bulletText("known-folders by ziglibs", .{});
|
||||
zgui.bulletText("nfd-zig ported by Fabio Arnold", .{});
|
||||
zgui.textLinkOpenURL("known-folders", "https://github.com/ziglibs/known-folders");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by ziglibs", .{});
|
||||
|
||||
zgui.textLinkOpenURL("nfd-zig", "https://github.com/fabioarnold/nfd-zig");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("ported by Fabio Arnold", .{});
|
||||
{
|
||||
zgui.indent(.{});
|
||||
defer zgui.unindent(.{});
|
||||
|
||||
zgui.bulletText("nativefiledialog by Michael Labbe", .{});
|
||||
zgui.textLinkOpenURL("nativefiledialog", "https://github.com/mlabbe/nativefiledialog");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Michael Labbe", .{});
|
||||
}
|
||||
|
||||
zgui.bulletText("SDL ported by Carl Åstholm", .{});
|
||||
zgui.textLinkOpenURL("SDL", "https://github.com/castholm/SDL");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("ported by Carl Åstholm", .{});
|
||||
{
|
||||
zgui.indent(.{});
|
||||
defer zgui.unindent(.{});
|
||||
|
||||
zgui.bulletText("SDL by Sam Lantinga", .{});
|
||||
zgui.textLinkOpenURL("SDL", "by Sam Lantinga");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Sam Lantinga", .{});
|
||||
}
|
||||
|
||||
// zgui.bulletText("tomlz by Matthew Hall", .{});
|
||||
zgui.bulletText("zba-gdbstub by Rekai Musuka", .{});
|
||||
zgui.bulletText("zba-util by Rekai Musuka", .{});
|
||||
zgui.bulletText("zgui ported by Michal Ziulek et al.", .{});
|
||||
zgui.textLinkOpenURL("zig-toml", "https://github.com/sam701/zig-toml");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Alexei Samokvalov", .{});
|
||||
|
||||
zgui.textLinkOpenURL("zba-gdbstub", "https://git.musuka.dev/paoda/zba-gdbstub");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Rekai Musuka", .{});
|
||||
|
||||
zgui.textLinkOpenURL("zba-util", "https://git.musuka.dev/paoda/zba-util");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Rekai Musuka", .{});
|
||||
|
||||
zgui.textLinkOpenURL("arm32", "https://git.musuka.dev/paoda/arm32");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Rekai Musuka", .{});
|
||||
|
||||
zgui.textLinkOpenURL("zgui", "https://github.com/zig-gamedev/zgui");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("ported by Michal Ziulek et al.", .{});
|
||||
{
|
||||
zgui.indent(.{});
|
||||
defer zgui.unindent(.{});
|
||||
|
||||
zgui.bulletText("DearImGui by Omar Cornut", .{});
|
||||
zgui.textLinkOpenURL("Dear ImGui", "https://github.com/ocornut/imgui");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Omar Cornut", .{});
|
||||
}
|
||||
zgui.bulletText("zig-clap by Jimmi Holst Christensen", .{});
|
||||
zgui.bulletText("zig-datetime by Jairus Martin", .{});
|
||||
|
||||
zgui.newLine();
|
||||
zgui.bulletText("bitfield.zig by Hannes Bredberg et al.", .{});
|
||||
zgui.bulletText("zigglgen ported by Carl Åstholm", .{});
|
||||
zgui.textLinkOpenURL("zig-clap", "https://github.com/Hejsil/zig-clap");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Jimmi Holst Christensen", .{});
|
||||
|
||||
zgui.textLinkOpenURL("zig-datetime", "https://github.com/frmdstryr/zig-datetime");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Jairus Martin", .{});
|
||||
|
||||
zgui.textLinkOpenURL("zig-bitjuggle", "https://github.com/leecannon/zig-bitjuggle");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by Lee Cannon + Hannes Bredberg et al.", .{});
|
||||
|
||||
zgui.textLinkOpenURL("zigglgen", "https://github.com/castholm/zigglgen");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("ported by Carl Åstholm", .{});
|
||||
{
|
||||
zgui.indent(.{});
|
||||
defer zgui.unindent(.{});
|
||||
|
||||
zgui.bulletText("OpenGL-Registry by The Khronos Group", .{});
|
||||
zgui.textLinkOpenURL("OpenGL-Registry", "https://github.com/KhronosGroup/OpenGL-Registry");
|
||||
zgui.sameLine(.{});
|
||||
zgui.text("by The Khronos Group", .{});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user