Implement a GDBSTUB Server #6
 Submodule lib/zba-gdbstub updated: c1158b547e...6d6a109a08
									
								
							| @@ -986,8 +986,7 @@ pub const Ppu = struct { | ||||
|             cpu.handleInterrupt(); | ||||
|         } | ||||
|  | ||||
|         // See if HBlank DMA is present and not enabled | ||||
|  | ||||
|         // If we're not also in VBlank, attempt to run any pending DMA Reqs | ||||
|         if (!self.dispstat.vblank.read()) | ||||
|             dma.onBlanking(cpu.bus, .HBlank); | ||||
|  | ||||
|   | ||||
							
								
								
									
										47
									
								
								src/main.zig
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								src/main.zig
									
									
									
									
									
								
							| @@ -4,14 +4,17 @@ const known_folders = @import("known_folders"); | ||||
| const clap = @import("clap"); | ||||
|  | ||||
| const config = @import("config.zig"); | ||||
| const emu = @import("core/emu.zig"); | ||||
|  | ||||
| const Gui = @import("platform.zig").Gui; | ||||
| const Bus = @import("core/Bus.zig"); | ||||
| const Arm7tdmi = @import("core/cpu.zig").Arm7tdmi; | ||||
| const Scheduler = @import("core/scheduler.zig").Scheduler; | ||||
| const FilePaths = @import("util.zig").FilePaths; | ||||
|  | ||||
| const FpsTracker = @import("util.zig").FpsTracker; | ||||
| const Allocator = std.mem.Allocator; | ||||
| const Atomic = std.atomic.Atomic; | ||||
|  | ||||
| const log = std.log.scoped(.Cli); | ||||
| const width = @import("core/ppu.zig").width; | ||||
| const height = @import("core/ppu.zig").height; | ||||
| @@ -88,6 +91,10 @@ pub fn main() void { | ||||
|         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) { | ||||
|         const Server = @import("gdbstub").Server; | ||||
|         const EmuThing = @import("core/emu.zig").EmuThing; | ||||
| @@ -96,29 +103,33 @@ pub fn main() void { | ||||
|         var emulator = wrapper.interface(allocator); | ||||
|         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", .{}); | ||||
|  | ||||
|         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(); | ||||
|         log.info("Starting GDB Server Thread", .{}); | ||||
|  | ||||
|         gui.run(&cpu, &scheduler) catch |e| exitln("failed to run gui thread: {}", .{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 { | ||||
|         var tracker = FpsTracker.init(); | ||||
|  | ||||
|         const thread = std.Thread.spawn(.{}, emu.run, .{ &quit, &scheduler, &cpu, &tracker }) catch |e| exitln("emu thread panicked: {}", .{e}); | ||||
|         defer thread.join(); | ||||
|  | ||||
|         gui.run(.{ | ||||
|             .cpu = &cpu, | ||||
|             .scheduler = &scheduler, | ||||
|             .tracker = &tracker, | ||||
|             .quit = &quit, | ||||
|         }) catch |e| exitln("main thread panicked: {}", .{e}); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -154,9 +154,17 @@ pub const Gui = struct { | ||||
|         return tex_id; | ||||
|     } | ||||
|  | ||||
|     pub fn run(self: *Self, cpu: *Arm7tdmi, scheduler: *Scheduler) !void { | ||||
|         var quit = std.atomic.Atomic(bool).init(false); | ||||
|         var tracker = FpsTracker.init(); | ||||
|     const RunOptions = struct { | ||||
|         quit: *std.atomic.Atomic(bool), | ||||
|         tracker: ?*FpsTracker = null, | ||||
|         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(); | ||||
|         defer { | ||||
| @@ -169,13 +177,15 @@ pub const Gui = struct { | ||||
|         const tex_id = Self.generateTexture(cpu.bus.ppu.framebuf.get(.Renderer)); | ||||
|         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; | ||||
|  | ||||
|         emu_loop: while (true) { | ||||
|             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) { | ||||
|                 switch (event.type) { | ||||
|                     SDL.SDL_QUIT => break :emu_loop, | ||||
| @@ -238,8 +248,10 @@ pub const Gui = struct { | ||||
|             gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, null); | ||||
|             SDL.SDL_GL_SwapWindow(self.window); | ||||
|  | ||||
|             const dyn_title = std.fmt.bufPrintZ(&title_buf, "ZBA | {s} [Emu: {}fps] ", .{ self.title, tracker.value() }) catch unreachable; | ||||
|             SDL.SDL_SetWindowTitle(self.window, dyn_title.ptr); | ||||
|             if (tracker) |t| { | ||||
|                 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); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         quit.store(true, .Monotonic); // Terminate Emulator Thread | ||||
|   | ||||
		Reference in New Issue
	
	Block a user