From cd59aca9e5f7cd5193bc609a0ef90bd9b056decc Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Thu, 21 Dec 2023 02:55:11 +0100 Subject: [PATCH] Added support for zig v0.11 --- README.md | 2 +- build.zig | 36 ++++++----- segatools.ini | 7 +++ src/main.zig | 171 ++++++++++++++++++++++++-------------------------- src/zigwin32 | 2 +- 5 files changed, 110 insertions(+), 108 deletions(-) diff --git a/README.md b/README.md index 379134c..5cd9e29 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,6 @@ Custom firmware USB device: 1CCF:2333 ``` $ git clone ... $ git submodule update --init -$ zig build -Drelease-safe=true +$ zig build -Doptimize=ReleaseSafe $ ls zig-out/lib/chuniio_tasoller.dll ``` diff --git a/build.zig b/build.zig index c704f15..6be90b5 100644 --- a/build.zig +++ b/build.zig @@ -1,20 +1,24 @@ const std = @import("std"); const CrossTarget = std.zig.CrossTarget; +const Build = std.build.Builder; +const Step = Build.Step; -pub fn build(b: *std.build.Builder) void { - - const lib86 = b.addSharedLibrary("chuniio_tasoller", "src/main.zig", .unversioned); - lib86.setBuildMode(b.standardReleaseOptions()); - lib86.setTarget(CrossTarget{ .os_tag = .windows, .cpu_arch = .i386, .abi = .msvc }); - lib86.install(); +pub fn build(b: *Build) void { + const mode = b.standardOptimizeOption(.{}); - const lib64 = b.addSharedLibrary("chuniio_tasoller_x64", "src/main.zig", .unversioned); - lib64.setBuildMode(b.standardReleaseOptions()); - lib64.setTarget(CrossTarget{ .os_tag = .windows, .cpu_arch = .x86_64, .abi = .msvc }); - lib64.install(); - - // const exe = b.addExecutable("tasoller_test", "src/main.zig"); - // lib.setBuildMode(b.standardReleaseOptions()); - // exe.setTarget(target); - // exe.install(); -} + const lib86 = b.addSharedLibrary(Build.SharedLibraryOptions{ + .name = "chuniio_tasoller", + .root_source_file = .{.path = "src/main.zig"}, + .target = CrossTarget{ .os_tag = .windows, .cpu_arch = .x86, .abi = .msvc }, + .optimize = mode, + }); + b.installArtifact(lib86); + + const lib64 = b.addSharedLibrary(Build.SharedLibraryOptions{ + .name = "chuniio_tasoller_x64", + .root_source_file = .{.path = "src/main.zig"}, + .target = CrossTarget{ .os_tag = .windows, .cpu_arch = .x86_64, .abi = .msvc }, + .optimize = mode, + }); + b.installArtifact(lib64); +} \ No newline at end of file diff --git a/segatools.ini b/segatools.ini index adb0298..8117343 100644 --- a/segatools.ini +++ b/segatools.ini @@ -1,4 +1,11 @@ [chuniio] +;; For Chunithm +;path=chuniio_tasoller.dll +;; For Chunithm NEW or newer +path32=chuniio_tasoller.dll +path64=chuniio_tasoller_x64.dll + +;; Uncomment for Chunithm NEW or newer chusan=1 [io3] diff --git a/src/main.zig b/src/main.zig index c55a8ef..1b0489a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -58,7 +58,7 @@ var input_thread: ?std.Thread = null; var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var usb_out_op = std.Thread.Mutex{}; -var usb_out = std.mem.zeroes([80*3]u8); +var usb_out = std.mem.zeroes([80 * 3]u8); var usb_in: ?[]u8 = null; var tasoller: ?*anyopaque = null; @@ -67,11 +67,11 @@ pub fn main() !void { usb_in = try gpa.allocator().alloc(u8, 0x24); var i: u32 = 0; try tasoller_init(); - while(true) { - if(WinUsb_WritePipe(tasoller, 0x03, @ptrCast(*u8, &usb_out), usb_out.len, &i, null) == 0) { + while (true) { + if (WinUsb_WritePipe(tasoller, 0x03, @as(*u8, @ptrCast(&usb_out)), usb_out.len, &i, null) == 0) { std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()}); } - if(WinUsb_ReadPipe(tasoller, 0x84, usb_in.ptr, usb_in.len, &i, null) == 0) { + if (WinUsb_ReadPipe(tasoller, 0x84, usb_in.ptr, usb_in.len, &i, null) == 0) { std.log.warn("[chuniio] WinUsb_ReadPipe: {any}", .{GetLastError()}); } std.time.sleep(100_000_000); @@ -81,8 +81,7 @@ pub fn main() !void { // MAIN DRIVER ====================================================================================================== fn tasoller_init() !void { - - if(cfg.?.chusan == 1) { + if (cfg.?.chusan == 1) { std.log.info("[chuniio] Initializing mode: chusan", .{}); const szName = W("Local\\ChuniioTasoller"); const hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, null, PAGE_READWRITE, 0, 0x24, szName) orelse { @@ -93,8 +92,8 @@ fn tasoller_init() !void { std.log.err("[chuniio] MapViewOfFile: {any}", .{GetLastError()}); return error.AccessError; }; - usb_in = @ptrCast([*]u8, pBuf)[0..0x24]; - if(builtin.cpu.arch == .x86_64) return; + usb_in = @as([*]u8, @ptrCast(pBuf))[0..0x24]; + if (builtin.cpu.arch == .x86_64) return; } else { std.log.info("[chuniio] Initializing mode: chuni", .{}); usb_in = gpa.allocator().alloc(u8, 0x24) catch |err| { @@ -104,66 +103,58 @@ fn tasoller_init() !void { } const hDevInfo = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_USB_DEVICE, null, null, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if(hDevInfo == INVALID_HANDLE_VALUE) { + if (hDevInfo == INVALID_HANDLE_VALUE) { std.log.err("[chuniio] SetupDiGetClassDevs: {any}", .{GetLastError()}); return error.AccessError; } defer _ = SetupDiDestroyDeviceInfoList(hDevInfo); - + var ifIdx: DWORD = 0; var devIf = std.mem.zeroes(SP_DEVICE_INTERFACE_DATA); devIf.cbSize = @sizeOf(SP_DEVICE_INTERFACE_DATA); var devicePath: ?[*:0]const u8 = null; - while(SetupDiEnumDeviceInterfaces(hDevInfo, null, &GUID_DEVINTERFACE_USB_DEVICE, ifIdx, &devIf) != 0) : (ifIdx += 1) { + while (SetupDiEnumDeviceInterfaces(hDevInfo, null, &GUID_DEVINTERFACE_USB_DEVICE, ifIdx, &devIf) != 0) : (ifIdx += 1) { var requiredSize: u32 = 0; var detailBuf align(4) = std.mem.zeroes([512]u8); - var devIfDetail = @ptrCast(*SP_DEVICE_INTERFACE_DETAIL_DATA_A, &detailBuf); + var devIfDetail = @as(*SP_DEVICE_INTERFACE_DETAIL_DATA_A, @ptrCast(&detailBuf)); devIfDetail.cbSize = @sizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA_A); - if(SetupDiGetDeviceInterfaceDetailA(hDevInfo, &devIf, devIfDetail, 263, &requiredSize, null) == 0) { + if (SetupDiGetDeviceInterfaceDetailA(hDevInfo, &devIf, devIfDetail, 263, &requiredSize, null) == 0) { std.log.err("[chuniio] SetupDiGetDeviceInterfaceDetailA: {any}", .{GetLastError()}); continue; } - if(requiredSize >= 263) { + if (requiredSize >= 263) { std.log.err("[chuniio] SetupDiGetDeviceInterfaceDetailA: Path too long", .{}); continue; } - const path = detailBuf[@offsetOf(SP_DEVICE_INTERFACE_DETAIL_DATA_A, "DevicePath") .. requiredSize :0]; + const path = detailBuf[@offsetOf(SP_DEVICE_INTERFACE_DETAIL_DATA_A, "DevicePath")..requiredSize :0]; // std.log.info("[chuniio] devPath: {s}", .{path}); - if(std.mem.indexOf(u8, path, "vid_1ccf") == null) continue; - if(std.mem.indexOf(u8, path, "pid_2333") == null) continue; + if (std.mem.indexOf(u8, path, "vid_1ccf") == null) continue; + if (std.mem.indexOf(u8, path, "pid_2333") == null) continue; devicePath = path; break; } - if(devicePath == null) { + if (devicePath == null) { std.log.err("[chuniio] Tasoller not found", .{}); return error.AccessError; } - const hDeviceHandle = CreateFileA( - devicePath, - @intToEnum(FILE_ACCESS_FLAGS, GENERIC_READ | GENERIC_WRITE), - @intToEnum(FILE_SHARE_MODE, @enumToInt(FILE_SHARE_READ) | @enumToInt(FILE_SHARE_WRITE)), - null, // Security Attributes - OPEN_EXISTING, - .FILE_FLAG_OVERLAPPED, - null // Template File - ) orelse { - std.log.err("[chuniio] CreateFileA {s}: {any}", .{devicePath, GetLastError()}); - return error.AccessError; - }; - if(hDeviceHandle == INVALID_HANDLE_VALUE) { - std.log.err("[chuniio] CreateFileA {s}: {any}", .{devicePath, GetLastError()}); + const hDeviceHandle = CreateFileA(devicePath, @as(FILE_ACCESS_FLAGS, @enumFromInt(GENERIC_READ | GENERIC_WRITE)), @as(FILE_SHARE_MODE, @enumFromInt(@intFromEnum(FILE_SHARE_READ) | @intFromEnum(FILE_SHARE_WRITE))), null, // Security Attributes + OPEN_EXISTING, .FILE_FLAG_OVERLAPPED, null // Template File + ); + + if (hDeviceHandle == INVALID_HANDLE_VALUE) { + std.log.err("[chuniio] CreateFileA {any}: {any}\n", .{ devicePath, GetLastError() }); return error.AccessError; } - if(WinUsb_Initialize(hDeviceHandle, &tasoller) == 0) { - std.log.err("[chuniio] WinUsb_Initialize: {any}", .{GetLastError()}); + if (WinUsb_Initialize(hDeviceHandle, &tasoller) == 0) { + std.log.err("[chuniio] WinUsb_Initialize: {any}\n", .{ GetLastError() }); return error.AccessError; } // Init magic bytes - std.mem.copy(u8, usb_out[0..3], &[_]u8{0x42, 0x4C, 0x00}); - + std.mem.copy(u8, usb_out[0..3], &[_]u8{ 0x42, 0x4C, 0x00 }); + input_thread = std.Thread.spawn(.{}, input_thread_proc, .{}) catch |err| { std.log.err("[chuniio] Spawn input thread: {any}", .{err}); return error.AccessError; @@ -173,23 +164,23 @@ fn tasoller_init() !void { // Poll input regardless of slider start/stop fn input_thread_proc() void { std.log.info("[chuniio] Input thread started", .{}); - while(true) { + while (true) { var len: u32 = 0; - if(WinUsb_ReadPipe(tasoller, 0x84, @ptrCast(*u8, usb_in.?.ptr), @intCast(u32, usb_in.?.len), &len, null) == 0) { + if (WinUsb_ReadPipe(tasoller, 0x84, @as(*u8, @ptrCast(usb_in.?.ptr)), @as(u32, @intCast(usb_in.?.len)), &len, null) == 0) { std.log.warn("[chuniio] WinUsb_ReadPipe: {any}", .{GetLastError()}); } } } -const chuni_io_slider_callback_t = ?fn ([*c]const u8) callconv(.C) void; +const chuni_io_slider_callback_t = ?*fn ([*c]const u8) callconv(.C) void; fn slider_thread_proc(callback: chuni_io_slider_callback_t) void { var pressure = std.mem.zeroes([32]u8); - while(slider_active) { - for(usb_in.?[4..]) |byte, i| { + while (slider_active) { + for (usb_in.?[4..], 0..) |byte, i| { // Tasoller order: top->bottom, left->right // Chunithm order: top->bottom, right->left - pressure[if(i%2 == 0) 30-i else 32-i] = byte; + pressure[if (i % 2 == 0) 30 - i else 32 - i] = byte; } callback.?(&pressure); std.time.sleep(1_000_000); // 1ms, limit reporting to 1kHz max @@ -205,59 +196,59 @@ export fn chuni_io_get_api_version() c_ushort { pub export fn DllMain(hDllHandle: HANDLE, dwReason: DWORD, lpreserved: LPVOID) BOOL { _ = hDllHandle; _ = lpreserved; - if(dwReason != DLL_PROCESS_ATTACH) return win32.zig.TRUE; - + if (dwReason != DLL_PROCESS_ATTACH) return win32.zig.TRUE; + const cfg_file = ".\\segatools.ini"; std.log.info("[chuniio] Loading config from {s}", .{cfg_file}); cfg = .{ - .test_key = @intCast(i32, GetPrivateProfileIntA("io3", "test", 0x31, cfg_file)), - .serv_key = @intCast(i32, GetPrivateProfileIntA("io3", "service", 0x32, cfg_file)), - .coin_key = @intCast(i32, GetPrivateProfileIntA("io3", "coin", 0x33, cfg_file)), - .chusan = @intCast(i32, GetPrivateProfileIntA("chuniio", "chusan", 0, cfg_file)), + .test_key = @as(i32, @intCast(GetPrivateProfileIntA("io3", "test", 0x31, cfg_file))), + .serv_key = @as(i32, @intCast(GetPrivateProfileIntA("io3", "service", 0x32, cfg_file))), + .coin_key = @as(i32, @intCast(GetPrivateProfileIntA("io3", "coin", 0x33, cfg_file))), + .chusan = @as(i32, @intCast(GetPrivateProfileIntA("chuniio", "chusan", 0, cfg_file))), }; - + return win32.zig.TRUE; } export fn chuni_io_jvs_init() HRESULT { - if(cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return S_OK; + if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return S_OK; tasoller_init() catch return E_FAIL; return S_OK; } export fn chuni_io_jvs_poll(opbtn: ?[*]u8, beams: ?[*]u8) void { - if(cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return; - if(opbtn == null or beams == null) return; - if(GetAsyncKeyState(cfg.?.test_key) != 0 or (usb_in.?[3] & (1 << 7)) != 0) opbtn.?.* |= (1 << 0); - if(GetAsyncKeyState(cfg.?.serv_key) != 0 or (usb_in.?[3] & (1 << 6)) != 0) opbtn.?.* |= (1 << 1); - beams.?.* |= usb_in.?[3] & 0b111111; + if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return; + if (opbtn == null or beams == null) return; + if (GetAsyncKeyState(cfg.?.test_key) != 0 or (usb_in.?[3] & (1 << 7)) != 0) opbtn.?[0] |= (1 << 0); + if (GetAsyncKeyState(cfg.?.serv_key) != 0 or (usb_in.?[3] & (1 << 6)) != 0) opbtn.?[0] |= (1 << 1); + beams.?[0] |= usb_in.?[3] & 0b111111; } var coin_conter: c_ushort = 0; var coin_prev_depressed = false; export fn chuni_io_jvs_read_coin_counter(total: ?*c_ushort) void { - if(cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return; - if(total == null) return; + if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return; + if (total == null) return; const coin_depressed = GetAsyncKeyState(cfg.?.coin_key) != 0; - if(coin_depressed and !coin_prev_depressed) coin_conter += 1; + if (coin_depressed and !coin_prev_depressed) coin_conter += 1; coin_prev_depressed = coin_depressed; total.?.* = coin_conter; } export fn chuni_io_slider_init() HRESULT { - if(cfg.?.chusan == 0) return S_OK; + if (cfg.?.chusan == 0) return S_OK; tasoller_init() catch return E_FAIL; return S_OK; } export fn chuni_io_slider_start(callback: chuni_io_slider_callback_t) void { - if(cfg.?.chusan == 1 and builtin.cpu.arch != .i386) return; - if(callback == null) return; - + if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86) return; + if (callback == null) return; + thread_op.lock(); defer thread_op.unlock(); - if(slider_thread == null) { + if (slider_thread == null) { slider_active = true; slider_thread = std.Thread.spawn(.{}, slider_thread_proc, .{callback}) catch |err| { std.log.err("[chuniio] Spawn slider thread: {any}", .{err}); @@ -267,11 +258,11 @@ export fn chuni_io_slider_start(callback: chuni_io_slider_callback_t) void { } export fn chuni_io_slider_stop() void { - if(cfg.?.chusan == 1 and builtin.cpu.arch != .i386) return; - + if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86) return; + thread_op.lock(); defer thread_op.unlock(); - if(slider_thread != null) { + if (slider_thread != null) { slider_active = false; slider_thread.?.join(); slider_thread = null; @@ -279,52 +270,52 @@ export fn chuni_io_slider_stop() void { } export fn chuni_io_slider_set_leds(rgb: ?[*]u8) void { - if(cfg.?.chusan == 1 and builtin.cpu.arch != .i386) return; - if(rgb == null) return; - + if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86) return; + if (rgb == null) return; + var n: u32 = 0; const out = usb_out[3..96]; - while(n < 31) : (n += 1) { - out[n*3+0] = rgb.?[n*3+2]; - out[n*3+1] = rgb.?[n*3+1]; - out[n*3+2] = rgb.?[n*3+0]; + while (n < 31) : (n += 1) { + out[n * 3 + 0] = rgb.?[n * 3 + 2]; + out[n * 3 + 1] = rgb.?[n * 3 + 1]; + out[n * 3 + 2] = rgb.?[n * 3 + 0]; } usb_out_op.lock(); defer usb_out_op.unlock(); - if(WinUsb_WritePipe(tasoller, 0x03, @ptrCast(*u8, &usb_out), usb_out.len, &n, null) == 0) { + if (WinUsb_WritePipe(tasoller, 0x03, @as(*u8, @ptrCast(&usb_out)), usb_out.len, &n, null) == 0) { std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()}); } } -export fn chuni_io_led_init() HRESULT{ +export fn chuni_io_led_init() HRESULT { return S_OK; } export fn chuni_io_led_set_colors(board: u8, rgb: ?[*]u8) void { - if(cfg.?.chusan == 1 and builtin.cpu.arch != .i386) return; - if(rgb == null) return; - + if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86) return; + if (rgb == null) return; + var n: u32 = 0; - if(board == 0) { + if (board == 0) { const out = usb_out[96..168]; - while(n < 24) : (n += 1) { - out[n*3+1] = rgb.?[0x96]; - out[n*3+0] = rgb.?[0x97]; - out[n*3+2] = rgb.?[0x98]; + while (n < 24) : (n += 1) { + out[n * 3 + 1] = rgb.?[0x96]; + out[n * 3 + 0] = rgb.?[0x97]; + out[n * 3 + 2] = rgb.?[0x98]; } - } else if(board == 1) { + } else if (board == 1) { const out = usb_out[168..240]; - while(n < 24) : (n += 1) { - out[n*3+1] = rgb.?[0xb4]; - out[n*3+0] = rgb.?[0xb5]; - out[n*3+2] = rgb.?[0xb6]; + while (n < 24) : (n += 1) { + out[n * 3 + 1] = rgb.?[0xb4]; + out[n * 3 + 0] = rgb.?[0xb5]; + out[n * 3 + 2] = rgb.?[0xb6]; } } usb_out_op.lock(); defer usb_out_op.unlock(); - if(WinUsb_WritePipe(tasoller, 0x03, @ptrCast(*u8, &usb_out), usb_out.len, &n, null) == 0) { + if (WinUsb_WritePipe(tasoller, 0x03, @as(*u8, @ptrCast(&usb_out)), usb_out.len, &n, null) == 0) { std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()}); } -} \ No newline at end of file +} diff --git a/src/zigwin32 b/src/zigwin32 index a74c9da..6777f1d 160000 --- a/src/zigwin32 +++ b/src/zigwin32 @@ -1 +1 @@ -Subproject commit a74c9dae6a1ccd361eb9a1d146a09c08d22f02b0 +Subproject commit 6777f1db221d0cb50322842f558f03e3c3a4099f -- 2.39.2