Compare commits

...

4 Commits

9 changed files with 105 additions and 7 deletions

3
.gitmodules vendored
View File

@ -13,3 +13,6 @@
[submodule "lib/zig-toml"]
path = lib/zig-toml
url = https://github.com/aeronavery/zig-toml
[submodule "lib/zba-gdbstub"]
path = lib/zba-gdbstub
url = https://git.musuka.dev/paoda/zba-gdbstub

View File

@ -1,6 +1,8 @@
const std = @import("std");
const builtin = @import("builtin");
const Sdk = @import("lib/SDL.zig/Sdk.zig");
const Gdbstub = @import("lib/zba-gdbstub/build.zig");
pub fn build(b: *std.build.Builder) void {
// Minimum Zig Version
@ -43,6 +45,9 @@ pub fn build(b: *std.build.Builder) void {
// OpenGL 3.3 Bindings
exe.addPackagePath("gl", "lib/gl.zig");
// gdbstub
Gdbstub.link(exe);
// Zig SDL Bindings: https://github.com/MasterQ32/SDL.zig
const sdk = Sdk.init(b);
sdk.link(exe, .dynamic);

@ -1 +1 @@
Subproject commit 2fbd4b228516bf08348a3173f1446c7e8d75540a
Subproject commit 2025889b612f345698feff44fc245501bff637e9

@ -1 +1 @@
Subproject commit 24845b0103e611c108d6bc334231c464e699742c
Subproject commit 6b37490ac7285133bf09441850b8102c9728a776

1
lib/zba-gdbstub Submodule

@ -0,0 +1 @@
Subproject commit 4bca44e5f2a4aa19361b51b7617a21f46f88eef4

@ -1 +1 @@
Subproject commit 88edafd00ec25dcc01deb8fc69e9864a16f8717c
Subproject commit 6c9ca9025199b145c42a75d10cadb3f97879ee6d

View File

@ -163,3 +163,59 @@ fn sleep(timer: *Timer, wake_time: u64) ?u64 {
fn spinLoop(timer: *Timer, wake_time: u64) void {
while (true) if (timer.read() > wake_time) break;
}
pub const EmuThing = struct {
const Self = @This();
const Interface = @import("gdbstub").Emulator;
cpu: *Arm7tdmi,
scheduler: *Scheduler,
pub fn init(cpu: *Arm7tdmi, scheduler: *Scheduler) Self {
return .{ .cpu = cpu, .scheduler = scheduler };
}
pub fn interface(self: *Self) Interface {
return Interface.init(self);
}
pub fn read(self: *const Self, addr: u32) u8 {
return self.cpu.bus.dbgRead(u8, addr);
}
pub fn write(self: *Self, addr: u32, value: u8) void {
_ = value;
_ = self;
_ = addr;
std.debug.panic("TODO: Implement Debug Writes?", .{});
}
pub fn registers(self: *const Self) *[16]u32 {
return &self.cpu.r;
}
pub fn cpsr(self: *const Self) u32 {
return self.cpu.cpsr.raw;
}
pub fn step(self: *Self) void {
const cpu = self.cpu;
const sched = self.scheduler;
// TODO: How can I make it easier to keep this in lock-step with runFrame?
while (true) {
if (!cpu.stepDmaTransfer()) {
if (cpu.isHalted()) {
// Fast-forward to next Event
sched.tick = sched.queue.peek().?.tick;
} else {
cpu.step();
break; // this function won't return until we've actually stepped once
}
}
if (sched.tick >= sched.nextTimestamp()) sched.handleEvent(cpu);
}
}
};

View File

@ -843,7 +843,12 @@ pub const Ppu = struct {
const is_top_layer = (top_layer >> layer) & 1 == 1;
if (is_top_layer) {
const pixel = self.scanline.btm()[i];
// FIXME: Can't I do this check ealier? Test Amazing Mirror File Select, bld_demo.gba
if (!pixel.isSet())
self.scanline.btm()[i] = Scanline.Pixel.from(.Background, bgr555); // this is intentional
return;
}
},

View File

@ -22,6 +22,7 @@ const params = clap.parseParamsComptime(
\\-h, --help Display this help and exit.
\\-s, --skip Skip BIOS.
\\-b, --bios <str> Optional path to a GBA BIOS ROM.
\\ --gdb Run ZBA from the context of a GDB Server
\\<str> Path to the GBA GamePak ROM.
\\
);
@ -87,11 +88,38 @@ pub fn main() void {
cpu.fastBoot();
}
if (result.args.gdb) {
const Server = @import("gdbstub").Server;
const EmuThing = @import("core/emu.zig").EmuThing;
var emu_thing = EmuThing.init(&cpu, &scheduler);
const emulator = emu_thing.interface();
{
const frames_per_second: usize = 60;
const emu = @import("core/emu.zig");
var i: usize = 0;
while (i < frames_per_second * 120) : (i += 1) {
emu.runFrame(&scheduler, &cpu);
std.debug.print("Frame {:0>3}/{:0>3}\r", .{ i, frames_per_second * 120 });
}
}
log.info("Ready to connect", .{});
var server = Server.init(emulator) catch |e| exitln("failed to init gdb server: {}", .{e});
defer server.deinit(allocator);
server.run(allocator) catch |e| exitln("gdb server crashed: {}", .{e});
} else {
var gui = Gui.init(&bus.pak.title, &bus.apu, width, height) catch |e| exitln("failed to init gui: {}", .{e});
defer gui.deinit();
gui.run(&cpu, &scheduler) catch |e| exitln("failed to run gui thread: {}", .{e});
}
}
pub fn handleArguments(allocator: Allocator, data_path: []const u8, result: *const clap.Result(clap.Help, &params, clap.parsers.default)) !FilePaths {
const rom_path = romPath(result);