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}), |             0x0400_0128 => util.io.read.todo(log, "Read {} from SIOCNT", .{T}), | ||||||
|  |  | ||||||
|             // Keypad Input |             // Keypad Input | ||||||
|             0x0400_0130 => bus.io.keyinput.load(.Monotonic).raw, |             0x0400_0130 => bus.io.keyinput.load(.Monotonic), | ||||||
|  |  | ||||||
|             // Serial Communication 2 |             // Serial Communication 2 | ||||||
|             0x0400_0134 => util.io.read.todo(log, "Read {} from RCNT", .{T}), |             0x0400_0134 => util.io.read.todo(log, "Read {} from RCNT", .{T}), | ||||||
| @@ -366,7 +366,7 @@ const InterruptEnable = extern union { | |||||||
|  |  | ||||||
| /// Read Only | /// Read Only | ||||||
| /// 0 = Pressed, 1 = Released | /// 0 = Pressed, 1 = Released | ||||||
| const KeyInput = extern union { | pub const KeyInput = extern union { | ||||||
|     a: Bit(u16, 0), |     a: Bit(u16, 0), | ||||||
|     b: Bit(u16, 1), |     b: Bit(u16, 1), | ||||||
|     select: Bit(u16, 2), |     select: Bit(u16, 2), | ||||||
| @@ -390,18 +390,19 @@ const AtomicKeyInput = struct { | |||||||
|         return .{ .inner = value }; |         return .{ .inner = value }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub inline fn load(self: *const Self, comptime ordering: Ordering) KeyInput { |     pub inline fn load(self: *const Self, comptime ordering: Ordering) u16 { | ||||||
|         return .{ .raw = switch (ordering) { |         return switch (ordering) { | ||||||
|             .AcqRel, .Release => @compileError("not supported for atomic loads"), |             .AcqRel, .Release => @compileError("not supported for atomic loads"), | ||||||
|             else => @atomicLoad(u16, &self.inner.raw, ordering), |             else => @atomicLoad(u16, &self.inner.raw, ordering), | ||||||
|         } }; |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub inline fn store(self: *Self, value: u16, comptime ordering: Ordering) void { |     pub inline fn fetchOr(self: *Self, value: u16, comptime ordering: Ordering) void { | ||||||
|         switch (ordering) { |         _ = @atomicRmw(u16, &self.inner.raw, .Or, value, ordering); | ||||||
|             .AcqRel, .Acquire => @compileError("not supported for atomic stores"), |  | ||||||
|             else => @atomicStore(u16, &self.inner.raw, 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 Scheduler = @import("core/scheduler.zig").Scheduler; | ||||||
| const FpsTracker = @import("util.zig").FpsTracker; | const FpsTracker = @import("util.zig").FpsTracker; | ||||||
| const TwoWayChannel = @import("zba-util").TwoWayChannel; | const TwoWayChannel = @import("zba-util").TwoWayChannel; | ||||||
|  | const KeyInput = @import("core/bus/io.zig").KeyInput; | ||||||
|  |  | ||||||
| const gba_width = @import("core/ppu.zig").width; | const gba_width = @import("core/ppu.zig").width; | ||||||
| const gba_height = @import("core/ppu.zig").height; | const gba_height = @import("core/ppu.zig").height; | ||||||
| @@ -136,28 +137,7 @@ pub const Gui = struct { | |||||||
|                     SDL.SDL_KEYDOWN => { |                     SDL.SDL_KEYDOWN => { | ||||||
|                         // TODO: Make use of compare_and_xor? |                         // TODO: Make use of compare_and_xor? | ||||||
|                         const key_code = event.key.keysym.sym; |                         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.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); |  | ||||||
|  |  | ||||||
|                         switch (key_code) { |                         switch (key_code) { | ||||||
|                             SDL.SDLK_UP => keyinput.up.set(), |                             SDL.SDLK_UP => keyinput.up.set(), | ||||||
| @@ -173,7 +153,28 @@ pub const Gui = struct { | |||||||
|                             else => {}, |                             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 => { |                     SDL.SDL_WINDOWEVENT => { | ||||||
|                         if (event.window.event == SDL.SDL_WINDOWEVENT_RESIZED) { |                         if (event.window.event == SDL.SDL_WINDOWEVENT_RESIZED) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user