From 32e54c67bf307bb7194aa7bc50f066846a78634b Mon Sep 17 00:00:00 2001 From: paoda Date: Wed, 14 Feb 2024 13:25:24 -0600 Subject: [PATCH] feat: revamp controls, add support for X and Y buttons --- src/core/io.zig | 54 ++++++++++++++++++++++++++++++++++---------- src/core/nds7/io.zig | 4 +++- src/core/nds9/io.zig | 2 +- src/platform.zig | 27 +++++++++++++++------- 4 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/core/io.zig b/src/core/io.zig index 608aa5f..0a2e0f5 100644 --- a/src/core/io.zig +++ b/src/core/io.zig @@ -14,7 +14,7 @@ pub const Io = struct { wramcnt: WramCnt = .{ .raw = 0x00 }, // Read Only - keyinput: AtomicKeyInput = .{}, + input: Input = .{}, }; fn warn(comptime format: []const u8, args: anytype) u0 { @@ -413,24 +413,54 @@ pub const KeyInput = extern union { raw: u16, }; -const AtomicKeyInput = struct { - const Self = @This(); +pub const ExtKeyIn = extern union { + x: Bit(u16, 0), + y: Bit(u16, 1), + debug: Bit(u16, 3), + stylus: Bit(u16, 6), + hinge: Bit(u16, 7), + raw: u16, +}; + +const Input = struct { const AtomicOrder = std.builtin.AtomicOrder; + const AtomicRmwOp = std.builtin.AtomicRmwOp; - inner: KeyInput = .{ .raw = 0x03FF }, + inner: u32 = 0x007F_03FF, - pub inline fn load(self: *const Self, comptime order: AtomicOrder) u16 { - return switch (order) { - .AcqRel, .Release => @compileError("not supported for atomic loads"), - else => @atomicLoad(u16, &self.inner.raw, order), + pub inline fn keyinput(self: *const Input) KeyInput { + const value = @atomicLoad(u32, &self.inner, .Monotonic); + return .{ .raw = @truncate(value) }; + } + + pub inline fn set_keyinput(self: *Input, comptime op: AtomicRmwOp, input: KeyInput) void { + const msked = switch (op) { + .And => 0xFFFF_FFFF & @as(u32, input.raw), + .Or => 0x0000_0000 | @as(u32, input.raw), + else => @compileError("not supported"), }; + + _ = @atomicRmw(u32, &self.inner, op, msked, .Monotonic); } - pub inline fn fetchOr(self: *Self, value: u16, comptime order: AtomicOrder) void { - _ = @atomicRmw(u16, &self.inner.raw, .Or, value, order); + pub inline fn extkeyin(self: *const Input) ExtKeyIn { + const value = @atomicLoad(u32, &self.inner, .Monotonic); + const shifted: u16 = @truncate(value >> 16); + + return .{ .raw = shifted | 0b00110100 }; // bits 2, 4, 5 are always set } - pub inline fn fetchAnd(self: *Self, value: u16, comptime order: AtomicOrder) void { - _ = @atomicRmw(u16, &self.inner.raw, .And, value, order); + pub inline fn set_extkeyin(self: *Input, comptime op: AtomicRmwOp, input: ExtKeyIn) void { + const msked = switch (op) { + .And => 0xFFFF_FFFF & (@as(u32, ~input.raw) << 16), + .Or => 0x0000_0000 | (@as(u32, input.raw) << 16), + else => @compileError("not supported"), + }; + + _ = @atomicRmw(u32, &self.inner, op, msked, .Monotonic); + } + + pub inline fn set(self: *Input, comptime op: AtomicRmwOp, value: u32) void { + _ = @atomicRmw(u32, &self.inner, op, value, .Monotonic); } }; diff --git a/src/core/nds7/io.zig b/src/core/nds7/io.zig index d1d0a2e..1b21810 100644 --- a/src/core/nds7/io.zig +++ b/src/core/nds7/io.zig @@ -75,7 +75,9 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T { // Timers 0x0400_0100...0x0400_010E => warn("TODO: impl timer", .{}), - 0x0400_0130 => bus.io.shr.keyinput.load(.Monotonic), + 0x0400_0130 => bus.io.shr.input.keyinput().raw, + 0x0400_0136 => bus.io.shr.input.extkeyin().raw, + 0x0400_0180 => @truncate(bus.io.shr.ipc._nds7.sync.raw), 0x0400_0184 => @truncate(bus.io.shr.ipc._nds7.cnt.raw), else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }), diff --git a/src/core/nds9/io.zig b/src/core/nds9/io.zig index e3cb2d9..9000ddc 100644 --- a/src/core/nds9/io.zig +++ b/src/core/nds9/io.zig @@ -95,7 +95,7 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T { 0x0400_0100...0x0400_010E => warn("TODO: impl timer", .{}), 0x0400_0004 => bus.ppu.io.nds9.dispstat.raw, - 0x0400_0130 => bus.io.shr.keyinput.load(.Monotonic), + 0x0400_0130 => bus.io.shr.input.keyinput().raw, 0x0400_0180 => @truncate(bus.io.shr.ipc._nds9.sync.raw), 0x0400_0184 => @truncate(bus.io.shr.ipc._nds9.cnt.raw), diff --git a/src/platform.zig b/src/platform.zig index 6a82b12..91284e8 100644 --- a/src/platform.zig +++ b/src/platform.zig @@ -9,6 +9,7 @@ const emu = @import("core/emu.zig"); const System = @import("core/emu.zig").System; const KeyInput = @import("core/io.zig").KeyInput; +const ExtKeyIn = @import("core/io.zig").ExtKeyIn; const Scheduler = @import("core/Scheduler.zig"); const Allocator = std.mem.Allocator; @@ -125,44 +126,54 @@ pub const Ui = struct { SDL.SDL_KEYDOWN => { // TODO: Make use of compare_and_xor? const key_code = event.key.keysym.sym; + var keyinput: KeyInput = .{ .raw = 0x0000 }; + var extkeyin: ExtKeyIn = .{ .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_c => keyinput.a.set(), + SDL.SDLK_x => keyinput.b.set(), + SDL.SDLK_d => extkeyin.x.set(), + SDL.SDLK_s => extkeyin.y.set(), SDL.SDLK_a => keyinput.shoulder_l.set(), - SDL.SDLK_s => keyinput.shoulder_r.set(), + SDL.SDLK_f => keyinput.shoulder_r.set(), SDL.SDLK_RETURN => keyinput.start.set(), SDL.SDLK_RSHIFT => keyinput.select.set(), else => {}, } - system.bus9.io.shr.keyinput.fetchAnd(~keyinput.raw, .Monotonic); + const input = (@as(u32, extkeyin.raw) << 16) | keyinput.raw; + system.bus9.io.shr.input.set(.And, ~input); }, SDL.SDL_KEYUP => { // TODO: Make use of compare_and_xor? const key_code = event.key.keysym.sym; + var keyinput: KeyInput = .{ .raw = 0x0000 }; + var extkeyin: ExtKeyIn = .{ .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_c => keyinput.a.set(), + SDL.SDLK_x => keyinput.b.set(), + SDL.SDLK_d => extkeyin.x.set(), + SDL.SDLK_s => extkeyin.y.set(), SDL.SDLK_a => keyinput.shoulder_l.set(), - SDL.SDLK_s => keyinput.shoulder_r.set(), + SDL.SDLK_f => keyinput.shoulder_r.set(), SDL.SDLK_RETURN => keyinput.start.set(), SDL.SDLK_RSHIFT => keyinput.select.set(), else => {}, } - system.bus9.io.shr.keyinput.fetchOr(keyinput.raw, .Monotonic); + const input = (@as(u32, extkeyin.raw) << 16) | keyinput.raw; + system.bus9.io.shr.input.set(.Or, input); }, else => {}, }