From 79514b0cd0b00613818b6b88169e8ac1c9eedcf5 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Tue, 23 May 2023 03:06:27 -0500 Subject: [PATCH] fix(input): make use of atomic rmw intrinsics when handling input --- src/core/bus/io.zig | 21 ++++++++++---------- src/platform.zig | 47 +++++++++++++++++++++++---------------------- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/core/bus/io.zig b/src/core/bus/io.zig index 2cbbb32..221f128 100644 --- a/src/core/bus/io.zig +++ b/src/core/bus/io.zig @@ -96,7 +96,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.load(.Monotonic).raw, + 0x0400_0130 => bus.io.keyinput.load(.Monotonic), // Serial Communication 2 0x0400_0134 => util.io.read.todo(log, "Read {} from RCNT", .{T}), @@ -366,7 +366,7 @@ const InterruptEnable = extern union { /// Read Only /// 0 = Pressed, 1 = Released -const KeyInput = extern union { +pub const KeyInput = extern union { a: Bit(u16, 0), b: Bit(u16, 1), select: Bit(u16, 2), @@ -390,18 +390,19 @@ const AtomicKeyInput = struct { return .{ .inner = value }; } - pub inline fn load(self: *const Self, comptime ordering: Ordering) KeyInput { - return .{ .raw = switch (ordering) { + pub inline fn load(self: *const Self, comptime ordering: Ordering) u16 { + return 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), - } + pub inline fn fetchOr(self: *Self, value: u16, comptime ordering: Ordering) void { + _ = @atomicRmw(u16, &self.inner.raw, .Or, value, ordering); + } + + pub inline fn fetchAnd(self: *Self, value: u16, comptime ordering: Ordering) void { + _ = @atomicRmw(u16, &self.inner.raw, .And, value, ordering); } }; diff --git a/src/platform.zig b/src/platform.zig index 6a5ee6b..d034ad7 100644 --- a/src/platform.zig +++ b/src/platform.zig @@ -12,6 +12,7 @@ const Arm7tdmi = @import("core/cpu.zig").Arm7tdmi; const Scheduler = @import("core/scheduler.zig").Scheduler; const FpsTracker = @import("util.zig").FpsTracker; const TwoWayChannel = @import("zba-util").TwoWayChannel; +const KeyInput = @import("core/bus/io.zig").KeyInput; const gba_width = @import("core/ppu.zig").width; const gba_height = @import("core/ppu.zig").height; @@ -136,28 +137,7 @@ pub const Gui = struct { SDL.SDL_KEYDOWN => { // TODO: Make use of compare_and_xor? const key_code = event.key.keysym.sym; - var keyinput = cpu.bus.io.keyinput.load(.Monotonic); - - switch (key_code) { - 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 => { - // TODO: Make use of compare_and_xor? - const key_code = event.key.keysym.sym; - var keyinput = cpu.bus.io.keyinput.load(.Monotonic); + var keyinput: KeyInput = .{ .raw = 0x0000 }; switch (key_code) { SDL.SDLK_UP => keyinput.up.set(), @@ -173,7 +153,28 @@ pub const Gui = struct { else => {}, } - cpu.bus.io.keyinput.store(keyinput.raw, .Monotonic); + cpu.bus.io.keyinput.fetchAnd(~keyinput.raw, .Monotonic); + }, + SDL.SDL_KEYUP => { + // TODO: Make use of compare_and_xor? + const key_code = event.key.keysym.sym; + var keyinput: KeyInput = .{ .raw = 0x0000 }; + + switch (key_code) { + 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(), + else => {}, + } + + cpu.bus.io.keyinput.fetchOr(keyinput.raw, .Monotonic); }, SDL.SDL_WINDOWEVENT => { if (event.window.event == SDL.SDL_WINDOWEVENT_RESIZED) {