From c8d9e5c862e0e165948671c7295ea0155ab22f03 Mon Sep 17 00:00:00 2001 From: Samuel Deutsch Date: Fri, 27 Jun 2025 02:44:11 -0700 Subject: [PATCH 01/10] Added support for updating the Steel Battalion Controller's lights --- lib/usb/libusbohci_xbox/xid_driver.c | 15 ++++++++++++++ lib/usb/libusbohci_xbox/xid_driver.h | 30 ++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/lib/usb/libusbohci_xbox/xid_driver.c b/lib/usb/libusbohci_xbox/xid_driver.c index f38ec4a45..cb7cf3fcc 100644 --- a/lib/usb/libusbohci_xbox/xid_driver.c +++ b/lib/usb/libusbohci_xbox/xid_driver.c @@ -372,6 +372,21 @@ int32_t usbh_xid_rumble(xid_dev_t *xid_dev, uint16_t l_value, uint16_t h_value){ return usbh_xid_write(xid_dev, 0, (uint8_t *)&command, sizeof(xid_gamepad_out), NULL); } +int32_t usbh_xid_sbc_lights(xid_dev_t *xid_dev, uint8_t lights[STEELBATTALION_LIGHT_COUNT]) { + if (xid_dev->xid_desc.bType != XID_TYPE_STEELBATTALION) + { + return USBH_ERR_NOT_SUPPORTED; + } + + xid_steelbattalion_out command = + { + .startByte = 0, + .bLength = sizeof(xid_steelbattalion_out), + }; + memcpy(command.lights, lights, STEELBATTALION_LIGHT_COUNT); + return usbh_xid_write(xid_dev, 0, (uint8_t *)&command, sizeof(xid_gamepad_out), NULL); +} + /** * @brief Returns the xid_type. * diff --git a/lib/usb/libusbohci_xbox/xid_driver.h b/lib/usb/libusbohci_xbox/xid_driver.h index 3d97cbee2..a62b79465 100644 --- a/lib/usb/libusbohci_xbox/xid_driver.h +++ b/lib/usb/libusbohci_xbox/xid_driver.h @@ -24,7 +24,7 @@ extern "C" struct xid_dev; typedef void(XID_CONN_FUNC)(struct xid_dev *hdev, int param); -typedef struct __attribute__((packed)) +typedef struct __attribute__((packed)) { uint8_t bLength; uint8_t bDescriptorType; @@ -36,7 +36,7 @@ typedef struct __attribute__((packed)) uint16_t wAlternateProductIds[4]; } xid_descriptor; -typedef struct __attribute__((packed)) +typedef struct __attribute__((packed)) { uint8_t startByte; uint8_t bLength; @@ -63,6 +63,31 @@ typedef struct __attribute__((packed)) uint16_t hValue; } xid_gamepad_out; +typedef struct __attribute__((packed)) +{ + uint8_t startByte; + uint8_t bLength; + uint16_t buttons[3]; + uint16_t aimingLeverX; // 0 = Left, 0xFFFF = Right + uint16_t aimingLeverY; // 0 = Top, 0xFFFF = Bottom + int16_t turningLever; + int16_t sightChangeX; + int16_t sightChangeY; + uint16_t slidePedal; + uint16_t brakePedal; + uint16_t accelPedal; + uint8_t tuner; // 0-15 is from 9oclock, around clockwise + int8_t shifter; // -2 = R, -1 = N, 0 = Error, 1 = 1st, 2 = 2nd, 3 = 3rnd, 4 = 4th, 5 = 5th +} xid_steelbattlion_in; + +#define STEELBATTALION_LIGHT_COUNT 20 +typedef struct __attribute__((packed)) +{ + uint8_t startByte; + uint8_t bLength; + uint8_t lights[STEELBATTALION_LIGHT_COUNT]; +} xid_steelbattalion_out; + //Ref https://xboxdevwiki.net/Xbox_DVD_Movie_Playback_Kit typedef struct __attribute__((packed)) { @@ -106,6 +131,7 @@ int32_t usbh_xid_read(xid_dev_t *xid_dev, uint8_t ep_addr, void *rx_complete_cal int32_t usbh_xid_write(xid_dev_t *xid_dev, uint8_t ep_addr, uint8_t *txbuff, uint32_t len, void *tx_complete_callback); xid_type usbh_xid_get_type(xid_dev_t *xid_dev); int32_t usbh_xid_rumble(xid_dev_t *xid_dev, uint16_t l_value, uint16_t h_value); +int32_t usbh_xid_sbc_lights(xid_dev_t *xid_dev, uint8_t lights[STEELBATTALION_LIGHT_COUNT]); #ifdef __cplusplus } From 14a2a52ec9498f6ba72428ce2d30d1004af32953 Mon Sep 17 00:00:00 2001 From: Samuel Deutsch Date: Sat, 28 Jun 2025 00:56:40 -0700 Subject: [PATCH 02/10] Move input structures from SDL to XID driver --- lib/usb/libusbohci_xbox/xid_driver.c | 4 ++-- lib/usb/libusbohci_xbox/xid_driver.h | 30 ++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/usb/libusbohci_xbox/xid_driver.c b/lib/usb/libusbohci_xbox/xid_driver.c index cb7cf3fcc..c0158fcc6 100644 --- a/lib/usb/libusbohci_xbox/xid_driver.c +++ b/lib/usb/libusbohci_xbox/xid_driver.c @@ -372,7 +372,7 @@ int32_t usbh_xid_rumble(xid_dev_t *xid_dev, uint16_t l_value, uint16_t h_value){ return usbh_xid_write(xid_dev, 0, (uint8_t *)&command, sizeof(xid_gamepad_out), NULL); } -int32_t usbh_xid_sbc_lights(xid_dev_t *xid_dev, uint8_t lights[STEELBATTALION_LIGHT_COUNT]) { +int32_t usbh_xid_sbc_lights(xid_dev_t *xid_dev, uint8_t lights[STEELBATTALION_LIGHT_BYTES]) { if (xid_dev->xid_desc.bType != XID_TYPE_STEELBATTALION) { return USBH_ERR_NOT_SUPPORTED; @@ -383,7 +383,7 @@ int32_t usbh_xid_sbc_lights(xid_dev_t *xid_dev, uint8_t lights[STEELBATTALION_LI .startByte = 0, .bLength = sizeof(xid_steelbattalion_out), }; - memcpy(command.lights, lights, STEELBATTALION_LIGHT_COUNT); + memcpy(command.lights, lights, STEELBATTALION_LIGHT_BYTES); return usbh_xid_write(xid_dev, 0, (uint8_t *)&command, sizeof(xid_gamepad_out), NULL); } diff --git a/lib/usb/libusbohci_xbox/xid_driver.h b/lib/usb/libusbohci_xbox/xid_driver.h index a62b79465..5f081313d 100644 --- a/lib/usb/libusbohci_xbox/xid_driver.h +++ b/lib/usb/libusbohci_xbox/xid_driver.h @@ -36,6 +36,23 @@ typedef struct __attribute__((packed)) uint16_t wAlternateProductIds[4]; } xid_descriptor; +//XINPUT defines and struct format from +//https://docs.microsoft.com/en-us/windows/win32/api/xinput/ns-xinput-xinput_gamepad +#define XINPUT_GAMEPAD_DPAD_UP 0x0001 +#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002 +#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004 +#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008 +#define XINPUT_GAMEPAD_START 0x0010 +#define XINPUT_GAMEPAD_BACK 0x0020 +#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040 +#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080 +#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 +#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 +#define XINPUT_GAMEPAD_A 0x1000 +#define XINPUT_GAMEPAD_B 0x2000 +#define XINPUT_GAMEPAD_X 0x4000 +#define XINPUT_GAMEPAD_Y 0x8000 + typedef struct __attribute__((packed)) { uint8_t startByte; @@ -47,8 +64,8 @@ typedef struct __attribute__((packed)) uint8_t y; uint8_t black; uint8_t white; - uint8_t l; - uint8_t r; + uint8_t leftTrigger; + uint8_t rightTrigger; int16_t leftStickX; int16_t leftStickY; int16_t rightStickX; @@ -78,14 +95,15 @@ typedef struct __attribute__((packed)) uint16_t accelPedal; uint8_t tuner; // 0-15 is from 9oclock, around clockwise int8_t shifter; // -2 = R, -1 = N, 0 = Error, 1 = 1st, 2 = 2nd, 3 = 3rnd, 4 = 4th, 5 = 5th -} xid_steelbattlion_in; +} xid_steelbattalion_in; -#define STEELBATTALION_LIGHT_COUNT 20 +#define STEELBATTALION_LIGHT_COUNT 40 +#define STEELBATTALION_LIGHT_BYTES (STEELBATTALION_LIGHT_COUNT / 2) // Each nibble is 1 light typedef struct __attribute__((packed)) { uint8_t startByte; uint8_t bLength; - uint8_t lights[STEELBATTALION_LIGHT_COUNT]; + uint8_t lights[STEELBATTALION_LIGHT_BYTES]; } xid_steelbattalion_out; //Ref https://xboxdevwiki.net/Xbox_DVD_Movie_Playback_Kit @@ -131,7 +149,7 @@ int32_t usbh_xid_read(xid_dev_t *xid_dev, uint8_t ep_addr, void *rx_complete_cal int32_t usbh_xid_write(xid_dev_t *xid_dev, uint8_t ep_addr, uint8_t *txbuff, uint32_t len, void *tx_complete_callback); xid_type usbh_xid_get_type(xid_dev_t *xid_dev); int32_t usbh_xid_rumble(xid_dev_t *xid_dev, uint16_t l_value, uint16_t h_value); -int32_t usbh_xid_sbc_lights(xid_dev_t *xid_dev, uint8_t lights[STEELBATTALION_LIGHT_COUNT]); +int32_t usbh_xid_sbc_lights(xid_dev_t *xid_dev, uint8_t lights[STEELBATTALION_LIGHT_BYTES]); #ifdef __cplusplus } From 6a76b58645f3013355c758be23198d5470178b26 Mon Sep 17 00:00:00 2001 From: Ryan Wendland Date: Sun, 22 Jun 2025 08:57:13 +0930 Subject: [PATCH 03/10] nvnetdrv: Implement link state change handling --- lib/net/nvnetdrv/nvnetdrv.c | 12 ++++++++++++ lib/net/nvnetdrv/nvnetdrv.h | 12 ++++++++++++ lib/net/nvnetdrv/nvnetdrv_lwip.c | 27 +++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/net/nvnetdrv/nvnetdrv.c b/lib/net/nvnetdrv/nvnetdrv.c index c05f55f6c..8ed21cdf8 100644 --- a/lib/net/nvnetdrv/nvnetdrv.c +++ b/lib/net/nvnetdrv/nvnetdrv.c @@ -264,6 +264,7 @@ static void nvnetdrv_handle_mii_irq (uint32_t miiStatus, bool init) if (miiStatus & NVREG_MIISTAT_LINKCHANGE) { nvnetdrv_start_txrx(); + nvnetdrv_link_state_change_callback(linkState & XNET_ETHERNET_LINK_ACTIVE); } INC_STAT(phy_interrupts, 1); @@ -654,3 +655,14 @@ void nvnetdrv_rx_release (void *buffer_virt) g_rxRing[index].flags = NV_RX_AVAIL; reg32(NvRegTxRxControl) = NVREG_TXRXCTL_GET; } + +bool nvnetdrv_is_link_up (void) +{ + uint32_t linkState = PhyGetLinkState(false); + return (linkState & XNET_ETHERNET_LINK_ACTIVE) != 0; +} + +__attribute__((weak)) void nvnetdrv_link_state_change_callback (bool link_active) +{ + (void)link_active; +} diff --git a/lib/net/nvnetdrv/nvnetdrv.h b/lib/net/nvnetdrv/nvnetdrv.h index 793ab8e37..e0f94ef9f 100644 --- a/lib/net/nvnetdrv/nvnetdrv.h +++ b/lib/net/nvnetdrv/nvnetdrv.h @@ -8,6 +8,7 @@ #include #include +#include #include // Must be greater than max ethernet frame size. A multiple of page size prevents page boundary crossing @@ -87,4 +88,15 @@ void nvnetdrv_submit_tx_descriptors (nvnetdrv_descriptor_t *buffers, size_t coun */ void nvnetdrv_rx_release (void *buffer_virt); +/** + * @brief Check if the link is up. + * @return true if link connected, false if link is down. + */ +bool nvnetdrv_is_link_up (void); + +/** + * Called by the ISR when the link state changes. + * @param link_up True if the link is up, false if it is down. + */ +void nvnetdrv_link_state_change_callback (bool link_up); #endif diff --git a/lib/net/nvnetdrv/nvnetdrv_lwip.c b/lib/net/nvnetdrv/nvnetdrv_lwip.c index 31457ae90..d5d979f9b 100644 --- a/lib/net/nvnetdrv/nvnetdrv_lwip.c +++ b/lib/net/nvnetdrv/nvnetdrv_lwip.c @@ -14,6 +14,7 @@ #include "lwip/snmp.h" #include "lwip/stats.h" #include "lwip/sys.h" +#include "lwip/tcpip.h" #include "netif/etharp.h" #include "netif/ppp/pppoe.h" #include "nvnetdrv.h" @@ -81,6 +82,17 @@ void rx_callback (void *buffer, uint16_t length) } } + +static void change_link_state(void *ctx) +{ + bool link_active = (bool)ctx; + if (link_active) { + netif_set_link_up(g_pnetif); + } else { + netif_set_link_down(g_pnetif); + } +} + /** * In this function, the hardware should be initialized. * Called from nforceif_init(). @@ -97,7 +109,7 @@ static err_t low_level_init (struct netif *netif) /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; #if LWIP_IPV6 && LWIP_IPV6_MLD /* @@ -123,6 +135,10 @@ static err_t low_level_init (struct netif *netif) /* set MAC hardware address */ memcpy(netif->hwaddr, nvnetdrv_get_ethernet_addr(), 6); + // Let LWIP know if a ethernet cable is currently connected + bool link_up = nvnetdrv_is_link_up(); + change_link_state((void *)link_up); + return ERR_OK; } @@ -277,4 +293,11 @@ err_t nvnetif_init (struct netif *netif) /* initialize the hardware */ return low_level_init(netif); -} \ No newline at end of file +} + +void nvnetdrv_link_state_change_callback (bool link_active) +{ + // ISR safe mbox to tcpip thread. This is very unlikely to fail as the mbox is large and the messages + // are allocated from the kernel's pool allocator. + tcpip_try_callback(change_link_state, (void *)link_active); +} From 730f53aa390fb8200f185de0b757f3fcfefb92d5 Mon Sep 17 00:00:00 2001 From: wutno Date: Wed, 9 Jul 2025 08:00:54 -0400 Subject: [PATCH 04/10] pdclib: Update to 679081d --- lib/pdclib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pdclib b/lib/pdclib index 82bf35e9e..679081d47 160000 --- a/lib/pdclib +++ b/lib/pdclib @@ -1 +1 @@ -Subproject commit 82bf35e9ebe70ae3214d4426ff7d1ef6b648376e +Subproject commit 679081d4725ab893d0ef7822111b5c5d05a572f5 From 6525f884e3020a405fc9924f5530c4212e2a0f13 Mon Sep 17 00:00:00 2001 From: wutno Date: Wed, 9 Jul 2025 08:32:07 -0400 Subject: [PATCH 05/10] video: Disable soften filter on start-up --- lib/hal/video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/hal/video.c b/lib/hal/video.c index 30553d1cb..61da0cac2 100644 --- a/lib/hal/video.c +++ b/lib/hal/video.c @@ -54,7 +54,7 @@ static DWORD dwEncoderSettings = 0; static VIDEO_MODE vmCurrent = { 0, 0, 0, 0 }; static int flickerLevel = 5; static BOOL flickerSet = FALSE; -static BOOL softenFilter = TRUE; +static BOOL softenFilter = FALSE; static BOOL softenSet = FALSE; static GAMMA_RAMP_ENTRY gammaRampEntries[256]; @@ -381,7 +381,7 @@ void XVideoInit(DWORD dwMode, int width, int height, int bpp) _fb = framebufferMemory; XVideoSetFlickerFilter(5); - XVideoSetSoftenFilter(TRUE); + XVideoSetSoftenFilter(FALSE); for(i = 0; i < 256; i++) { defaultGammaRampEntries[i].red = i; From 7b54aebd7c1bc832487d6751cb5ccb3ae24cf7b3 Mon Sep 17 00:00:00 2001 From: Ryzee119 Date: Sun, 20 Jul 2025 09:18:40 +0930 Subject: [PATCH 06/10] winapi: Fix typo in thread priority define --- lib/winapi/winbase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/winapi/winbase.h b/lib/winapi/winbase.h index a2d17921d..6945f4a46 100644 --- a/lib/winapi/winbase.h +++ b/lib/winapi/winbase.h @@ -25,7 +25,7 @@ extern "C" { #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 #define THREAD_PRIORITY_ABOVE_NORMAL 1 -#define THREAD_PRIOIRTY_BELOW_NORMAL (-1) +#define THREAD_PRIORITY_BELOW_NORMAL (-1) #define THREAD_PRIORITY_HIGHEST 2 #define THREAD_PRIORITY_IDLE (-15) #define THREAD_PRIORITY_LOWEST (-2) From 27058e675fb0cefcb100c778a9c15ae1299b5d66 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Tue, 18 Feb 2025 05:35:33 +0100 Subject: [PATCH 07/10] xboxkrnl: Fix typo in TIME_FIELDS definition --- lib/winapi/sysinfo.c | 4 ++-- lib/xboxkrnl/xboxkrnl.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/winapi/sysinfo.c b/lib/winapi/sysinfo.c index 2479b6d60..ac93dd250 100644 --- a/lib/winapi/sysinfo.c +++ b/lib/winapi/sysinfo.c @@ -24,7 +24,7 @@ void GetSystemTime (LPSYSTEMTIME lpSystemTime) lpSystemTime->wHour = timeFields.Hour; lpSystemTime->wMinute = timeFields.Minute; lpSystemTime->wSecond = timeFields.Second; - lpSystemTime->wMilliseconds = timeFields.Millisecond; + lpSystemTime->wMilliseconds = timeFields.Milliseconds; lpSystemTime->wDayOfWeek = timeFields.Weekday; } @@ -92,6 +92,6 @@ void GetLocalTime (LPSYSTEMTIME lpSystemTime) lpSystemTime->wHour = timeFields.Hour; lpSystemTime->wMinute = timeFields.Minute; lpSystemTime->wSecond = timeFields.Second; - lpSystemTime->wMilliseconds = timeFields.Millisecond; + lpSystemTime->wMilliseconds = timeFields.Milliseconds; lpSystemTime->wDayOfWeek = timeFields.Weekday; } diff --git a/lib/xboxkrnl/xboxkrnl.h b/lib/xboxkrnl/xboxkrnl.h index 6eab27374..01662fd36 100644 --- a/lib/xboxkrnl/xboxkrnl.h +++ b/lib/xboxkrnl/xboxkrnl.h @@ -184,7 +184,7 @@ typedef struct _TIME_FIELDS SHORT Hour; /**< Specifies a value from 0 to 23 */ SHORT Minute; /**< Specifies a value from 0 to 59 */ SHORT Second; /**< Specifies a value from 0 to 59 */ - SHORT Millisecond; /**< Specifies a value from 0 to 999 */ + SHORT Milliseconds; /**< Specifies a value from 0 to 999 */ SHORT Weekday; /**< Specifies a value from 0 to 6 (Sunday to Saturday) */ } TIME_FIELDS, *PTIME_FIELDS; From e45a857fa7eb03e6473c8c2cacb33e8373549e5b Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Tue, 18 Feb 2025 05:17:47 +0100 Subject: [PATCH 08/10] winapi: Implement FileTimeToSystemTime() --- lib/winapi/timezoneapi.c | 32 ++++++++++++++++++++++++++++++++ lib/winapi/timezoneapi.h | 3 +++ 2 files changed, 35 insertions(+) diff --git a/lib/winapi/timezoneapi.c b/lib/winapi/timezoneapi.c index e55c0f4d9..217d61609 100644 --- a/lib/winapi/timezoneapi.c +++ b/lib/winapi/timezoneapi.c @@ -1,10 +1,12 @@ // SPDX-License-Identifier: MIT // SPDX-FileCopyrightText: 2023 Ryan Wendland +// SPDX-FileCopyrightText: 2025 Stefan Schmidt #include #include #include +#include #include #include @@ -210,3 +212,33 @@ DWORD GetTimeZoneInformation (LPTIME_ZONE_INFORMATION lpTimeZoneInformation) return TIME_ZONE_ID_STANDARD; } } + +BOOL FileTimeToSystemTime (const FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime) +{ + if (!lpFileTime || !lpSystemTime) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + LARGE_INTEGER filetime; + filetime.LowPart = lpFileTime->dwLowDateTime; + filetime.HighPart = lpFileTime->dwHighDateTime; + if (filetime.QuadPart < 0) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + TIME_FIELDS timefields; + RtlTimeToTimeFields(&filetime, &timefields); + + lpSystemTime->wYear = timefields.Year; + lpSystemTime->wMonth = timefields.Month; + lpSystemTime->wDay = timefields.Day; + lpSystemTime->wDayOfWeek = timefields.Weekday; + lpSystemTime->wHour = timefields.Hour; + lpSystemTime->wMinute = timefields.Minute; + lpSystemTime->wSecond = timefields.Second; + lpSystemTime->wMilliseconds = timefields.Milliseconds; + + return TRUE; +} diff --git a/lib/winapi/timezoneapi.h b/lib/winapi/timezoneapi.h index 7dba20d54..ec0d24eb0 100644 --- a/lib/winapi/timezoneapi.h +++ b/lib/winapi/timezoneapi.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT // SPDX-FileCopyrightText: 2023 Ryan Wendland +// SPDX-FileCopyrightText: 2025 Stefan Schmidt #ifndef __TIMEZONEAPI_H__ #define __TIMEZONEAPI_H__ @@ -29,6 +30,8 @@ typedef struct _TIME_ZONE_INFORMATION DWORD GetTimeZoneInformation (LPTIME_ZONE_INFORMATION lpTimeZoneInformation); +BOOL FileTimeToSystemTime (const FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime); + #ifdef __cplusplus } #endif From 1ac42bb9f8a95162e0ab2bc9dcb6c8be1a98aec5 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Tue, 18 Feb 2025 05:24:28 +0100 Subject: [PATCH 09/10] winapi: Implement CompareFileTime() --- lib/winapi/fileapi.h | 1 + lib/winapi/filemanip.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/lib/winapi/fileapi.h b/lib/winapi/fileapi.h index 64fc9d08a..6dfaaca30 100644 --- a/lib/winapi/fileapi.h +++ b/lib/winapi/fileapi.h @@ -18,6 +18,7 @@ DWORD GetFileAttributesA (LPCSTR lpFileName); BOOL GetFileAttributesExA (LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation); BOOL SetFileAttributesA (LPCSTR lpFileName, DWORD dwFileAttributes); +LONG CompareFileTime (const FILETIME *lpFileTime1, const FILETIME *lpFileTime2); BOOL GetFileTime (HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime); BOOL SetFileTime (HANDLE hFile, const FILETIME *lpCreationTime, const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime); diff --git a/lib/winapi/filemanip.c b/lib/winapi/filemanip.c index 6be700f0f..31140d264 100644 --- a/lib/winapi/filemanip.c +++ b/lib/winapi/filemanip.c @@ -106,6 +106,28 @@ BOOL SetFileAttributesA (LPCSTR lpFileName, DWORD dwFileAttributes) return TRUE; } +LONG CompareFileTime (const FILETIME *lpFileTime1, const FILETIME *lpFileTime2) +{ + ULARGE_INTEGER filetime1; + ULARGE_INTEGER filetime2; + + assert(lpFileTime1 != NULL); + assert(lpFileTime2 != NULL); + + filetime1.LowPart = lpFileTime1->dwLowDateTime; + filetime1.HighPart = lpFileTime1->dwHighDateTime; + filetime2.LowPart = lpFileTime2->dwLowDateTime; + filetime2.HighPart = lpFileTime2->dwHighDateTime; + + if (filetime1.QuadPart < filetime2.QuadPart) { + return -1; + } + if (filetime1.QuadPart > filetime2.QuadPart) { + return 1; + } + return 0; +} + BOOL GetFileTime (HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime) { NTSTATUS status; From 21e7b0ffed6eec57b938ae3db7e2a02d46d4d463 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Tue, 18 Feb 2025 05:38:31 +0100 Subject: [PATCH 10/10] winapi: Implement SystemTimeToFileTime() --- lib/winapi/timezoneapi.c | 27 +++++++++++++++++++++++++++ lib/winapi/timezoneapi.h | 1 + 2 files changed, 28 insertions(+) diff --git a/lib/winapi/timezoneapi.c b/lib/winapi/timezoneapi.c index 217d61609..2dea55206 100644 --- a/lib/winapi/timezoneapi.c +++ b/lib/winapi/timezoneapi.c @@ -242,3 +242,30 @@ BOOL FileTimeToSystemTime (const FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime return TRUE; } + +BOOL SystemTimeToFileTime (const SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime) +{ + if (!lpSystemTime || !lpFileTime) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + TIME_FIELDS timefields; + timefields.Year = lpSystemTime->wYear; + timefields.Month = lpSystemTime->wMonth; + timefields.Day = lpSystemTime->wDay; + timefields.Hour = lpSystemTime->wHour; + timefields.Minute = lpSystemTime->wMinute; + timefields.Second = lpSystemTime->wSecond; + timefields.Milliseconds = lpSystemTime->wMilliseconds; + + LARGE_INTEGER filetime; + if (!RtlTimeFieldsToTime(&timefields, &filetime)) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + lpFileTime->dwLowDateTime = filetime.LowPart; + lpFileTime->dwHighDateTime = filetime.HighPart; + return TRUE; +} diff --git a/lib/winapi/timezoneapi.h b/lib/winapi/timezoneapi.h index ec0d24eb0..09e2b1187 100644 --- a/lib/winapi/timezoneapi.h +++ b/lib/winapi/timezoneapi.h @@ -31,6 +31,7 @@ typedef struct _TIME_ZONE_INFORMATION DWORD GetTimeZoneInformation (LPTIME_ZONE_INFORMATION lpTimeZoneInformation); BOOL FileTimeToSystemTime (const FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime); +BOOL SystemTimeToFileTime (const SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime); #ifdef __cplusplus }