diff --git a/music/3xosc.flp b/music/3xosc.flp new file mode 100644 index 0000000..bba72b5 Binary files /dev/null and b/music/3xosc.flp differ diff --git a/music/chips/chipbgm.mp3 b/music/chips/chipbgm.mp3 new file mode 100644 index 0000000..910952b Binary files /dev/null and b/music/chips/chipbgm.mp3 differ diff --git a/music/chips/chips.flp b/music/chips/chips.flp new file mode 100644 index 0000000..515f552 Binary files /dev/null and b/music/chips/chips.flp differ diff --git a/rewrite/src/controller.zig b/rewrite/src/controller.zig index c48a4f7..0a5a433 100644 --- a/rewrite/src/controller.zig +++ b/rewrite/src/controller.zig @@ -3,14 +3,14 @@ const fumo = @import("fumostd.zig"); const input = @import("input.zig"); const Axis = struct { - data: f64, + data: f64 = 0, - last_pressed: u64, - last_released: u64, + last_pressed: u64 = 0, + last_released: u64 = 0, - is_down: bool, - is_held: bool, - is_up: bool, + is_down: bool = false, + is_held: bool = false, + is_up: bool = false, }; const Bind = struct { @@ -18,37 +18,37 @@ const Bind = struct { multiplier: f64, }; -const Controller = struct { +pub const Controller = struct { const BindHashMap = fumo.HashMap(*Bind); axes: []Axis, binds: []Bind, - scancode_map: BindHashMap, + code_map: BindHashMap, - pending: [input.IO_BUF_SIZE]*Axis = undefined, + pending: [16]*Axis = undefined, n_pending: usize = 0, pub fn init( - arena: std.heap.ArenaAllocator, + arena: std.mem.Allocator, n_axes: usize, n_binds: usize, - n_scancodes: usize, + n_codes: usize, ) !@This() { const ctrl = @This(){ .axes = try arena.alloc(Axis, n_axes), .binds = try arena.alloc(Bind, n_binds), - .scancode_map = try BindHashMap.init(arena, n_scancodes), + .code_map = try BindHashMap.init(arena, n_codes), }; - @memset(ctrl.axes, 0); + @memset(ctrl.axes, Axis{}); return ctrl; } - pub fn bindScancode(this: *@This(), scancode: usize, bind: usize) !void { - try this.scancode_map.set(scancode, &this.binds[bind]); + pub fn bindCode(this: *@This(), code: usize, bind: usize) !void { + try this.code_map.set(code, &this.binds[bind]); } pub fn bindAxis(this: *@This(), bind: usize, axis: usize, mul: f64) void { @@ -58,29 +58,28 @@ const Controller = struct { }; } - pub fn poll(this: *@This(), record_buffer: fumo.RingBuffer(input.Record, 16)) void { + pub fn poll(this: *@This(), rec_circ: *input.RecordCircle) void { for (this.pending[0..this.n_pending]) |axis| { axis.is_up = false; axis.is_down = false; } - for (record_buffer) |*record| { - if (this.scancode_map.find(record.scancode)) |*bind| { + inline for (rec_circ.read()) |slice| for (slice) |record| { + if (this.code_map.find(record.code)) |bind| { dispatch(bind, record); } - } + }; } fn dispatch(bind: *Bind, record: input.Record) void { bind.axis.data = record.data * bind.multiplier; - if (record.is_down) { - bind.axis.is_down = true; - bind.axis.is_held = true; + bind.axis.is_down = record.data != 0; + bind.axis.is_up = record.data == 0; + + if (record.data != 0) { bind.axis.last_pressed = record.time; } else { - bind.axis.is_up = true; - bind.axis.is_held = false; bind.axis.last_released = record.time; } } diff --git a/rewrite/src/fumostd.zig b/rewrite/src/fumostd.zig index 87f9149..d3d04f2 100644 --- a/rewrite/src/fumostd.zig +++ b/rewrite/src/fumostd.zig @@ -1,12 +1,13 @@ const std = @import("std"); +const AtomicOrder = @import("std").builtin.AtomicOrder; pub fn HashMap(comptime V: type) type { return struct { pub const HashMapError = error{Full}; pub const Bucket = struct { - hash: usize, - value: V, + hash: usize = 0, + value: V = undefined, }; buckets: []Bucket, @@ -17,7 +18,7 @@ pub fn HashMap(comptime V: type) type { .buckets = try allocator.alloc(Bucket, n), }; - @memset(map.buckets, Bucket{ .hash = 0, .value = undefined }); + @memset(map.buckets, Bucket{}); return map; } @@ -78,46 +79,63 @@ pub fn HashMap(comptime V: type) type { }; } -pub fn RingBuffer(comptime T: type, comptime size: comptime_int) type { +pub fn Buffer(comptime T: type, comptime size: comptime_int) type { return struct { array: [size]T = undefined, - read_index: isize = 0, - write_index: isize = 0, + len: usize = 0, + read: usize = 0, - pub fn write(this: *@This(), slice: []T) usize { - const write_limit = @mod(this.read_index - 1, size); - var i: usize = 0; - - while (i < slice.len and this.write_index != write_limit) : ({ - i += 1; - }) { - this.array[this.write_index] = slice[i]; - this.write_index = @mod(this.write_index + 1, size); - } - - return i; + pub fn slice(this: *@This()) []T { + return this.array[this.read..this.len]; } - pub fn read(this: *@This()) struct { []T, []T } { - const contiguous: bool = this.write_index >= this.read_index; - - const upper_1: usize = if (contiguous) this.write_index else size; - const upper_2: usize = if (contiguous) 0 else this.write_index; - - this.read_index = this.write_index; - - return .{ - this.array[this.read_index..upper_1], - this.array[0..upper_2], - }; - } - - pub fn unreadLen(this: @This()) usize { - if (this.write_index >= this.read_index) { - return this.write_index - this.read_index; - } else { - return (size - this.read_index) + this.write_index; - } + pub fn flush(this: *@This()) void { + this.len = 0; + this.read = 0; + } + }; +} + +pub fn CircleBuffer(comptime T: type, comptime size: comptime_int) type { + return struct { + array: [size]T = undefined, + read: usize = 0, + write: usize = 0, + + pub fn write(this: *@This(), slice: []T) usize { + const read_atm: usize = @atomicLoad(usize, &this.read, AtomicOrder.acquire); + const contiguous: bool = this.write < read_atm; + + const a_upper: usize = if (contiguous) read_atm else size; + const b_upper: usize = if (contiguous) 0 else read_atm; + + const region_a: []T = this.array[this.write..a_upper]; + const region_b: []T = this.array[0..b_upper]; + + const slice_a: []T = slice[0..@min(slice.len, region_a.len)]; + const slice_b: []T = slice[slice_a.len..slice.len]; + + @memcpy(region_a, slice_a); + @memcpy(region_b, slice_b); + + const written: usize = @min(slice.len, region_a.len + region_b.len); + @atomicStore(usize, &this.write, (this.write + written) % size, AtomicOrder.release); + return written; + } + + pub fn read(this: *@This()) struct { []T, []T } { + const write_atm: usize = @atomicLoad(usize, &this.write, AtomicOrder.acquire); + const contiguous: bool = this.read < write_atm; + + const a_upper: usize = if (contiguous) write_atm else size; + const b_upper: usize = if (contiguous) 0 else write_atm; + + const region_a: []T = this.array[this.read..a_upper]; + const region_b: []T = this.array[0..b_upper]; + + const read_total: usize = region_a.len + region_b.len; + @atomicStore(usize, &this.read, (this.read + read_total) % size, AtomicOrder.release); + return struct { region_a, region_b }; } }; } diff --git a/rewrite/src/input.zig b/rewrite/src/input.zig index 85451f5..a004a79 100644 --- a/rewrite/src/input.zig +++ b/rewrite/src/input.zig @@ -1,61 +1,67 @@ const std = @import("std"); const fumo = @import("fumostd.zig"); +const platform = @import("platform.zig"); -const IO_BUF_SIZE: usize = 16; -const STR_BUF_SIZE: usize = IO_BUF_SIZE * 4; +pub const RecordCircle = fumo.CircleBuffer(Record, 16); +pub const StringCircle = fumo.CircleBuffer(u8, 16 * 4); -const RecordBuffer = fumo.RingBuffer(Record, IO_BUF_SIZE); -const StringBuffer = fumo.RingBuffer(u8, STR_BUF_SIZE); +pub const RecordBuffer = fumo.Buffer(Record, 16); +pub const StringBuffer = fumo.Buffer(u8, 16 * 4); -const Record = struct { - scancode: usize, +pub const Record = struct { + const Type = enum { axis, joystick }; + + hash: usize, data: f64, - time: u64, + pub fn readAxis(buf: RecordBuffer, code: usize, data: f64) void { + buf.array[buf.len] = Record{ + .hash = hashCode(code, Type.axis), + .data = data, + }; + buf.len += 1; + } - is_down: bool, + pub fn readJoystick(buf: RecordBuffer, code: usize, x: f64, y: f64) void { + buf.array[buf.len] = .{ .code = scancode | Record.joystick_ofs, .data = x }; + buf.array[buf.len + 1] = .{ .code = scancode | Record.joystick_ofs, .data = y }; + buf.len += 2; + } + + fn hashCode(code: usize, code_type: usize) usize { + return code | (code_type << (@bitSizeOf(usize) / 2)); + } }; -const Handle = struct { - records: RecordBuffer, - string: StringBuffer, +pub const Handle = struct { + rec_circ: RecordCircle = .{}, + str_circ: StringCircle = .{}, - thread: std.Thread, - mutex: std.Thread.Mutex = std.Thread.Mutex{}, - read_signal: std.Thread.Condition = std.Thread.Condition{}, + thread: std.Thread = undefined, + signal: std.Thread.Condition = .{}, pub fn init() !Handle { - const handle = Handle{ - .thread = try std.Thread.spawn(.{}, worker, .{}), - }; + var handle = Handle{}; + handle.thread = try std.Thread.spawn(.{}, worker, .{&handle}); return handle; } - fn worker(this: *@This()) void { - var rec_buf: [IO_BUF_SIZE]Record = undefined; - var str_buf: [STR_BUF_SIZE]u8 = undefined; + fn worker(hand: *Handle) !void { + var rec_buf = RecordBuffer{}; + var str_buf = StringBuffer{}; - var n_recs: usize = 0; - var n_str: usize = 0; + while (true) : ({ + rec_buf.flush(); + str_buf.flush(); + }) { + try platform.ReadInput(&rec_buf, &str_buf); - while (true) { - // block platform read in - try platform.ReadInput(&rec_buf, &n_recs, &str_buf, &n_str); - - this.mutex.lock(); - defer this.mutex.unlock(); - - var w_recs: usize = 0; - var w_str: usize = 0; - - while (w_recs < n_recs) : ({ - this.read_signal.wait(&this.mutex); - if (this.records.read_index == this.records.write_index) - continue; + while (rec_buf.read < rec_buf.len) : ({ + hand.signal.wait(&hand.mutex); }) { - w_recs += this.records.write(rec_buf[w_recs..n_recs]); - w_str += this.string.write(str_buf[w_str..n_str]); + rec_buf.read += hand.rec_circ.write(rec_buf.slice()); + str_buf.read += hand.str_circ.write(str_buf.slice()); } } } diff --git a/rewrite/src/main.zig b/rewrite/src/main.zig index 9385434..2091fd6 100644 --- a/rewrite/src/main.zig +++ b/rewrite/src/main.zig @@ -1,11 +1,25 @@ const std = @import("std"); -//const fumo = @import("fumostd.zig"); +const fumo = @import("fumostd.zig"); +const controller = @import("controller.zig"); +const input = @import("input.zig"); pub fn main() !void { - const a: isize = 0; - const b: isize = 6; + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + const allocator = arena.allocator(); - std.debug.print("{}", .{@mod(a - 1, b)}); + var ctrl = try controller.Controller.init(allocator, 3, 3, 3); + + try ctrl.bindCode(69, 0); + ctrl.bindAxis(0, 2, 1); + + var hand = try input.Handle.init(); + hand.aquire(); + + _ = hand.rec_circ.write(input.Record.readAxis(69, 123)); + + ctrl.poll(&hand.rec_circ); + + std.debug.print("axis index 2: {}", .{ctrl.axes[2].data}); + + hand.release(); } - -test "dict" {} diff --git a/rewrite/src/platform.zig b/rewrite/src/platform.zig index ae6bc6a..0c2e0c2 100644 --- a/rewrite/src/platform.zig +++ b/rewrite/src/platform.zig @@ -10,47 +10,100 @@ const stdin = windows.GetStdHandle(windows.STD_INPUT_HANDLE); const PlatformError = error{ReadInputCall}; pub fn ReadInput( - out_buf: *[input.IO_BUF_SIZE]input.Record, - n_out: *usize, - str_buf: *[input.STR_BUF_SIZE]u8, - n_str: *usize, + rec_buf: *input.RecordBuffer, + str_buf: *input.StringBuffer, ) !void { - var buf: [input.IO_BUF_SIZE]windows.INPUT_RECORD = undefined; - var n_buf: usize = 0; + var win_buf: [input.IO_BUF_SIZE]windows.INPUT_RECORD = undefined; + var n_win_buf: usize = 0; const success: bool = windows.ReadConsoleInputW( stdin, - &buf, + &win_buf, input.IO_BUF_SIZE, - &n_buf, + &n_win_buf, ); if (!success) return PlatformError.ReadInputCall; - n_out.* = 0; - - for (buf, out_buf) |rec, *out_rec| {} -} - -fn dispatch(win_rec: windows.INPUT_RECORD) bool { - switch (win_rec.EventType) { - windows.KEY_EVENT => blk: { - out_rec.* = input.Record{ - .scancode = rec.Event.KeyEvent.wVirtualScanCode, - .data = rec.Event.KeyEvent.bKeyDown, - .time = now, - .is_down = rec.Event.KeyEvent.bKeyDown, - }; - - if (rec.Event.KeyEvent.bKeyDown) - n_str.* += ucs2ToUtf8(str_buf + n_out, rec.Event.KeyEvent.uChar.UnicodeChar); - - break :blk true; - }, - - windows.WINDOW_BUFFER_SIZE_EVENT => false, - - else => false, + for (win_buf) |win_rec| { + translate(win_rec, rec_buf, str_buf); } } + +fn translate( + win_rec: windows.INPUT_RECORD, + rec_buf: *input.RecordBuffer, + str_buf: *input.StringBuffer, +) void { + switch (win_rec.EventType) { + windows.KEY_EVENT => { + input.Record.readAxis( + rec_buf, + win_rec.Event.KeyEvent.wVirtualKeyCode, + win_rec.Event.KeyEvent.bKeyDown, + ); + + if (!win_rec.Event.KeyEvent.bKeyDown) + return; + + str_buf.len += sprintWchar( + str_buf.array + str_buf.len, + win_rec.Event.KeyEvent.uChar.UnicodeChar, + ); + }, + + windows.MOUSE_EVENT => translateMouse( + rec_buf, + win_rec.Event.MouseEvent, + ), + + windows.WINDOW_BUFFER_SIZE_EVENT => void, + + else => void, + } +} + +fn translateMouse( + rec_buf: *input.RecordBuffer, + win_mouse: windows.MOUSE_EVENT_RECORD, +) void { + switch (win_mouse.dwEventFlags) { + windows.MOUSE_MOVED => input.Record.readJoystick( + rec_buf, + 0, + win_mouse.dwMousePosition.X, + win_mouse.dwMousePosition.Y, + ), + + windows.MOUSE_WHEELED => input.Record.readAxis( + rec_buf, + 1, + win_mouse.dwButtonState, + ), + + windows.MOUSE_HWHEELED => input.Record.readAxis( + rec_buf, + 2, + win_mouse.dwButtonState, + ), + } +} + +fn sprintWchar(buf: [*]u8, wchar: u16) usize { + if (wchar < 255) { + buf[0] = wchar; + return 1; + } + + if (wchar < 2047) { + buf[0] = 0xC0 + (wchar >> 6); + buf[1] = 0x80 + (wchar & 0x3F); + return 2; + } + + buf[0] = 0xE0 + (wchar >> 12); + buf[1] = 0x80 + ((wchar >> 6) & 0x3F); + buf[2] = 0x80 + (wchar & 0x3F); + return 3; +} diff --git a/rewrite/zig-cache/h/de18fb6bfd208e10a781b0c70184227b.txt b/rewrite/zig-cache/h/de18fb6bfd208e10a781b0c70184227b.txt index d009921..aebc54d 100644 --- a/rewrite/zig-cache/h/de18fb6bfd208e10a781b0c70184227b.txt +++ b/rewrite/zig-cache/h/de18fb6bfd208e10a781b0c70184227b.txt @@ -1,5 +1,5 @@ 0 -203 844424932407779 1716524569939084500 ec1e1d6dab6581d55ec18dff49107eaf 0 src\main.zig +231 844424932407779 1716824983055731700 4865c7439eede09c6c465fa6b8510223 0 src\main.zig 7757 281474978983955 1715741198000000000 3170fcda94ef1eb8e6ca725dff5e254d 1 std\std.zig 23040 281474978983952 1715741198000000000 da66963546b611ee7750a27396b7d1ea 1 std\start.zig 114777 281474978983653 1715741198000000000 b78cd1771bac0cee1cfa01c556ea1508 1 std\debug.zig diff --git a/rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.exe b/rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.exe new file mode 100644 index 0000000..5f479b8 Binary files /dev/null and b/rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.exe differ diff --git a/rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.exe.obj b/rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.exe.obj new file mode 100644 index 0000000..1ae6d19 Binary files /dev/null and b/rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.exe.obj differ diff --git a/rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.pdb b/rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.pdb new file mode 100644 index 0000000..0d9ee18 Binary files /dev/null and b/rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.pdb differ diff --git a/rewrite/zig-cache/z/3f1e76f863f210e69d09260c311f8b28 b/rewrite/zig-cache/z/3f1e76f863f210e69d09260c311f8b28 new file mode 100644 index 0000000..ddc6444 Binary files /dev/null and b/rewrite/zig-cache/z/3f1e76f863f210e69d09260c311f8b28 differ diff --git a/rewrite/zig-cache/z/540a4ac45c35aeaf4123cf9fe7d40c2f b/rewrite/zig-cache/z/540a4ac45c35aeaf4123cf9fe7d40c2f new file mode 100644 index 0000000..c401027 Binary files /dev/null and b/rewrite/zig-cache/z/540a4ac45c35aeaf4123cf9fe7d40c2f differ diff --git a/rewrite/zig-cache/z/9534d87f4f24eca7ce5266633aa9f75d b/rewrite/zig-cache/z/9534d87f4f24eca7ce5266633aa9f75d new file mode 100644 index 0000000..370d022 Binary files /dev/null and b/rewrite/zig-cache/z/9534d87f4f24eca7ce5266633aa9f75d differ diff --git a/rewrite/zig-cache/z/e9c4bfc358c3be207b456ad56f32decd b/rewrite/zig-cache/z/e9c4bfc358c3be207b456ad56f32decd index 35df478..85c5dc0 100644 Binary files a/rewrite/zig-cache/z/e9c4bfc358c3be207b456ad56f32decd and b/rewrite/zig-cache/z/e9c4bfc358c3be207b456ad56f32decd differ diff --git a/rewrite/zig-cache/z/fae34d3dfb6d1431c475cfcbefdcfba9 b/rewrite/zig-cache/z/fae34d3dfb6d1431c475cfcbefdcfba9 new file mode 100644 index 0000000..a8642c0 Binary files /dev/null and b/rewrite/zig-cache/z/fae34d3dfb6d1431c475cfcbefdcfba9 differ diff --git a/rewrite/zig-out/bin/rewrite.exe b/rewrite/zig-out/bin/rewrite.exe index 5b95d21..5f479b8 100644 Binary files a/rewrite/zig-out/bin/rewrite.exe and b/rewrite/zig-out/bin/rewrite.exe differ diff --git a/rewrite/zig-out/bin/rewrite.pdb b/rewrite/zig-out/bin/rewrite.pdb index ae36142..0d9ee18 100644 Binary files a/rewrite/zig-out/bin/rewrite.pdb and b/rewrite/zig-out/bin/rewrite.pdb differ