Add missing TUs for Wii/Shield retail (+ filename cleanup) (#3072)

* Fix GCN_mem_alloc.c filename capitalization

* Fix up TRK file names in Wii/Shield splits

* Add string_TRK

* Add cc_gdev

* Add Shield-only wstring TUs

* Implement NdevExi2A

* Add missing JSystem TUs (more are still missing from ShieldD)

* Clean up includes
This commit is contained in:
Max Roncace
2026-01-29 17:18:08 -05:00
committed by GitHub
parent c161523338
commit 050ebb4471
52 changed files with 2741 additions and 74 deletions
@@ -9,9 +9,15 @@ extern "C" {
size_t wcstombs(char* dst, const wchar_t* src, size_t n);
int mbtowc(wchar_t* pwc, const char* s, size_t n);
int mbstowcs(wchar_t* param_0, const char* param_1, int param_2);
int __mbtowc_noconv(wchar_t*, const char*, size_t);
int __wctomb_noconv(char*, wchar_t);
int mbsrtowcs_s(size_t* retval, wchar_t* dst, unsigned int dstsz, const char** param_4, size_t len,
int param_6);
#ifdef __cplusplus
}
#endif
@@ -12,7 +12,7 @@ int fprintf(FILE* stream, const char* format, ...);
int printf(const char* format, ...);
int sprintf(char* s, const char* format, ...);
int snprintf(char* s, size_t n, const char* format, ...);
int vsnprintf(char* s, size_t n, const char* format, va_list arg);
int vsnprintf(char* s, size_t n, const char* fmt, va_list args);
int vsprintf(char* s, const char* format, va_list arg);
int vprintf(const char* format, va_list arg);
@@ -0,0 +1,18 @@
#ifndef _MSL_COMMON_WCSTOUL_H
#define _MSL_COMMON_WCSTOUL_H
#include <wstring.h>
#ifdef __cplusplus
extern "C" {
#endif
size_t wcstoul(wchar_t* param_1, wchar_t** param_2, int param_3);
size_t wcstol(wchar_t* param_1, wchar_t** param_2, int param_3);
#ifdef __cplusplus
}
#endif
#endif /* _MSL_COMMON_WCSTOUL_H */
@@ -0,0 +1,18 @@
#ifndef _MSL_COMMON_WMEM_H
#define _MSL_COMMON_WMEM_H
#include <cstddef>
#ifdef __cplusplus
extern "C" {
#endif
void wmemcpy(wchar_t* dst, const wchar_t* src, size_t n);
const wchar_t* wmemchr(const wchar_t* str, wchar_t needle, int max_len);
#ifdef __cplusplus
}
#endif
#endif /* _MSL_COMMON_WMEM_H */
@@ -0,0 +1,20 @@
#ifndef _MSL_COMMON_WPRINTF_H
#define _MSL_COMMON_WPRINTF_H
#include <wstring.h>
#include <cstddef>
#include <cstdarg>
#ifdef __cplusplus
extern "C" {
#endif
int swprintf(wchar_t *dst, size_t maxlen, const wchar_t *fmt, ...);
int vsnwprintf_s(wchar_t* str, size_t n, const wchar_t* fmt, va_list args);
#ifdef __cplusplus
}
#endif
#endif /* _MSL_COMMON_WPRINTF_H */
@@ -0,0 +1,23 @@
#ifndef _MSL_COMMON_WSCANF_H
#define _MSL_COMMON_WSCANF_H
#include <wstring.h>
#include <cstddef>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
wchar_t* WCharStr;
size_t MaxCharCount;
size_t CharsWritten;
} __OutStrCtrl;
wchar_t __wStringRead(wString* src, wchar_t param_1, wchar_t param_2);
#ifdef __cplusplus
}
#endif
#endif /* _MSL_COMMON_WSCANF_H */
@@ -7,6 +7,12 @@
extern "C" {
#endif
typedef struct wString {
wchar_t* buffer;
size_t field_0x4;
size_t field_0x8;
} wString;
size_t wcslen(const wchar_t*);
wchar_t* wcscpy(wchar_t*, const wchar_t*);
wchar_t* wcsncpy(wchar_t*, const wchar_t*, size_t);
@@ -2,8 +2,124 @@
#include <cstring>
#include <locale>
#include "errno.h"
#include "global.h"
extern void __msl_runtime_constraint_violation_s(const char* msg, void* ptr, int error);
static unsigned int is_utf8_complete(const char* buf, unsigned int len) {
char start_byte;
int checked_cnt;
int conts;
int rem_conts;
if (len == 0) {
return -1;
}
start_byte = buf[0];
if (start_byte == 0) {
return 0;
}
if ((start_byte & 0x80) == 0) {
return 1;
}
if ((start_byte & 0xe0) == 0xc0) {
conts = 1;
} else if ((start_byte & 0xf0) == 0xe0) {
conts = 2;
} else if ((start_byte & 0xf8) == 0xf0) {
conts = 3;
} else if ((start_byte & 0xfc) == 0xf8) {
conts = 4;
} else if ((start_byte & 0xfe) == 0xfc) {
conts = 5;
} else {
return 0xffffffff;
}
checked_cnt = 0;
for (rem_conts = conts; rem_conts > 0; rem_conts--) {
if ((buf[checked_cnt + 1] & 0xc0) != 0x80) {
return 0xffffffff;
}
checked_cnt++;
}
if (len >= checked_cnt + 1U) {
return conts + 1;
}
return 0xfffffffe;
}
static int __utf8_to_unicode(wchar_t* dst, const char* src, unsigned int len) {
short byte_cnt;
int remaining;
int codepoint;
codepoint = 0;
if (src == NULL) {
return 0;
}
if (len == 0) {
return -1;
}
byte_cnt = is_utf8_complete(src, len);
if (byte_cnt < 0) {
return -1;
}
switch (byte_cnt) {
case 6:
codepoint = *src & ((1 << 2) - 1);
break;
case 5:
codepoint = *src & ((1 << 3) - 1);
break;
case 4:
codepoint = *src & ((1 << 4) - 1);
break;
case 3:
codepoint = *src & ((1 << 5) - 1);
break;
case 2:
codepoint = *src & ((1 << 6) - 1);
break;
case 1:
codepoint = *src;
break;
}
for (remaining = byte_cnt - 1; remaining > 0; remaining--) {
codepoint <<= 6;
codepoint |= *++src & 0x7f;
}
if (codepoint == 0) {
remaining = 0;
} else if (codepoint < 0 || codepoint < 0x80) {
remaining = 1;
} else if (codepoint < 0x800) {
remaining = 2;
} else if (codepoint < 0x10000) {
remaining = 3;
} else if (codepoint < 0x200000) {
remaining = 4;
} else if (codepoint < 0x4000000) {
remaining = 5;
} else {
remaining = 6;
}
if (remaining != byte_cnt) {
return -1;
}
if (dst != NULL) {
*dst = codepoint;
}
return byte_cnt;
}
#if !PLATFORM_GCN
int mbtowc(wchar_t* pwc, const char* s, size_t n) {
return _current_locale.ctype_cmpt_ptr->decode_mb(pwc, s, n);
@@ -67,6 +183,32 @@ int __wctomb_noconv(char* s, wchar_t wchar) {
return 1;
}
int mbstowcs(wchar_t* param_0, const char* param_1, int param_2) {
unsigned int i;
int decoded_cnt;
int remaining = strlen(param_1);
if (param_0 != NULL) {
for (i = 0; i < param_2; i++) {
if (param_1[0] != '\0') {
decoded_cnt =
_current_locale.ctype_cmpt_ptr->decode_mb(param_0++, param_1, remaining);
if (decoded_cnt > 0) {
param_1 += decoded_cnt;
remaining -= decoded_cnt;
continue;
}
return -1;
}
param_0[0] = L'\0';
break;
}
} else {
i = 0;
}
return i;
}
int wctomb(char* s, wchar_t wchar) {
#if PLATFORM_GCN
return (unicode_to_UTF8(s, wchar));
@@ -101,3 +243,67 @@ size_t wcstombs(char* s, const wchar_t* pwcs, size_t n) {
return chars_written;
}
int mbsrtowcs_s(size_t* retval, wchar_t* dst, unsigned int dstsz, const char** param_4,
size_t len, int param_6) {
wchar_t* var_r27;
const char* var_r24;
unsigned int var_r25;
int var_r26;
wchar_t sp08[4];
if (retval == NULL || param_4 == NULL || *param_4 == NULL || param_6 == 0 ||
(dst != NULL && (len > 0x7fffffff || dstsz > 0x7fffffff || dstsz < len)))
{
__msl_runtime_constraint_violation_s(NULL, NULL, 0x22);
if (retval != NULL) {
*retval = 0xffffffff;
}
return 0x22;
}
var_r24 = *param_4;
var_r26 = strlen(var_r24);
for (var_r25 = 0; var_r25 < len; var_r25++) {
if (*var_r24 != '\0') {
int var_r3_1;
if (dst == NULL) {
var_r27 = sp08;
} else {
var_r27 = dst++;
}
if (var_r24 != NULL) {
var_r3_1 = is_utf8_complete(var_r24, var_r26);
if (var_r3_1 < 0xfffffffe) {
if (var_r27 != NULL) {
var_r3_1 = __utf8_to_unicode(var_r27, var_r24, var_r26);
} else if (var_r3_1 == 0xffffffff) {
errno = 0x58;
}
}
} else {
if (var_r27 != NULL) {
*var_r27 = L'\0';
}
var_r3_1 = 0;
}
if (var_r3_1 <= 0) {
break;
}
var_r24 += var_r3_1;
var_r26 -= var_r3_1;
} else {
if (dst != NULL) {
*dst = 0;
*param_4 = 0;
}
break;
}
}
*retval = var_r25;
return 0;
}
@@ -1550,7 +1550,7 @@ int vprintf(const char* format, va_list arg) {
return ret;
}
int vsnprintf(char* s, size_t n, const char* format, va_list arg) {
int vsnprintf(char* s, size_t n, const char* fmt, va_list args) {
int end;
__OutStrCtrl osc;
osc.CharStr = s;
@@ -1558,9 +1558,9 @@ int vsnprintf(char* s, size_t n, const char* format, va_list arg) {
osc.CharsWritten = 0;
#if PLATFORM_GCN
end = __pformatter(&__StringWrite, &osc, format, arg);
end = __pformatter(&__StringWrite, &osc, fmt, args);
#else
end = __pformatter(&__StringWrite, &osc, format, arg, 0);
end = __pformatter(&__StringWrite, &osc, fmt, args, 0);
#endif
if (s) {
@@ -72,7 +72,7 @@ unsigned long __strtoul(int base, int max_width, int (*ReadProc)(void*, int, int
scan_state = need_digit;
break;
case 4:
case leading_zero:
if (c == 'X' || c == 'x') {
base = 16;
scan_state = need_digit;
@@ -0,0 +1,224 @@
#include <wcstoul.h>
#include <errno.h>
#include <wctype_api.h>
#include <wscanf.h>
#include <climits>
#include <locale>
enum scan_states {
start = 0x01,
check_for_zero = 0x02,
leading_zero = 0x04,
need_digit = 0x08,
digit_loop = 0x10,
finished = 0x20,
failure = 0x40
};
#define final_state(scan_state) (scan_state & (finished | failure))
#define success(scan_state) (scan_state & (leading_zero | digit_loop | finished))
#define fetch() (count++, (*read_proc)(read_proc_arg, 0, 0))
static size_t __wcstoul(int base, int max_width,
wchar_t (*read_proc)(wString* src, wchar_t param_1, wchar_t param_2),
void* read_proc_arg, int* chars_scanned, int* negative, int* overflow) {
int scan_state;
int count;
int spaces;
unsigned int value;
unsigned int value_max;
wchar_t c;
count = 0;
scan_state = 1;
spaces = 0;
value = 0;
value_max = 0;
*negative = *overflow = 0;
if (base < 0 || base == 1 || base > 36 || max_width < 1) {
scan_state = failure;
} else {
c = fetch();
}
if (base != 0) {
value_max = ULONG_MAX / base;
}
// NOTE: c is uninitialized if the parameter validation above fails. In practice, this doesn't
// matter because the third condition will always fail in this scenario anyway.
while (count <= max_width && c != -1 && !final_state(scan_state)) {
switch (scan_state) {
case start:
if (c >= 0x100 ?
0 :
_current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & wctype_space) {
c = read_proc(read_proc_arg, 0, 0);
spaces++;
} else {
if (c == L'+') {
c = fetch();
} else if (c == L'-') {
c = fetch();
*negative = 1;
}
scan_state = check_for_zero;
}
break;
case check_for_zero:
if ((base == 0 || base == 16) && c == L'0') {
scan_state = leading_zero;
c = fetch();
} else {
scan_state = need_digit;
}
break;
case leading_zero:
if (c == L'X' || c == L'x') {
base = 16;
scan_state = need_digit;
c = fetch();
} else {
if (base == 0) {
base = 8;
}
scan_state = digit_loop;
}
break;
case need_digit:
case digit_loop:
if (base == 0) {
base = 10;
}
if (value_max == 0) {
value_max = ULONG_MAX / base;
}
if (c >= 0x100 ? 0 : _current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & wctype_digit) {
c -= L'0';
if (c >= base) {
if (scan_state == digit_loop) {
scan_state = finished;
} else {
scan_state = failure;
}
c += L'0';
break;
}
} else {
int temp;
if (!(c >= 0x100 ?
0 :
_current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & wctype_alpha)) {
goto label;
}
temp = 1;
if (c <= 0xFF) {
temp = 0;
}
if ((temp ? c :
_current_locale.ctype_cmpt_ptr->upper_map_ptr[c]) -
0x37 >=
base) {
label:
if (scan_state == digit_loop) {
scan_state = finished;
} else {
scan_state = failure;
}
continue;
} else {
c = (wchar_t)(c >= 0x100 ?
c :
_current_locale.ctype_cmpt_ptr->wupper_map_ptr[c]) -
0x37;
}
}
if (value > value_max) {
*overflow = 1;
}
value *= base;
if (c > ULONG_MAX - value) {
*overflow = 1;
}
scan_state = digit_loop;
value += c;
c = fetch();
break;
}
}
if (!success(scan_state)) {
value = 0;
*chars_scanned = 0;
} else {
*chars_scanned = count + spaces - 1;
}
read_proc(read_proc_arg, c, 1);
return value;
}
size_t wcstoul(wchar_t* param_1, wchar_t** param_2, int param_3) {
wString sp18;
size_t retval;
int sp10[2]; // not sure if this should be an array, but the stack doesn't match otherwise
int sp0C;
int sp08;
sp18.buffer = param_1;
sp18.field_0x4 = 0;
retval = __wcstoul(param_3, 0x7fffffff, __wStringRead, &sp18, sp10, &sp0C, &sp08);
if (param_2 != NULL) {
*param_2 = param_1 + sp10[0];
}
if (sp08 != 0) {
errno = 0x22;
return -1;
}
if (sp0C != 0) {
return -retval;
} else {
return retval;
}
}
size_t wcstol(wchar_t* param_1, wchar_t** param_2, int param_3) {
size_t retval;
wString sp18;
int sp10[2]; // not sure if this should be an array, but the stack doesn't match otherwise
int sp0C;
int sp08;
sp18.buffer = param_1;
sp18.field_0x4 = 0;
retval = __wcstoul(param_3, 0x7fffffff, __wStringRead, &sp18, sp10, &sp0C, &sp08);
if (param_2 != NULL) {
*param_2 = param_1 + sp10[0];
}
if (sp08 != 0 || (sp0C == 0 && retval > 0x7fffffff) || (sp0C != 0 && retval > 0x80000000)) {
errno = 0x22;
return sp0C != 0 ? 0x80000000 : 0x7fffffff;
}
if (sp0C != 0) {
return -retval;
} else {
return retval;
}
}
@@ -0,0 +1,19 @@
#include <wmem.h>
#include <cstddef>
#include <cstring>
void wmemcpy(wchar_t* dst, const wchar_t* src, size_t n) {
memcpy(dst, src, n * 2);
}
const wchar_t* wmemchr(const wchar_t* str, wchar_t needle, int max_len) {
int i;
for (i = 0; i != max_len; i++) {
if (*str == needle) {
return str;
}
str++;
}
return NULL;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,27 @@
#include <wscanf.h>
#include <wstring.h>
wchar_t __wStringRead(wString* src, wchar_t param_1, wchar_t param_2) {
switch (param_2) {
case 0:
param_2 = *src->buffer;
if (param_2 == 0) {
src->field_0x4 = 1;
return 0xFFFF;
} else {
src->buffer++;
return param_2;
}
case 1:
if (src->field_0x4 == 0) {
src->buffer--;
} else {
src->field_0x4 = 0;
}
return param_1;
case 2:
return src->field_0x4;
default:
return 0;
}
}