From 26db340077185cda94cc88717c68a250db17fa63 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Wed, 30 Nov 2022 00:42:20 -0400 Subject: [PATCH] fix(input): implement atomic for KeyInput --- src/core/bus/io.zig | 31 ++++++++++++++++++++--- src/platform.zig | 60 +++++++++++++++++++++------------------------ 2 files changed, 56 insertions(+), 35 deletions(-) diff --git a/src/core/bus/io.zig b/src/core/bus/io.zig index 24ff81a..2a89b66 100644 --- a/src/core/bus/io.zig +++ b/src/core/bus/io.zig @@ -24,14 +24,14 @@ pub const Io = struct { postflg: PostFlag, waitcnt: WaitControl, haltcnt: HaltControl, - keyinput: KeyInput, + keyinput: AtomicKeyInput, pub fn init() Self { return .{ .ime = false, .ie = .{ .raw = 0x0000 }, .irq = .{ .raw = 0x0000 }, - .keyinput = .{ .raw = 0x03FF }, + .keyinput = AtomicKeyInput.init(.{ .raw = 0x03FF }), .waitcnt = .{ .raw = 0x0000_0000 }, // Bit 15 == 0 for GBA .postflg = .FirstBoot, .haltcnt = .Execute, @@ -92,7 +92,7 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T { 0x0400_0128 => util.io.read.todo(log, "Read {} from SIOCNT", .{T}), // Keypad Input - 0x0400_0130 => bus.io.keyinput.raw, + 0x0400_0130 => bus.io.keyinput.load(.Monotonic).raw, // Serial Communication 2 0x0400_0134 => util.io.read.todo(log, "Read {} from RCNT", .{T}), @@ -376,6 +376,31 @@ const KeyInput = extern union { raw: u16, }; +const AtomicKeyInput = struct { + const Self = @This(); + const Ordering = std.atomic.Ordering; + + inner: KeyInput, + + pub fn init(value: KeyInput) Self { + return .{ .inner = value }; + } + + pub inline fn load(self: *const Self, comptime ordering: Ordering) KeyInput { + return .{ .raw = switch (ordering) { + .AcqRel, .Release => @compileError("not supported for atomic loads"), + else => @atomicLoad(u16, &self.inner.raw, ordering), + } }; + } + + pub inline fn store(self: *Self, value: u16, comptime ordering: Ordering) void { + switch (ordering) { + .AcqRel, .Acquire => @compileError("not supported for atomic stores"), + else => @atomicStore(u16, &self.inner.raw, value, ordering), + } + } +}; + // Read / Write pub const BackgroundControl = extern union { priority: Bitfield(u16, 0, 2), diff --git a/src/platform.zig b/src/platform.zig index fb598f9..c5adb8d 100644 --- a/src/platform.zig +++ b/src/platform.zig @@ -180,54 +180,50 @@ pub const Gui = struct { switch (event.type) { SDL.SDL_QUIT => break :emu_loop, SDL.SDL_KEYDOWN => { - const io = &cpu.bus.io; const key_code = event.key.keysym.sym; + var keyinput = cpu.bus.io.keyinput.load(.Monotonic); switch (key_code) { - SDL.SDLK_UP => io.keyinput.up.unset(), - SDL.SDLK_DOWN => io.keyinput.down.unset(), - SDL.SDLK_LEFT => io.keyinput.left.unset(), - SDL.SDLK_RIGHT => io.keyinput.right.unset(), - SDL.SDLK_x => io.keyinput.a.unset(), - SDL.SDLK_z => io.keyinput.b.unset(), - SDL.SDLK_a => io.keyinput.shoulder_l.unset(), - SDL.SDLK_s => io.keyinput.shoulder_r.unset(), - SDL.SDLK_RETURN => io.keyinput.start.unset(), - SDL.SDLK_RSHIFT => io.keyinput.select.unset(), + SDL.SDLK_UP => keyinput.up.unset(), + SDL.SDLK_DOWN => keyinput.down.unset(), + SDL.SDLK_LEFT => keyinput.left.unset(), + SDL.SDLK_RIGHT => keyinput.right.unset(), + SDL.SDLK_x => keyinput.a.unset(), + SDL.SDLK_z => keyinput.b.unset(), + SDL.SDLK_a => keyinput.shoulder_l.unset(), + SDL.SDLK_s => keyinput.shoulder_r.unset(), + SDL.SDLK_RETURN => keyinput.start.unset(), + SDL.SDLK_RSHIFT => keyinput.select.unset(), else => {}, } + + cpu.bus.io.keyinput.store(keyinput.raw, .Monotonic); }, SDL.SDL_KEYUP => { - const io = &cpu.bus.io; const key_code = event.key.keysym.sym; + var keyinput = cpu.bus.io.keyinput.load(.Monotonic); switch (key_code) { - SDL.SDLK_UP => io.keyinput.up.set(), - SDL.SDLK_DOWN => io.keyinput.down.set(), - SDL.SDLK_LEFT => io.keyinput.left.set(), - SDL.SDLK_RIGHT => io.keyinput.right.set(), - SDL.SDLK_x => io.keyinput.a.set(), - SDL.SDLK_z => io.keyinput.b.set(), - SDL.SDLK_a => io.keyinput.shoulder_l.set(), - SDL.SDLK_s => io.keyinput.shoulder_r.set(), - SDL.SDLK_RETURN => io.keyinput.start.set(), - SDL.SDLK_RSHIFT => io.keyinput.select.set(), + SDL.SDLK_UP => keyinput.up.set(), + SDL.SDLK_DOWN => keyinput.down.set(), + SDL.SDLK_LEFT => keyinput.left.set(), + SDL.SDLK_RIGHT => keyinput.right.set(), + SDL.SDLK_x => keyinput.a.set(), + SDL.SDLK_z => keyinput.b.set(), + SDL.SDLK_a => keyinput.shoulder_l.set(), + SDL.SDLK_s => keyinput.shoulder_r.set(), + SDL.SDLK_RETURN => keyinput.start.set(), + SDL.SDLK_RSHIFT => keyinput.select.set(), SDL.SDLK_i => { comptime std.debug.assert(sample_format == SDL.AUDIO_U16); log.err("Sample Count: {}", .{@intCast(u32, SDL.SDL_AudioStreamAvailable(cpu.bus.apu.stream)) / (2 * @sizeOf(u16))}); }, - SDL.SDLK_j => log.err("Scheduler Capacity: {} | Scheduler Event Count: {}", .{ scheduler.queue.capacity(), scheduler.queue.count() }), - SDL.SDLK_k => { - // Dump IWRAM to file - log.info("PC: 0x{X:0>8}", .{cpu.r[15]}); - log.info("LR: 0x{X:0>8}", .{cpu.r[14]}); - // const iwram_file = try std.fs.cwd().createFile("iwram.bin", .{}); - // defer iwram_file.close(); - - // try iwram_file.writeAll(cpu.bus.iwram.buf); - }, + // SDL.SDLK_j => log.err("Scheduler Capacity: {} | Scheduler Event Count: {}", .{ scheduler.queue.capacity(), scheduler.queue.count() }), + SDL.SDLK_k => {}, else => {}, } + + cpu.bus.io.keyinput.store(keyinput.raw, .Monotonic); }, else => {}, }