fix(input): make use of atomic rmw intrinsics when handling input
This commit is contained in:
		| @@ -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); | ||||
|     } | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user