a
a
This commit is contained in:
parent
6477a45b8b
commit
0c2653ffaa
BIN
music/3xosc.flp
Normal file
BIN
music/3xosc.flp
Normal file
Binary file not shown.
BIN
music/chips/chipbgm.mp3
Normal file
BIN
music/chips/chipbgm.mp3
Normal file
Binary file not shown.
BIN
music/chips/chips.flp
Normal file
BIN
music/chips/chips.flp
Normal file
Binary file not shown.
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" {}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
BIN
rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.exe
Normal file
BIN
rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.exe
Normal file
Binary file not shown.
Binary file not shown.
BIN
rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.pdb
Normal file
BIN
rewrite/zig-cache/o/08f146d46cfbd4d5ae8ea46a3ef43ce1/rewrite.pdb
Normal file
Binary file not shown.
BIN
rewrite/zig-cache/z/3f1e76f863f210e69d09260c311f8b28
Normal file
BIN
rewrite/zig-cache/z/3f1e76f863f210e69d09260c311f8b28
Normal file
Binary file not shown.
BIN
rewrite/zig-cache/z/540a4ac45c35aeaf4123cf9fe7d40c2f
Normal file
BIN
rewrite/zig-cache/z/540a4ac45c35aeaf4123cf9fe7d40c2f
Normal file
Binary file not shown.
BIN
rewrite/zig-cache/z/9534d87f4f24eca7ce5266633aa9f75d
Normal file
BIN
rewrite/zig-cache/z/9534d87f4f24eca7ce5266633aa9f75d
Normal file
Binary file not shown.
Binary file not shown.
BIN
rewrite/zig-cache/z/fae34d3dfb6d1431c475cfcbefdcfba9
Normal file
BIN
rewrite/zig-cache/z/fae34d3dfb6d1431c475cfcbefdcfba9
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue