fix(input): implement atomic for KeyInput
This commit is contained in:
		| @@ -24,14 +24,14 @@ pub const Io = struct { | |||||||
|     postflg: PostFlag, |     postflg: PostFlag, | ||||||
|     waitcnt: WaitControl, |     waitcnt: WaitControl, | ||||||
|     haltcnt: HaltControl, |     haltcnt: HaltControl, | ||||||
|     keyinput: KeyInput, |     keyinput: AtomicKeyInput, | ||||||
|  |  | ||||||
|     pub fn init() Self { |     pub fn init() Self { | ||||||
|         return .{ |         return .{ | ||||||
|             .ime = false, |             .ime = false, | ||||||
|             .ie = .{ .raw = 0x0000 }, |             .ie = .{ .raw = 0x0000 }, | ||||||
|             .irq = .{ .raw = 0x0000 }, |             .irq = .{ .raw = 0x0000 }, | ||||||
|             .keyinput = .{ .raw = 0x03FF }, |             .keyinput = AtomicKeyInput.init(.{ .raw = 0x03FF }), | ||||||
|             .waitcnt = .{ .raw = 0x0000_0000 }, // Bit 15 == 0 for GBA |             .waitcnt = .{ .raw = 0x0000_0000 }, // Bit 15 == 0 for GBA | ||||||
|             .postflg = .FirstBoot, |             .postflg = .FirstBoot, | ||||||
|             .haltcnt = .Execute, |             .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}), |             0x0400_0128 => util.io.read.todo(log, "Read {} from SIOCNT", .{T}), | ||||||
|  |  | ||||||
|             // Keypad Input |             // Keypad Input | ||||||
|             0x0400_0130 => bus.io.keyinput.raw, |             0x0400_0130 => bus.io.keyinput.load(.Monotonic).raw, | ||||||
|  |  | ||||||
|             // 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}), | ||||||
| @@ -376,6 +376,31 @@ const KeyInput = extern union { | |||||||
|     raw: u16, |     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 | // Read / Write | ||||||
| pub const BackgroundControl = extern union { | pub const BackgroundControl = extern union { | ||||||
|     priority: Bitfield(u16, 0, 2), |     priority: Bitfield(u16, 0, 2), | ||||||
|   | |||||||
| @@ -180,54 +180,50 @@ pub const Gui = struct { | |||||||
|                 switch (event.type) { |                 switch (event.type) { | ||||||
|                     SDL.SDL_QUIT => break :emu_loop, |                     SDL.SDL_QUIT => break :emu_loop, | ||||||
|                     SDL.SDL_KEYDOWN => { |                     SDL.SDL_KEYDOWN => { | ||||||
|                         const io = &cpu.bus.io; |  | ||||||
|                         const key_code = event.key.keysym.sym; |                         const key_code = event.key.keysym.sym; | ||||||
|  |                         var keyinput = cpu.bus.io.keyinput.load(.Monotonic); | ||||||
|  |  | ||||||
|                         switch (key_code) { |                         switch (key_code) { | ||||||
|                             SDL.SDLK_UP => io.keyinput.up.unset(), |                             SDL.SDLK_UP => keyinput.up.unset(), | ||||||
|                             SDL.SDLK_DOWN => io.keyinput.down.unset(), |                             SDL.SDLK_DOWN => keyinput.down.unset(), | ||||||
|                             SDL.SDLK_LEFT => io.keyinput.left.unset(), |                             SDL.SDLK_LEFT => keyinput.left.unset(), | ||||||
|                             SDL.SDLK_RIGHT => io.keyinput.right.unset(), |                             SDL.SDLK_RIGHT => keyinput.right.unset(), | ||||||
|                             SDL.SDLK_x => io.keyinput.a.unset(), |                             SDL.SDLK_x => keyinput.a.unset(), | ||||||
|                             SDL.SDLK_z => io.keyinput.b.unset(), |                             SDL.SDLK_z => keyinput.b.unset(), | ||||||
|                             SDL.SDLK_a => io.keyinput.shoulder_l.unset(), |                             SDL.SDLK_a => keyinput.shoulder_l.unset(), | ||||||
|                             SDL.SDLK_s => io.keyinput.shoulder_r.unset(), |                             SDL.SDLK_s => keyinput.shoulder_r.unset(), | ||||||
|                             SDL.SDLK_RETURN => io.keyinput.start.unset(), |                             SDL.SDLK_RETURN => keyinput.start.unset(), | ||||||
|                             SDL.SDLK_RSHIFT => io.keyinput.select.unset(), |                             SDL.SDLK_RSHIFT => keyinput.select.unset(), | ||||||
|                             else => {}, |                             else => {}, | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|  |                         cpu.bus.io.keyinput.store(keyinput.raw, .Monotonic); | ||||||
|                     }, |                     }, | ||||||
|                     SDL.SDL_KEYUP => { |                     SDL.SDL_KEYUP => { | ||||||
|                         const io = &cpu.bus.io; |  | ||||||
|                         const key_code = event.key.keysym.sym; |                         const key_code = event.key.keysym.sym; | ||||||
|  |                         var keyinput = cpu.bus.io.keyinput.load(.Monotonic); | ||||||
|  |  | ||||||
|                         switch (key_code) { |                         switch (key_code) { | ||||||
|                             SDL.SDLK_UP => io.keyinput.up.set(), |                             SDL.SDLK_UP => keyinput.up.set(), | ||||||
|                             SDL.SDLK_DOWN => io.keyinput.down.set(), |                             SDL.SDLK_DOWN => keyinput.down.set(), | ||||||
|                             SDL.SDLK_LEFT => io.keyinput.left.set(), |                             SDL.SDLK_LEFT => keyinput.left.set(), | ||||||
|                             SDL.SDLK_RIGHT => io.keyinput.right.set(), |                             SDL.SDLK_RIGHT => keyinput.right.set(), | ||||||
|                             SDL.SDLK_x => io.keyinput.a.set(), |                             SDL.SDLK_x => keyinput.a.set(), | ||||||
|                             SDL.SDLK_z => io.keyinput.b.set(), |                             SDL.SDLK_z => keyinput.b.set(), | ||||||
|                             SDL.SDLK_a => io.keyinput.shoulder_l.set(), |                             SDL.SDLK_a => keyinput.shoulder_l.set(), | ||||||
|                             SDL.SDLK_s => io.keyinput.shoulder_r.set(), |                             SDL.SDLK_s => keyinput.shoulder_r.set(), | ||||||
|                             SDL.SDLK_RETURN => io.keyinput.start.set(), |                             SDL.SDLK_RETURN => keyinput.start.set(), | ||||||
|                             SDL.SDLK_RSHIFT => io.keyinput.select.set(), |                             SDL.SDLK_RSHIFT => keyinput.select.set(), | ||||||
|                             SDL.SDLK_i => { |                             SDL.SDLK_i => { | ||||||
|                                 comptime std.debug.assert(sample_format == SDL.AUDIO_U16); |                                 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))}); |                                 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_j => log.err("Scheduler Capacity: {} | Scheduler Event Count: {}", .{ scheduler.queue.capacity(), scheduler.queue.count() }), | ||||||
|                             SDL.SDLK_k => { |                             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); |  | ||||||
|                             }, |  | ||||||
|                             else => {}, |                             else => {}, | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|  |                         cpu.bus.io.keyinput.store(keyinput.raw, .Monotonic); | ||||||
|                     }, |                     }, | ||||||
|                     else => {}, |                     else => {}, | ||||||
|                 } |                 } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user