Compare commits
No commits in common. "94243711df74578a090a9cf0a2ee44e0f45e5db3" and "7b83bba1c1d1c0d04f692b789f45be7a8cdc3eb2" have entirely different histories.
94243711df
...
7b83bba1c1
|
@ -1 +1 @@
|
||||||
Subproject commit 6d6a109a086361d300da675db8445ede74be58f6
|
Subproject commit c1158b547e54d82f5ac7aba4cf372c6e061b1eab
|
|
@ -200,18 +200,15 @@ pub const EmuThing = struct {
|
||||||
const cpu = self.cpu;
|
const cpu = self.cpu;
|
||||||
const sched = self.scheduler;
|
const sched = self.scheduler;
|
||||||
|
|
||||||
// Is true when we have executed one (1) instruction
|
|
||||||
var did_step: bool = false;
|
|
||||||
|
|
||||||
// TODO: How can I make it easier to keep this in lock-step with runFrame?
|
// TODO: How can I make it easier to keep this in lock-step with runFrame?
|
||||||
while (!did_step) {
|
while (true) {
|
||||||
if (!cpu.stepDmaTransfer()) {
|
if (!cpu.stepDmaTransfer()) {
|
||||||
if (cpu.isHalted()) {
|
if (cpu.isHalted()) {
|
||||||
// Fast-forward to next Event
|
// Fast-forward to next Event
|
||||||
sched.tick = sched.queue.peek().?.tick;
|
sched.tick = sched.queue.peek().?.tick;
|
||||||
} else {
|
} else {
|
||||||
cpu.step();
|
cpu.step();
|
||||||
did_step = true;
|
break; // this function won't return until we've actually stepped once
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -990,7 +990,8 @@ pub const Ppu = struct {
|
||||||
cpu.handleInterrupt();
|
cpu.handleInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're not also in VBlank, attempt to run any pending DMA Reqs
|
// See if HBlank DMA is present and not enabled
|
||||||
|
|
||||||
if (!self.dispstat.vblank.read())
|
if (!self.dispstat.vblank.read())
|
||||||
dma.onBlanking(cpu.bus, .HBlank);
|
dma.onBlanking(cpu.bus, .HBlank);
|
||||||
|
|
||||||
|
|
45
src/main.zig
45
src/main.zig
|
@ -4,17 +4,14 @@ const known_folders = @import("known_folders");
|
||||||
const clap = @import("clap");
|
const clap = @import("clap");
|
||||||
|
|
||||||
const config = @import("config.zig");
|
const config = @import("config.zig");
|
||||||
const emu = @import("core/emu.zig");
|
|
||||||
|
|
||||||
const Gui = @import("platform.zig").Gui;
|
const Gui = @import("platform.zig").Gui;
|
||||||
const Bus = @import("core/Bus.zig");
|
const Bus = @import("core/Bus.zig");
|
||||||
const Arm7tdmi = @import("core/cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("core/cpu.zig").Arm7tdmi;
|
||||||
const Scheduler = @import("core/scheduler.zig").Scheduler;
|
const Scheduler = @import("core/scheduler.zig").Scheduler;
|
||||||
const FilePaths = @import("util.zig").FilePaths;
|
const FilePaths = @import("util.zig").FilePaths;
|
||||||
const FpsTracker = @import("util.zig").FpsTracker;
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
const Atomic = std.atomic.Atomic;
|
|
||||||
|
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
const log = std.log.scoped(.Cli);
|
const log = std.log.scoped(.Cli);
|
||||||
const width = @import("core/ppu.zig").width;
|
const width = @import("core/ppu.zig").width;
|
||||||
const height = @import("core/ppu.zig").height;
|
const height = @import("core/ppu.zig").height;
|
||||||
|
@ -91,10 +88,6 @@ pub fn main() void {
|
||||||
cpu.fastBoot();
|
cpu.fastBoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
var quit = Atomic(bool).init(false);
|
|
||||||
var gui = Gui.init(&bus.pak.title, &bus.apu, width, height) catch |e| exitln("failed to init gui: {}", .{e});
|
|
||||||
defer gui.deinit();
|
|
||||||
|
|
||||||
if (result.args.gdb) {
|
if (result.args.gdb) {
|
||||||
const Server = @import("gdbstub").Server;
|
const Server = @import("gdbstub").Server;
|
||||||
const EmuThing = @import("core/emu.zig").EmuThing;
|
const EmuThing = @import("core/emu.zig").EmuThing;
|
||||||
|
@ -103,33 +96,29 @@ pub fn main() void {
|
||||||
var emulator = wrapper.interface(allocator);
|
var emulator = wrapper.interface(allocator);
|
||||||
defer emulator.deinit();
|
defer emulator.deinit();
|
||||||
|
|
||||||
|
{
|
||||||
|
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", .{});
|
log.info("Ready to connect", .{});
|
||||||
|
|
||||||
var server = Server.init(emulator) catch |e| exitln("failed to init gdb server: {}", .{e});
|
var server = Server.init(emulator) catch |e| exitln("failed to init gdb server: {}", .{e});
|
||||||
defer server.deinit(allocator);
|
defer server.deinit(allocator);
|
||||||
|
|
||||||
log.info("Starting GDB Server Thread", .{});
|
server.run(allocator) catch |e| exitln("gdb server crashed: {}", .{e});
|
||||||
|
|
||||||
const thread = std.Thread.spawn(.{}, Server.run, .{ &server, allocator, &quit }) catch |e| exitln("gdb server thread crashed: {}", .{e});
|
|
||||||
defer thread.join();
|
|
||||||
|
|
||||||
gui.run(.{
|
|
||||||
.cpu = &cpu,
|
|
||||||
.scheduler = &scheduler,
|
|
||||||
.quit = &quit,
|
|
||||||
}) catch |e| exitln("main thread panicked: {}", .{e});
|
|
||||||
} else {
|
} else {
|
||||||
var tracker = FpsTracker.init();
|
var gui = Gui.init(&bus.pak.title, &bus.apu, width, height) catch |e| exitln("failed to init gui: {}", .{e});
|
||||||
|
defer gui.deinit();
|
||||||
|
|
||||||
const thread = std.Thread.spawn(.{}, emu.run, .{ &quit, &scheduler, &cpu, &tracker }) catch |e| exitln("emu thread panicked: {}", .{e});
|
gui.run(&cpu, &scheduler) catch |e| exitln("failed to run gui thread: {}", .{e});
|
||||||
defer thread.join();
|
|
||||||
|
|
||||||
gui.run(.{
|
|
||||||
.cpu = &cpu,
|
|
||||||
.scheduler = &scheduler,
|
|
||||||
.tracker = &tracker,
|
|
||||||
.quit = &quit,
|
|
||||||
}) catch |e| exitln("main thread panicked: {}", .{e});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,17 +154,9 @@ pub const Gui = struct {
|
||||||
return tex_id;
|
return tex_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RunOptions = struct {
|
pub fn run(self: *Self, cpu: *Arm7tdmi, scheduler: *Scheduler) !void {
|
||||||
quit: *std.atomic.Atomic(bool),
|
var quit = std.atomic.Atomic(bool).init(false);
|
||||||
tracker: ?*FpsTracker = null,
|
var tracker = FpsTracker.init();
|
||||||
cpu: *Arm7tdmi,
|
|
||||||
scheduler: *Scheduler,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn run(self: *Self, opt: RunOptions) !void {
|
|
||||||
const cpu = opt.cpu;
|
|
||||||
const tracker = opt.tracker;
|
|
||||||
const quit = opt.quit;
|
|
||||||
|
|
||||||
var buffer_ids = Self.generateBuffers();
|
var buffer_ids = Self.generateBuffers();
|
||||||
defer {
|
defer {
|
||||||
|
@ -177,15 +169,13 @@ pub const Gui = struct {
|
||||||
const tex_id = Self.generateTexture(cpu.bus.ppu.framebuf.get(.Renderer));
|
const tex_id = Self.generateTexture(cpu.bus.ppu.framebuf.get(.Renderer));
|
||||||
defer gl.deleteTextures(1, &tex_id);
|
defer gl.deleteTextures(1, &tex_id);
|
||||||
|
|
||||||
|
const thread = try std.Thread.spawn(.{}, emu.run, .{ &quit, scheduler, cpu, &tracker });
|
||||||
|
defer thread.join();
|
||||||
|
|
||||||
var title_buf: [0x100]u8 = undefined;
|
var title_buf: [0x100]u8 = undefined;
|
||||||
|
|
||||||
emu_loop: while (true) {
|
emu_loop: while (true) {
|
||||||
var event: SDL.SDL_Event = undefined;
|
var event: SDL.SDL_Event = undefined;
|
||||||
|
|
||||||
// This might be true if the emu is running via a gdbstub server
|
|
||||||
// and the gdb stub exits first
|
|
||||||
if (quit.load(.Monotonic)) break :emu_loop;
|
|
||||||
|
|
||||||
while (SDL.SDL_PollEvent(&event) != 0) {
|
while (SDL.SDL_PollEvent(&event) != 0) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
SDL.SDL_QUIT => break :emu_loop,
|
SDL.SDL_QUIT => break :emu_loop,
|
||||||
|
@ -248,10 +238,8 @@ pub const Gui = struct {
|
||||||
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, null);
|
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, null);
|
||||||
SDL.SDL_GL_SwapWindow(self.window);
|
SDL.SDL_GL_SwapWindow(self.window);
|
||||||
|
|
||||||
if (tracker) |t| {
|
const dyn_title = std.fmt.bufPrintZ(&title_buf, "ZBA | {s} [Emu: {}fps] ", .{ self.title, tracker.value() }) catch unreachable;
|
||||||
const dyn_title = std.fmt.bufPrintZ(&title_buf, "ZBA | {s} [Emu: {}fps] ", .{ self.title, t.value() }) catch unreachable;
|
SDL.SDL_SetWindowTitle(self.window, dyn_title.ptr);
|
||||||
SDL.SDL_SetWindowTitle(self.window, dyn_title.ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quit.store(true, .Monotonic); // Terminate Emulator Thread
|
quit.store(true, .Monotonic); // Terminate Emulator Thread
|
||||||
|
|
Loading…
Reference in New Issue