summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/JSystem/J3DGraphAnimator/J3DJoint.cpp8
-rw-r--r--src/JSystem/J3DU/J3DUFur.cpp29
-rw-r--r--src/JSystem/J3DU/J3DUMotion.cpp18
-rw-r--r--src/JSystem/J3DU/J3DUShadow.cpp22
-rw-r--r--src/JSystem/JAudio2/JAUAudience.cpp5
-rw-r--r--src/JSystem/JAudio2/JAUSoundObject.cpp11
-rw-r--r--src/NdevExi2A/DebuggerDriver.c174
-rw-r--r--src/NdevExi2A/exi2.c167
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/mbstring.h6
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/printf.h2
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wcstoul.h18
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wmem.h18
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wprintf.h20
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wscanf.h23
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wstring.h6
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/mbstring.c206
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/printf.c6
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/strtoul.c2
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wcstoul.c224
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wmem.c19
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wprintf.c1406
-rw-r--r--src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wscanf.c27
-rw-r--r--src/PowerPC_EABI_Support/Runtime/Src/GCN_mem_alloc.c (renamed from src/PowerPC_EABI_Support/Runtime/Src/GCN_Mem_Alloc.c)0
-rw-r--r--src/TRK_MINNOW_DOLPHIN/debugger/embedded/MetroTRK/Portable/string_TRK.c10
-rw-r--r--src/TRK_MINNOW_DOLPHIN/gamedev/cust_connection/utils/gc/cc_gdev.c105
-rw-r--r--src/odemuexi2/DebuggerDriver.c4
26 files changed, 2521 insertions, 15 deletions
diff --git a/src/JSystem/J3DGraphAnimator/J3DJoint.cpp b/src/JSystem/J3DGraphAnimator/J3DJoint.cpp
index 00fd7d1935..4091a3b7a1 100644
--- a/src/JSystem/J3DGraphAnimator/J3DJoint.cpp
+++ b/src/JSystem/J3DGraphAnimator/J3DJoint.cpp
@@ -26,14 +26,6 @@ J3DMtxBuffer* J3DMtxCalc::mMtxBuffer;
J3DJoint* J3DMtxCalc::mJoint;
-inline s32 checkScaleOne(const Vec& param_0) {
- if (param_0.x == 1.0f && param_0.y == 1.0f && param_0.z == 1.0f) {
- return true;
- } else {
- return false;
- }
-}
-
void J3DMtxCalcCalcTransformBasic::calcTransform(J3DTransformInfo const& transInfo) {
J3DJoint* joint = J3DMtxCalc::getJoint();
J3DMtxBuffer* mtxBuf = J3DMtxCalc::getMtxBuffer();
diff --git a/src/JSystem/J3DU/J3DUFur.cpp b/src/JSystem/J3DU/J3DUFur.cpp
new file mode 100644
index 0000000000..8920ff0517
--- /dev/null
+++ b/src/JSystem/J3DU/J3DUFur.cpp
@@ -0,0 +1,29 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DU/J3DUFur.h"
+
+#include "JSystem/J3DGraphAnimator/J3DModel.h"
+#include "JSystem/J3DGraphBase/J3DMaterial.h"
+#include "JSystem/J3DGraphBase/J3DVertex.h"
+
+static void dummy() {
+ J3DShape* shape;
+ J3DMaterial* material = shape->getMaterial();
+ J3DJoint* joint = material->getJoint();
+
+ J3DVertexBuffer* vtxBuf;
+ vtxBuf->swapTransformedVtxPos();
+ J3DVertexData* vtxData = vtxBuf->getVertexData();
+ vtxBuf->getTransformedVtxPos(0);
+ vtxBuf->getCurrentVtxNrm();
+ vtxBuf->setCurrentVtxPos(NULL);
+
+ J3DModel* model;
+ model->getVertexBuffer();
+
+ J3DModelData* modelData;
+ vtxData->getNrmNum();
+ modelData->getNrmNum();
+ vtxData->getVtxNum();
+ modelData->getVtxNum();
+}
diff --git a/src/JSystem/J3DU/J3DUMotion.cpp b/src/JSystem/J3DU/J3DUMotion.cpp
new file mode 100644
index 0000000000..b8e7096c91
--- /dev/null
+++ b/src/JSystem/J3DU/J3DUMotion.cpp
@@ -0,0 +1,18 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DU/J3DUMotion.h"
+
+#include "JSystem/J3DGraphAnimator/J3DJoint.h"
+#include "JSystem/J3DGraphLoader/J3DModelLoader.h"
+#include "JSystem/JMath/JMath.h"
+
+static void dummy() {
+ J3DMtxCalcJ3DSysInitSoftimage* img;
+ Vec* vec;
+ Mtx mtx;
+ img->init(*vec, mtx);
+ checkScaleOne(*vec);
+ J3DMtxCalc::getMtxBuffer();
+ JMAFastReciprocal(0.0f);
+ JMath::fastReciprocal(0.0f);
+}
diff --git a/src/JSystem/J3DU/J3DUShadow.cpp b/src/JSystem/J3DU/J3DUShadow.cpp
new file mode 100644
index 0000000000..5a44bea051
--- /dev/null
+++ b/src/JSystem/J3DU/J3DUShadow.cpp
@@ -0,0 +1,22 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/J3DU/J3DUShadow.h"
+
+#include "JSystem/JGeometry.h"
+#include "JSystem/JMath/JMath.h"
+#include "JSystem/JUtility/JUTTexture.h"
+
+void dummy() {
+ JMAAbs(0.0f);
+ JMathInlineVEC::C_VECDotProduct(NULL, NULL);
+ JGeometry::TVec3<f32>* vec;
+ vec->dot(*vec);
+ vec->length();
+
+ JUTTexture* tex;
+ tex->getCaptureFlag();
+ tex->getFormat();
+ JMath::fastSqrt<f32>(0.0f);
+ JUTTexture tex2;
+ tex2.setCaptureFlag(false);
+}
diff --git a/src/JSystem/JAudio2/JAUAudience.cpp b/src/JSystem/JAudio2/JAUAudience.cpp
new file mode 100644
index 0000000000..f21b3f32c6
--- /dev/null
+++ b/src/JSystem/JAudio2/JAUAudience.cpp
@@ -0,0 +1,5 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/JAudio2/JAUAudience.h"
+
+// NONMATCHING
diff --git a/src/JSystem/JAudio2/JAUSoundObject.cpp b/src/JSystem/JAudio2/JAUSoundObject.cpp
new file mode 100644
index 0000000000..0a630c8ca2
--- /dev/null
+++ b/src/JSystem/JAudio2/JAUSoundObject.cpp
@@ -0,0 +1,11 @@
+#include "JSystem/JSystem.h" // IWYU pragma: keep
+
+#include "JSystem/JAudio2/JAUSoundObject.h"
+
+#include "JSystem/JGeometry.h"
+
+static void dummy() {
+ JGeometry::TVec3<f32>* vec_1;
+ JGeometry::TVec3<f32>* vec_2;
+ *vec_1 = *vec_2;
+}
diff --git a/src/NdevExi2A/DebuggerDriver.c b/src/NdevExi2A/DebuggerDriver.c
new file mode 100644
index 0000000000..8bbc082f23
--- /dev/null
+++ b/src/NdevExi2A/DebuggerDriver.c
@@ -0,0 +1,174 @@
+#include "NdevExi2A/DebuggerDriver.h"
+
+#include "NdevExi2A/exi2.h"
+#include <dolphin/exi.h>
+#include <dolphin/os.h>
+
+static s32 __DBRecvDataSize;
+static u32 __DBRecvMail;
+
+static u8 EXIInputFlag;
+
+static MtrCallback __DBDbgCallback;
+static MtrCallback __DBMtrCallback;
+
+static u8 SendCount = 0x80;
+
+#define IS_TRUE(x) ((x) != FALSE)
+#define IS_FALSE(x) !IS_TRUE(x)
+#define ROUND_UP(x, align) (((x) + (align)-1) & (-(align)))
+
+void __DBMtrHandler(s32 param_0, OSContext* ctx) {
+ EXIInputFlag = 1;
+ if (__DBMtrCallback != (void*)NULL) {
+ __DBMtrCallback(0, ctx);
+ }
+}
+
+void __DBIntrHandler(s16 param_0, OSContext* ctx) {
+ *__PIRegs = 0x1000;
+ if (__DBDbgCallback != NULL) {
+ __DBDbgCallback(param_0, ctx);
+ }
+}
+
+void __DBCheckMailBox(void) {
+ u8 sp08;
+ u32 mail;
+ sp08 = __DBReadUSB_CSR();
+ if (!(sp08 & 0x8)) {
+ __DBReadMailbox(&mail);
+
+ if (ODEMUIsValidMail(mail)) {
+ __DBRecvMail = mail;
+ __DBRecvDataSize = ODEMUGetSize(mail);
+ EXIInputFlag = 1;
+ }
+ }
+}
+
+u8 __DBReadUSB_CSR() {
+ u8 result;
+ __DBEXIReadReg(0x34000000, &result, 1);
+ return result;
+}
+
+void DBInitComm(u8** a, MtrCallback callback) {
+ BOOL interrupts = OSDisableInterrupts();
+
+ //pEXIInputFlag = &EXIInputFlag;
+ *a = &EXIInputFlag;
+ __DBMtrCallback = callback;
+ __DBEXIInit();
+
+ OSRestoreInterrupts(interrupts);
+}
+
+void DBInitInterrupts(void) {
+ __OSMaskInterrupts(0x18000);
+ __OSMaskInterrupts(0x40);
+ __DBDbgCallback = &__DBMtrHandler;
+ __OSSetInterruptHandler(0x19, __DBIntrHandler);
+ __OSUnmaskInterrupts(0x40);
+}
+
+u32 DBQueryData(void) {
+ BOOL interrupts;
+ EXIInputFlag = 0;
+ if (__DBRecvDataSize == 0) {
+ interrupts = OSDisableInterrupts();
+ __DBCheckMailBox();
+ OSRestoreInterrupts(interrupts);
+ }
+ return __DBRecvDataSize;
+}
+
+BOOL DBRead(u32* buffer, s32 count) {
+ u32 v;
+ u32 interrupts = OSDisableInterrupts();
+ v = ODEMUGetPc2NngcOffset(__DBRecvMail) + 0x1000;
+
+ __DBRead(v, buffer, ROUND_UP(count, 4));
+
+ __DBRecvDataSize = 0;
+ EXIInputFlag = 0;
+
+ OSRestoreInterrupts(interrupts);
+
+ return 0;
+}
+
+BOOL DBWrite(void* src, u32 size) {
+ BOOL interrupts;
+ u32 v;
+ u32 mail;
+
+ interrupts = OSDisableInterrupts();
+
+ __DBWaitForSendMail();
+
+ SendCount++;
+ v = (SendCount & 0x1) ? 0x800 : 0;
+
+ while (!__DBWrite(v, src, ROUND_UP(size, 4)))
+ ;
+
+ __DBWaitForSendMail();
+
+ mail = ODEMUGenMailData(SendCount, size);
+ while (!__DBWriteMailbox(mail))
+ ;
+
+ __DBWaitForSendMail();
+
+ OSRestoreInterrupts(interrupts);
+
+ return 0;
+}
+
+void __DBWaitForSendMail() {
+ u8 busyFlag;
+ do {
+ busyFlag = __DBReadUSB_CSR();
+ } while (busyFlag & 0x4);
+}
+
+void DBOpen(void) {}
+
+void DBClose(void) {}
+
+static u32 ODEMUGetSize(u32 mail) {
+ return mail & 0x1FFF;
+}
+
+BOOL ODEMUIsValidMail(u32 mail) {
+ return (mail & 0x1F000000) == 0x1F000000;
+}
+
+u32 ODEMUGetPc2NngcOffset(u32 v) {
+ return ODEMUGetPage(v) & 0x1 ? 0x800 : 0;
+}
+
+u32 ODEMUGetPage(u32 v) {
+ return (v & 0xFF0000) >> 16;
+}
+
+u32 ODEMUGenMailData(u32 v, u32 size) {
+ return (0x1f000000 | ((v << 16) & 0xFF0000)) | (size & 0x1FFF);
+}
+
+void __DBReadMailbox(u32* out) {
+ __DBEXIReadReg(0x34000200, out, 4);
+}
+
+BOOL __DBRead(u32 param_0, void* dst, u32 count) {
+ return __DBEXIReadRam(((param_0 + 0xD10000) << 6) & 0x3FFFFF00, dst, count);
+}
+
+BOOL __DBWriteMailbox(u32 val) {
+ return __DBEXIWriteReg(0xB4000100, &val, 0x4);
+}
+
+BOOL __DBWrite(u32 param_0, void* dst, u32 count) {
+ return __DBEXIWriteRam((((param_0 + 0xD10000) << 6) & 0x3FFFFF00) | 0x80000000, dst, count);
+}
diff --git a/src/NdevExi2A/exi2.c b/src/NdevExi2A/exi2.c
new file mode 100644
index 0000000000..83035a0991
--- /dev/null
+++ b/src/NdevExi2A/exi2.c
@@ -0,0 +1,167 @@
+#include "NdevExi2A/exi2.h"
+
+#include <revolution/os.h>
+
+#define IS_TRUE(x) ((x) != FALSE)
+#define IS_FALSE(x) !IS_TRUE(x)
+#define ROUND_UP(x, align) (((x) + (align)-1) & (-(align)))
+
+BOOL __EXI2Select() {
+ u32 regs = __EXIRegs[10];
+ regs &= 0x405;
+ regs |= 0xC0;
+ __EXIRegs[10] = regs;
+ return TRUE;
+}
+
+BOOL __EXI2Deselect() {
+ u32 regs = __EXIRegs[10];
+ __EXIRegs[10] = regs & 0x405;
+ return TRUE;
+}
+
+BOOL __EXI2Sync() {
+ while (__EXIRegs[13] & 0x1) {
+ }
+ return TRUE;
+}
+
+BOOL __EXI2Imm(u32* param_0, int width, int param_2) {
+ int i1; // r31
+ int i2; // r30
+ u32 var_r29;
+ u8* var_r28;
+ u32 var_r25;
+
+ if (param_2 != 0) {
+ var_r29 = 0;
+ for (i1 = 0; i1 < width; i1++) {
+ var_r29 |= ((u8*)param_0)[i1] << ((3 - i1) << 3);
+ }
+ __EXIRegs[14] = var_r29;
+ }
+
+ __EXIRegs[13] = 0x1 | (param_2 << 2) | ((width - 1) << 4);
+ __EXI2Sync();
+
+ if (param_2 == 0) {
+ var_r28 = (u8*)param_0;
+ var_r25 = __EXIRegs[14];
+ for (i2 = 0; i2 < width; i2++) {
+ *var_r28 = var_r25 >> ((3 - i2) << 3);
+ var_r28++;
+ }
+ }
+
+ return 1;
+}
+
+void __DBEXIInit() {
+ u8 sp08;
+
+ __OSMaskInterrupts(0x18000);
+
+ while ((__EXIRegs[13] & 0x1) == 0x1) {
+ };
+
+ __EXIRegs[10] = 0;
+ sp08 = 0xD4;
+ __DBEXIWriteReg(0xB4000000, &sp08, 1);
+}
+
+BOOL __DBEXIReadReg(u32 param_0, void* dst, u32 param_2) {
+ int is_failed = FALSE;
+ u32 val = 0;
+
+ is_failed |= IS_FALSE(__EXI2Select());
+ is_failed |= IS_FALSE(__EXI2Imm(&param_0, 4, 1));
+ is_failed |= IS_FALSE(__EXI2Sync());
+ is_failed |= IS_FALSE(__EXI2Imm(&val, 4, 0));
+ is_failed |= IS_FALSE(__EXI2Sync());
+ is_failed |= IS_FALSE(__EXI2Deselect());
+
+ switch (param_2) {
+ case 1:
+ *(u8*)dst = val >> 24;
+ break;
+ case 2:
+ *(u16*)dst = (val >> 24) | ((val >> 8) & 0xff00);
+ break;
+ default:
+ *(u32*)dst = __EXISwap32(val);
+ break;
+ }
+ return IS_FALSE(is_failed);
+}
+
+BOOL __DBEXIWriteReg(u32 param_0, void* src, u32 width) {
+ int is_failed = FALSE;
+ u32 val;
+
+ switch (width) {
+ case 1:
+ val = (*(u8*)src & 0xFF) << 24;
+ break;
+ case 2:
+ val = ((*(u16*)src & 0xFF) << 24) | ((*(u16*)src & 0xff00) << 8);
+ break;
+ default:
+ val = __EXISwap32(*(u32*)src);
+ break;
+ }
+
+ is_failed |= IS_FALSE(__EXI2Select());
+ is_failed |= IS_FALSE(__EXI2Imm(&param_0, 4, 1));
+ is_failed |= IS_FALSE(__EXI2Sync());
+ is_failed |= IS_FALSE(__EXI2Imm(&val, 4, 1));
+ is_failed |= IS_FALSE(__EXI2Sync());
+ is_failed |= IS_FALSE(__EXI2Deselect());
+
+ return IS_FALSE(is_failed);
+}
+
+BOOL __DBEXIReadRam(u32 param_0, void* dst, int count) {
+ int is_failed = FALSE;
+ u32 cur_val;
+ u32* cursor = (u32*)dst;
+
+ is_failed |= IS_FALSE(__EXI2Select());
+ is_failed |= IS_FALSE(__EXI2Imm(&param_0, 4, 1));
+ is_failed |= IS_FALSE(__EXI2Sync());
+
+ while (count > 0) {
+ is_failed |= IS_FALSE(__EXI2Imm(&cur_val, 4, 0));
+ is_failed |= IS_FALSE(__EXI2Sync());
+ *cursor++ = cur_val;
+ count -= 4;
+ }
+
+ is_failed |= IS_FALSE(__EXI2Deselect());
+
+ return IS_FALSE(is_failed);
+}
+
+BOOL __DBEXIWriteRam(u32 param_0, void* src, int count) {
+ int is_failed = FALSE;
+ u32 cur_val;
+ u32* cursor = (u32*)src;
+
+ is_failed |= IS_FALSE(__EXI2Select());
+ is_failed |= IS_FALSE(__EXI2Imm(&param_0, 4, 1));
+ is_failed |= IS_FALSE(__EXI2Sync());
+
+ while (count > 0) {
+ cur_val = *cursor++;
+ is_failed |= IS_FALSE(__EXI2Imm(&cur_val, 4, 1));
+ is_failed |= IS_FALSE(__EXI2Sync());
+ count -= 4;
+ }
+
+ is_failed |= IS_FALSE(__EXI2Deselect());
+
+ return IS_FALSE(is_failed);
+}
+
+u32 __EXISwap32(u32 v) {
+ return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);
+}
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/mbstring.h b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/mbstring.h
index 5936adcc6c..0fb1d40b12 100644
--- a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/mbstring.h
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/mbstring.h
@@ -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
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/printf.h b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/printf.h
index d8322efb06..f4ed9bb876 100644
--- a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/printf.h
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/printf.h
@@ -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);
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wcstoul.h b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wcstoul.h
new file mode 100644
index 0000000000..c60b21ad75
--- /dev/null
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wcstoul.h
@@ -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 */
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wmem.h b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wmem.h
new file mode 100644
index 0000000000..4dd71cbd16
--- /dev/null
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wmem.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 */
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wprintf.h b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wprintf.h
new file mode 100644
index 0000000000..69a50f1f68
--- /dev/null
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wprintf.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 */
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wscanf.h b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wscanf.h
new file mode 100644
index 0000000000..37a81c6a22
--- /dev/null
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wscanf.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 */
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wstring.h b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wstring.h
index 8fbf40231b..b78ddf0ebe 100644
--- a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wstring.h
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/wstring.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);
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/mbstring.c b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/mbstring.c
index 2b03a829f4..d19c23d3f9 100644
--- a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/mbstring.c
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/mbstring.c
@@ -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;
+}
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/printf.c b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/printf.c
index b542d792e8..f1b6bd6413 100644
--- a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/printf.c
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/printf.c
@@ -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) {
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/strtoul.c b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/strtoul.c
index 2a93968f67..d0ed3aee67 100644
--- a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/strtoul.c
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/strtoul.c
@@ -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;
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wcstoul.c b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wcstoul.c
new file mode 100644
index 0000000000..c4bc89dd0d
--- /dev/null
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wcstoul.c
@@ -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;
+ }
+}
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wmem.c b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wmem.c
new file mode 100644
index 0000000000..3353086350
--- /dev/null
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wmem.c
@@ -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;
+}
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wprintf.c b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wprintf.c
new file mode 100644
index 0000000000..546c77c8d6
--- /dev/null
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wprintf.c
@@ -0,0 +1,1406 @@
+#include <wprintf.h>
+
+#include <ansi_fp.h>
+#include <mbstring.h>
+#include <wmem.h>
+#include <wscanf.h>
+#include <cmath>
+#include <cstdint>
+#include <cstring>
+#include <locale>
+#include <cstdarg>
+#include <cstddef>
+#include <va_list>
+
+#define LDBL_MANT_DIG 53
+
+#define TARGET_FLOAT_BITS 64
+#define TARGET_FLOAT_BYTES (TARGET_FLOAT_BITS / 8)
+#define TARGET_FLOAT_MAX_EXP LDBL_MAX_EXP
+#define TARGET_FLOAT_MANT_DIG LDBL_MANT_DIG
+#define TARGET_FLOAT_IMPLICIT_J_BIT 1
+#define TARGET_FLOAT_MANT_BITS (TARGET_FLOAT_MANT_DIG - TARGET_FLOAT_IMPLICIT_J_BIT)
+#define TARGET_FLOAT_EXP_BITS (TARGET_FLOAT_BITS - TARGET_FLOAT_MANT_BITS - 1)
+
+enum justification_options { left_justification, right_justification, zero_fill };
+
+enum sign_options { only_minus, sign_always, space_holder };
+
+enum argument_options {
+ normal_argument,
+ char_argument,
+ short_argument,
+ long_argument,
+ long_long_argument,
+ wchar_argument,
+
+ intmax_argument,
+ size_t_argument,
+ ptrdiff_argument,
+
+ long_double_argument,
+};
+
+typedef struct {
+ unsigned char justification_options;
+ unsigned char sign_options;
+ unsigned char precision_specified;
+ unsigned char alternate_form;
+ unsigned char argument_options;
+ wchar_t conversion_char;
+ int field_width;
+ int precision;
+} print_format;
+
+extern void __msl_runtime_constraint_violation_s(const char* msg, void* ptr, int error);
+
+const wchar_t* parse_format(const wchar_t* format_string, va_list* arg, print_format* format) {
+ print_format f;
+ const wchar_t* s = format_string;
+ wchar_t c;
+ int flag_found;
+ f.justification_options = right_justification;
+ f.sign_options = only_minus;
+ f.precision_specified = 0;
+ f.alternate_form = 0;
+ f.argument_options = normal_argument;
+ f.field_width = 0;
+ f.precision = 0;
+
+ if ((c = *++s) == '%') {
+ f.conversion_char = c;
+ *format = f;
+ return s + 1;
+ }
+
+ while (1) {
+ flag_found = 1;
+
+ switch (c) {
+ case '-':
+ f.justification_options = left_justification;
+ break;
+ case '+':
+ f.sign_options = sign_always;
+ break;
+ case ' ':
+ if (f.sign_options != sign_always) {
+ f.sign_options = space_holder;
+ }
+ break;
+ case '#':
+ f.alternate_form = 1;
+ break;
+ case '0':
+ if (f.justification_options != left_justification) {
+ f.justification_options = zero_fill;
+ }
+ break;
+ default:
+ flag_found = 0;
+ break;
+ }
+
+ if (flag_found) {
+ c = *++s;
+ } else {
+ break;
+ }
+ }
+
+ if (c == '*') {
+ if ((f.field_width = va_arg(*arg, int)) < 0) {
+ f.justification_options = left_justification;
+ f.field_width = -f.field_width;
+ }
+
+ c = *++s;
+ } else {
+ while ((c >= 0x100 ? 0 : _current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & 0x8) != 0) {
+ f.field_width = f.field_width * 10 + (c - '0');
+ c = *++s;
+ }
+ }
+
+ if (f.field_width > 509) {
+ f.conversion_char = 0xFFFF;
+ *format = f;
+ return s + 1;
+ }
+
+ if (c == '.') {
+ f.precision_specified = 1;
+
+ if ((c = *++s) == '*') {
+ if ((f.precision = va_arg(*arg, int)) < 0) {
+ f.precision_specified = 0;
+ }
+
+ c = *++s;
+ } else {
+ while ((c >= 0x100 ? 0 : _current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & 0x8) != 0)
+ {
+ f.precision = f.precision * 10 + (c - '0');
+ c = *++s;
+ }
+ }
+ }
+
+ flag_found = 1;
+
+ switch (c) {
+ case 'h':
+ f.argument_options = short_argument;
+
+ if (s[1] == 'h') {
+ f.argument_options = char_argument;
+ c = *++s;
+ }
+
+ break;
+
+ case 'l':
+ f.argument_options = long_argument;
+
+ if (s[1] == 'l') {
+ f.argument_options = long_long_argument;
+ c = *++s;
+ }
+ break;
+ case 'L':
+ f.argument_options = long_double_argument;
+ break;
+ case 'j':
+ f.argument_options = intmax_argument;
+ break;
+ case 't':
+ f.argument_options = ptrdiff_argument;
+ break;
+ case 'z':
+ f.argument_options = size_t_argument;
+ break;
+ default:
+ flag_found = 0;
+ break;
+ }
+
+ if (flag_found) {
+ c = *++s;
+ }
+
+ switch (f.conversion_char = c) {
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'o':
+ case 'x':
+ case 'X':
+ if (f.argument_options == long_double_argument) {
+ f.argument_options = 4;
+ }
+
+ if (!f.precision_specified) {
+ f.precision = 1;
+ } else if (f.justification_options == zero_fill) {
+ f.justification_options = right_justification;
+ }
+ break;
+
+ case 'f':
+ case 'F':
+ if (f.argument_options == short_argument || f.argument_options == intmax_argument ||
+ f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument ||
+ f.argument_options == long_long_argument)
+ {
+ f.conversion_char = 0xFFFF;
+ break;
+ }
+
+ if (!f.precision_specified) {
+ f.precision = 6;
+ }
+ break;
+
+ case 'a':
+ case 'A':
+ if (!f.precision_specified) {
+ f.precision = 0xD;
+ }
+
+ if (f.argument_options == short_argument || f.argument_options == intmax_argument ||
+ f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument ||
+ f.argument_options == long_long_argument || f.argument_options == char_argument)
+ {
+ f.conversion_char = 0xFFFF;
+ }
+
+ break;
+
+ case 'g':
+ case 'G':
+ if (!f.precision) {
+ f.precision = 1;
+ }
+
+ case 'e':
+ case 'E':
+ if (f.argument_options == short_argument || f.argument_options == intmax_argument ||
+ f.argument_options == size_t_argument || f.argument_options == ptrdiff_argument ||
+ f.argument_options == long_long_argument || f.argument_options == char_argument)
+ {
+ f.conversion_char = 0xFFFF;
+ break;
+ }
+
+ if (!f.precision_specified) {
+ f.precision = 6;
+ }
+ break;
+
+ case 'p':
+ f.argument_options = long_argument;
+ f.alternate_form = 1;
+ f.conversion_char = 'x';
+ f.precision = 8;
+ break;
+
+ case 'c':
+ if (f.argument_options == long_argument) {
+ f.argument_options = wchar_argument;
+ } else {
+ if (f.precision_specified || f.argument_options != normal_argument) {
+ f.conversion_char = 0xFFFF;
+ }
+ }
+
+ break;
+
+ case 's':
+ if (f.argument_options == long_argument) {
+ f.argument_options = wchar_argument;
+ } else {
+ if (f.argument_options != normal_argument) {
+ f.conversion_char = 0xFFFF;
+ }
+ }
+
+ break;
+
+ case 'n':
+ if (f.argument_options == long_double_argument) {
+ f.argument_options = 0x4;
+ }
+
+ break;
+
+ default:
+ f.conversion_char = 0xFFFF;
+ break;
+ }
+
+ *format = f;
+ return s + 1;
+}
+
+wchar_t* long2str(signed long num, wchar_t* buff, print_format format) {
+ unsigned long unsigned_num, base;
+ wchar_t* p;
+ int n, digits;
+ int minus = 0;
+ unsigned_num = num;
+ minus = 0;
+
+ p = buff;
+ *--p = 0;
+ digits = 0;
+
+ if (!num && !format.precision && !(format.alternate_form && format.conversion_char == 'o')) {
+ return p;
+ }
+
+ switch (format.conversion_char) {
+ case 'd':
+ case 'i':
+ base = 10;
+
+ if (num < 0) {
+ if (num != 0x80000000L) {
+ unsigned_num = -unsigned_num;
+ }
+
+ minus = 1;
+ }
+ break;
+
+ case 'o':
+ base = 8;
+ format.sign_options = only_minus;
+ break;
+
+ case 'u':
+ base = 10;
+ format.sign_options = only_minus;
+ break;
+
+ case 'x':
+ case 'X':
+ base = 16;
+ format.sign_options = only_minus;
+ break;
+ }
+
+ do {
+ n = unsigned_num % base;
+ unsigned_num /= base;
+
+ if (n < 10) {
+ n += '0';
+ } else {
+ n -= 10;
+
+ if (format.conversion_char == 'x') {
+ n += 'a';
+ } else {
+ n += 'A';
+ }
+ }
+
+ *--p = n;
+ ++digits;
+ } while (unsigned_num != 0);
+
+ if (base == 8 && format.alternate_form && *p != '0') {
+ *--p = '0';
+ ++digits;
+ }
+
+ if (format.justification_options == zero_fill) {
+ format.precision = format.field_width;
+
+ if (minus || format.sign_options != only_minus)
+ --format.precision;
+
+ if (base == 16 && format.alternate_form)
+ format.precision -= 2;
+ }
+
+ if (buff - p + format.precision > 509)
+ return 0;
+
+ while (digits < format.precision) {
+ *--p = '0';
+ ++digits;
+ }
+
+ if (base == 16 && format.alternate_form) {
+ *--p = format.conversion_char;
+ *--p = '0';
+ }
+
+ if (minus) {
+ *--p = '-';
+ } else if (format.sign_options == sign_always) {
+ *--p = '+';
+ } else if (format.sign_options == space_holder) {
+ *--p = ' ';
+ }
+
+ return p;
+}
+
+wchar_t* longlong2str(signed long long num, wchar_t* pBuf, print_format fmt) {
+ unsigned long long unsigned_num, base;
+ wchar_t* p;
+ int n, digits;
+ int minus = 0;
+ unsigned_num = num;
+ minus = 0;
+ p = pBuf;
+ *--p = 0;
+ digits = 0;
+
+ if (!num && !fmt.precision && !(fmt.alternate_form && fmt.conversion_char == 'o')) {
+ return p;
+ }
+
+ switch (fmt.conversion_char) {
+ case 'd':
+ case 'i':
+ base = 10;
+
+ if (num < 0) {
+ if (num != 0x8000000000000000LL) {
+ unsigned_num = -unsigned_num;
+ }
+
+ minus = 1;
+ }
+ break;
+ case 'o':
+ base = 8;
+ fmt.sign_options = only_minus;
+ break;
+ case 'u':
+ base = 10;
+ fmt.sign_options = only_minus;
+ break;
+ case 'x':
+ case 'X':
+ base = 16;
+ fmt.sign_options = only_minus;
+ break;
+ }
+
+ do {
+ n = unsigned_num % base;
+ unsigned_num /= base;
+
+ if (n < 10) {
+ n += '0';
+ } else {
+ n -= 10;
+ if (fmt.conversion_char == 'x') {
+ n += 'a';
+ } else {
+ n += 'A';
+ }
+ }
+
+ *--p = n;
+ ++digits;
+ } while (unsigned_num != 0);
+
+ if (base == 8 && fmt.alternate_form && *p != '0') {
+ *--p = '0';
+ ++digits;
+ }
+
+ if (fmt.justification_options == zero_fill) {
+ fmt.precision = fmt.field_width;
+
+ if (minus || fmt.sign_options != only_minus) {
+ --fmt.precision;
+ }
+
+ if (base == 16 && fmt.alternate_form) {
+ fmt.precision -= 2;
+ }
+ }
+
+ if (pBuf - p + fmt.precision > 509) {
+ return 0;
+ }
+
+ while (digits < fmt.precision) {
+ *--p = '0';
+ ++digits;
+ }
+
+ if (base == 16 && fmt.alternate_form) {
+ *--p = fmt.conversion_char;
+ *--p = '0';
+ }
+
+ if (minus) {
+ *--p = '-';
+ } else if (fmt.sign_options == sign_always) {
+ *--p = '+';
+ } else if (fmt.sign_options == space_holder) {
+ *--p = ' ';
+ }
+
+ return p;
+}
+
+wchar_t* double2hex(long double num, wchar_t* buff, print_format format) {
+ wchar_t* p;
+ wchar_t* q;
+ unsigned char working_char;
+ long double ld;
+ int expbits, expmask;
+ unsigned snum;
+ long exp;
+ print_format exp_format;
+ int hex_precision;
+ int mantissa_bit;
+ decform form;
+ decimal dec;
+ int radix_marker;
+ double tempF;
+
+ radix_marker = *(unsigned char *)(__lconv).decimal_point;
+ p = buff;
+ ld = num;
+
+ if (format.precision > 509) {
+ return 0;
+ }
+
+ form.style = (char)0;
+ form.digits = 0x20;
+ __num2dec(&form, num, &dec);
+
+ switch (*dec.sig.text) {
+ case '0':
+ dec.exp = 0;
+ if (dec.sign) {
+ p = buff - 5;
+ if (format.conversion_char == 'A') {
+ wcscpy(p, L"-0X0");
+ } else {
+ wcscpy(p, L"-0x0");
+ }
+ } else {
+ p = buff - 4;
+ if (format.conversion_char == 'A') {
+ wcscpy(p, L"0X0");
+ } else {
+ wcscpy(p, L"0x0");
+ }
+ }
+
+ return p;
+ case 'I':
+ if (dec.sign) {
+ p = buff - 5;
+ if (format.conversion_char == 'A') {
+ wcscpy(p, L"-INF");
+ } else {
+ wcscpy(p, L"-inf");
+ }
+ } else {
+ p = buff - 4;
+ if (format.conversion_char == 'A') {
+ wcscpy(p, L"INF");
+ } else {
+ wcscpy(p, L"inf");
+ }
+ }
+
+ return p;
+ case 'N':
+ if (dec.sign) {
+ p = buff - 5;
+ if (format.conversion_char == 'A') {
+ wcscpy(p, L"-NAN");
+ } else {
+ wcscpy(p, L"-nan");
+ }
+ } else {
+ p = buff - 4;
+ if (format.conversion_char == 'A') {
+ wcscpy(p, L"NAN");
+ } else {
+ wcscpy(p, L"nan");
+ }
+ }
+
+ return p;
+ }
+
+ exp_format.justification_options = right_justification;
+ exp_format.sign_options = sign_always;
+ exp_format.precision_specified = 0;
+ exp_format.alternate_form = 0;
+ exp_format.argument_options = normal_argument;
+ exp_format.field_width = 0;
+ exp_format.precision = 1;
+ exp_format.conversion_char = 'd';
+
+ expbits = 11;
+ expmask = 0x7FF;
+
+ snum = ((unsigned char *)&num)[0] << 25;
+ if (TARGET_FLOAT_EXP_BITS > 7) {
+ snum |= ((unsigned char *)&num)[1] << 17;
+ }
+ if (TARGET_FLOAT_EXP_BITS > 15) {
+ snum |= ((unsigned char *)&num)[2] << 9;
+ }
+ if (TARGET_FLOAT_EXP_BITS > 23) {
+ snum |= ((unsigned char *)&num)[3] << 1;
+ }
+
+ snum = (snum >> (32 - expbits)) & expmask;
+
+ if(snum != 0)
+ exp = snum - 0x3FF;
+ else
+ exp = 0;
+
+ p = long2str(exp, buff, exp_format);
+ if (format.conversion_char == 'a') {
+ *--p = 'p';
+ } else {
+ *--p = 'P';
+ }
+ q = (wchar_t*)&num;
+
+ if (TARGET_FLOAT_IMPLICIT_J_BIT) {
+ mantissa_bit = (1 + expbits + format.precision * 4) - 1;
+ } else {
+ mantissa_bit = (1 + expbits + format.precision * 4) - 4;
+ }
+
+ for (hex_precision = format.precision; hex_precision >= 1; hex_precision--) {
+ if (mantissa_bit < 64) {
+ int mantissa_byte;
+
+ mantissa_byte = mantissa_bit >> 3;
+ working_char = (*((unsigned char*)q + mantissa_byte)) >> (0x7 - (mantissa_bit & 0x7));
+
+ if ((mantissa_bit & ~0x7) != ((mantissa_bit - 4) & ~0x7)) {
+ working_char |= (unsigned char)(((*((unsigned char*)q + (mantissa_byte - 1))) << 8) >> (0x7 - ((mantissa_bit) & 0x7)));
+ }
+
+ if (!TARGET_FLOAT_IMPLICIT_J_BIT) {
+ if (mantissa_bit == 1 + expbits) {
+ *--p = radix_marker;
+ working_char &= 0x1;
+ }
+ }
+
+ if ((working_char &= 0xF) < 10) {
+ working_char += (unsigned char)'0';
+ } else {
+ if (format.conversion_char == 'a') {
+ working_char += (unsigned char)('a' - 10);
+ } else {
+ working_char += (unsigned char)('A' - 10);
+ }
+ }
+ }
+ else {
+ working_char = '0';
+ }
+
+ *--p = working_char;
+ mantissa_bit -= 4;
+ }
+
+ if (TARGET_FLOAT_IMPLICIT_J_BIT){
+ if (format.precision || format.alternate_form) {
+ *--p = radix_marker;
+ }
+
+ tempF = __fabs(ld);
+ if (tempF != 0.0) {
+ *--p = '1';
+ } else {
+ *--p = '0';
+ }
+ }
+
+ if (format.conversion_char == 'a') {
+ *--p = 'x';
+ } else {
+ *--p = 'X';
+ }
+
+ *--p = '0';
+
+ if (dec.sign) {
+ *--p = '-';
+ } else if (format.sign_options == sign_always) {
+ *--p = '+';
+ } else if (format.sign_options == space_holder) {
+ *--p = ' ';
+ }
+
+ return p;
+}
+
+void round_decimal(decimal* dec, int new_length) {
+ char c;
+ char* p;
+ int carry;
+
+ if (new_length < 0) {
+ return_zero:
+ dec->exp = 0;
+ dec->sig.length = 1;
+ *dec->sig.text = '0';
+ return;
+ }
+
+ if (new_length >= dec->sig.length) {
+ return;
+ }
+
+ p = (char*)dec->sig.text + new_length + 1;
+ c = *--p - '0';
+
+ if (c == 5) {
+ char* q = &((char*)dec->sig.text)[dec->sig.length];
+
+ while (--q > p && *q == '0')
+ ;
+ carry = q == p ? p[-1] & 1 : 1;
+ } else {
+ carry = c > 5;
+ }
+
+ while (new_length != 0) {
+ c = *--p - '0' + carry;
+
+ if ((carry = (c > 9)) != 0 || c == 0) {
+ --new_length;
+ } else {
+ *p = c + '0';
+ break;
+ }
+ }
+
+ if (carry != 0) {
+ dec->exp += 1;
+ dec->sig.length = 1;
+ *dec->sig.text = '1';
+ return;
+ } else if (new_length == 0) {
+ goto return_zero;
+ }
+
+ dec->sig.length = new_length;
+}
+
+wchar_t* float2str(double num, wchar_t* buff, print_format format) {
+ wchar_t out_buf[0x100];
+ decimal dec;
+ decform form;
+ wchar_t* p;
+ char* p2;
+ wchar_t c;
+ char* p3;
+ unsigned char* q;
+ int n, digits, sign;
+ int int_digits, frac_digits;
+ int radix_marker;
+ int used_bytes;
+
+ radix_marker = *(unsigned char*)__lconv.decimal_point;
+
+ if (format.precision > 509) {
+ return 0;
+ }
+
+ form.style = 0;
+ form.digits = 0x20;
+ __num2dec(&form, num, &dec);
+ p3 = (char*)(dec.sig.text + dec.sig.length);
+
+ while (dec.sig.length > 1 && *--p3 == '0') {
+ --dec.sig.length;
+ ++dec.exp;
+ }
+
+ switch (*dec.sig.text) {
+ case '0':
+ dec.exp = 0;
+ break;
+ case 'I':
+ if (num < 0) {
+ c = format.conversion_char;
+ p = buff - 5;
+
+ if ((c >= 0x100 ? 0 : _current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & 0x200) != 0) {
+ wcscpy(p, L"-INF");
+ } else {
+ wcscpy(p, L"-inf");
+ }
+ } else {
+ c = format.conversion_char;
+ p = buff - 4;
+ if ((c >= 0x100 ? 0 : _current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & 0x200) != 0) {
+ wcscpy(p, L"INF");
+ } else {
+ wcscpy(p, L"inf");
+ }
+ }
+
+ return p;
+
+ case 'N':
+ if (dec.sign) {
+ c = format.conversion_char;
+ p = buff - 5;
+ if ((c >= 0x100 ? 0 : _current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & 0x200) != 0) {
+ wcscpy(p, L"-NAN");
+ } else {
+ wcscpy(p, L"-nan");
+ }
+ } else {
+ c = format.conversion_char;
+ p = buff - 4;
+ if ((c >= 0x100 ? 0 : _current_locale.ctype_cmpt_ptr->wctype_map_ptr[c] & 0x200) != 0) {
+ wcscpy(p, L"NAN");
+ } else {
+ wcscpy(p, L"nan");
+ }
+ }
+
+ return p;
+ }
+
+ dec.exp += (short)(dec.sig.length - 1);
+
+ p2 = (char*)&out_buf + sizeof(out_buf);
+ *--p2 = 0;
+
+ switch (format.conversion_char) {
+ case 'g':
+ case 'G':
+
+ if (dec.sig.length > format.precision) {
+ round_decimal(&dec, format.precision);
+ }
+
+ if (dec.exp < -4 || dec.exp >= format.precision) {
+ if (format.alternate_form) {
+ --format.precision;
+ } else {
+ format.precision = dec.sig.length - 1;
+ }
+
+ if (format.conversion_char == 'g') {
+ format.conversion_char = 'e';
+ } else {
+ format.conversion_char = 'E';
+ }
+
+ goto e_format;
+ }
+
+ if (format.alternate_form) {
+ format.precision -= dec.exp + 1;
+ } else {
+ if ((format.precision = dec.sig.length - (dec.exp + 1)) < 0) {
+ format.precision = 0;
+ }
+ }
+
+ goto f_format;
+
+ case 'e':
+ case 'E':
+ e_format:
+
+ if (dec.sig.length > format.precision + 1) {
+ round_decimal(&dec, format.precision + 1);
+ }
+
+ n = dec.exp;
+ sign = '+';
+
+ if (n < 0) {
+ n = -n;
+ sign = '-';
+ }
+
+ for (digits = 0; n || digits < 2; ++digits) {
+ *--p2 = n % 10 + '0';
+ n /= 10;
+ }
+
+ *--p2 = sign;
+ *--p2 = format.conversion_char;
+
+ used_bytes = (intptr_t)out_buf - (intptr_t)p2;
+ if (used_bytes + format.precision > 0x1FD) {
+ return NULL;
+ }
+
+ if (dec.sig.length < format.precision + 1) {
+ for (n = format.precision + 1 - dec.sig.length + 1; --n;) {
+ *--p2 = '0';
+ }
+ }
+
+ for (n = dec.sig.length, q = (dec.sig.text + dec.sig.length); --n;) {
+ *--p2 = *--q;
+ }
+
+ if (format.precision || format.alternate_form) {
+ *--p2 = radix_marker;
+ }
+
+ *--p2 = *dec.sig.text;
+
+ if (dec.sign)
+ *--p2 = '-';
+ else if (format.sign_options == sign_always)
+ *--p2 = '+';
+ else if (format.sign_options == space_holder)
+ *--p2 = ' ';
+
+ break;
+
+ case 'f':
+ case 'F':
+ f_format:
+
+ if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0)
+ frac_digits = 0;
+
+ if (frac_digits > format.precision) {
+ round_decimal(&dec, dec.sig.length - (frac_digits - format.precision));
+
+ if ((frac_digits = -dec.exp + dec.sig.length - 1) < 0)
+ frac_digits = 0;
+ }
+
+ if ((int_digits = dec.exp + 1) < 0)
+ int_digits = 0;
+
+ if (int_digits + frac_digits > 509)
+ return 0;
+
+ q = dec.sig.text + dec.sig.length;
+
+ for (digits = 0; digits < (format.precision - frac_digits); ++digits)
+ *--p2 = '0';
+
+ for (digits = 0; digits < frac_digits && digits < dec.sig.length; ++digits)
+ *--p2 = *--q;
+
+ for (; digits < frac_digits; ++digits)
+ *--p2 = '0';
+
+ if (format.precision || format.alternate_form)
+ *--p2 = radix_marker;
+
+ if (int_digits) {
+ for (digits = 0; digits < int_digits - dec.sig.length; ++digits) {
+ *--p2 = '0';
+ }
+
+ for (; digits < int_digits; ++digits) {
+ *--p2 = *--q;
+ }
+ } else {
+ *--p2 = '0';
+ }
+
+ if (dec.sign) {
+ *--p2 = '-';
+ } else if (format.sign_options == sign_always) {
+ *--p2 = '+';
+ } else if (format.sign_options == space_holder) {
+ *--p2 = ' ';
+ }
+
+ break;
+ }
+
+ p = buff - strlen((char*)p2) - 1;
+ mbstowcs(p, p2, strlen((char*)p2));
+
+ return p;
+}
+
+int __wpformatter(int (*write_proc)(wString* dst, const void* data, size_t len),
+ void* proc_data, const wchar_t* fmt,
+ va_list args, int is_secure) {
+ int num_chars, chars_written, field_width;
+ const wchar_t* format_ptr;
+ const wchar_t* curr_format;
+ print_format format;
+ signed long long_num;
+ signed long long long_long_num;
+ long double long_double_num;
+ wchar_t buff[512];
+ wchar_t* buff_ptr;
+ const wchar_t* string_end;
+ wchar_t fill_char = ' ';
+
+ format_ptr = fmt;
+ chars_written = 0;
+
+ while (*format_ptr) {
+ if (!(curr_format = wcschr(format_ptr, L'%'))) {
+ num_chars = wcslen(format_ptr);
+ chars_written += num_chars;
+
+ if (num_chars && !(*write_proc)(proc_data, format_ptr, num_chars)) {
+ return -1;
+ }
+
+ break;
+ }
+
+ num_chars = curr_format - format_ptr;
+ chars_written += num_chars;
+
+ if (num_chars && !(*write_proc)(proc_data, format_ptr, num_chars)) {
+ return -1;
+ }
+
+ format_ptr = curr_format;
+ format_ptr = parse_format(format_ptr, (va_list*)args, &format);
+
+ switch (format.conversion_char) {
+ case 'd':
+ case 'i':
+ if (format.argument_options == long_argument) {
+ long_num = va_arg(args, signed long);
+ } else if (format.argument_options == long_long_argument) {
+ long_long_num = va_arg(args, signed long long);
+ } else if (format.argument_options == intmax_argument) {
+ long_long_num = va_arg(args, intmax_t);
+ } else if (format.argument_options == size_t_argument) {
+ long_num = va_arg(args, size_t);
+ } else if (format.argument_options == ptrdiff_argument) {
+ long_num = va_arg(args, ptrdiff_t);
+ } else {
+ long_num = va_arg(args, int);
+ }
+
+ if (format.argument_options == short_argument) {
+ long_num = (signed short)long_num;
+ }
+
+ if (format.argument_options == long_long_argument ||
+ format.argument_options == intmax_argument)
+ {
+ if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) {
+ goto conversion_error;
+ }
+ } else {
+ if (!(buff_ptr = long2str(long_num, buff + 512, format))) {
+ goto conversion_error;
+ }
+ }
+
+ num_chars = buff + 512 - 1 - buff_ptr;
+ break;
+
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ if (format.argument_options == long_argument) {
+ long_num = va_arg(args, unsigned long);
+ } else if (format.argument_options == long_long_argument) {
+ long_long_num = va_arg(args, signed long long);
+ }
+ else if (format.argument_options == intmax_argument) {
+ long_long_num = va_arg(args, intmax_t);
+ }
+ else if (format.argument_options == size_t_argument) {
+ long_num = va_arg(args, size_t);
+ }
+ else if (format.argument_options == ptrdiff_argument) {
+ long_num = va_arg(args, ptrdiff_t);
+ }
+ else {
+ long_num = va_arg(args, unsigned int);
+ }
+
+ if (format.argument_options == short_argument) {
+ long_num = (unsigned short)long_num;
+ }
+
+ if ((format.argument_options == long_long_argument)
+ || format.argument_options == intmax_argument
+ )
+ {
+ if (!(buff_ptr = longlong2str(long_long_num, buff + 512, format))) {
+ goto conversion_error;
+ }
+ } else {
+ if (!(buff_ptr = long2str(long_num, buff + 512, format))) {
+ goto conversion_error;
+ }
+ }
+
+ num_chars = buff + 512 - 1 - buff_ptr;
+ break;
+
+ case 'f':
+ case 'F':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ if (format.argument_options == long_double_argument) {
+ long_double_num = va_arg(args, long double);
+ } else {
+ long_double_num = va_arg(args, double);
+ }
+
+ if (!(buff_ptr = float2str(long_double_num, buff + 512, format))) {
+ goto conversion_error;
+ }
+
+ num_chars = buff + 512 - 1 - buff_ptr;
+ break;
+
+ case 'a':
+ case 'A':
+ if (format.argument_options == long_double_argument) {
+ long_double_num = va_arg(args, long double);
+ } else {
+ long_double_num = va_arg(args, double);
+ }
+
+ if (!(buff_ptr = double2hex(long_double_num, buff + 512, format))) {
+ goto conversion_error;
+ }
+
+ num_chars = buff + 512 - 1 - buff_ptr;
+ break;
+
+ case 's':
+ if (format.argument_options == wchar_argument) {
+ wchar_t* wcs_ptr = va_arg(args, wchar_t*);
+
+ if (is_secure && wcs_ptr == NULL){
+ __msl_runtime_constraint_violation_s(0,0,-1);
+ return -1;
+ }
+
+ if (wcs_ptr == NULL) {
+ wcs_ptr = L"";
+ }
+
+ if (format.alternate_form) {
+ num_chars = (unsigned char)*wcs_ptr++;
+
+ if (format.precision_specified && num_chars > format.precision) {
+ num_chars = format.precision;
+ }
+ } else if (format.precision_specified) {
+ num_chars = format.precision;
+
+ if ((string_end = wmemchr(wcs_ptr, 0, num_chars)) != 0) {
+ num_chars = string_end - wcs_ptr;
+ }
+
+ } else {
+ num_chars = wcslen(wcs_ptr);
+ }
+
+ buff_ptr = wcs_ptr;
+ break;
+ } else {
+ const char* wcs_ptr = (const char*)va_arg(args, wchar_t*);
+
+ if (is_secure && wcs_ptr == NULL){
+ __msl_runtime_constraint_violation_s(0,0,-1);
+ return -1;
+ }
+
+ if (wcs_ptr == NULL) {
+ wcs_ptr = "";
+ }
+
+ if (format.alternate_form) {
+ num_chars = (unsigned char)*buff_ptr;
+
+ if (format.precision_specified && num_chars > format.precision) {
+ num_chars = format.precision;
+ }
+ } else if (format.precision_specified) {
+ num_chars = format.precision;
+
+ if ((string_end = memchr(wcs_ptr, 0, num_chars)) != 0) {
+ num_chars = (intptr_t)string_end - (intptr_t)wcs_ptr;
+ }
+ } else {
+ num_chars = strlen(wcs_ptr);
+ }
+
+ if ((num_chars = mbstowcs(buff, wcs_ptr, num_chars)) < 0) {
+ goto conversion_error;
+ }
+
+ buff_ptr = buff;
+ }
+
+ break;
+
+ case 'n':
+ if (is_secure) {
+ __msl_runtime_constraint_violation_s(NULL, NULL, -1);
+ return -1;
+ }
+
+ buff_ptr = va_arg(args, wchar_t*);
+
+ switch (format.argument_options) {
+ case normal_argument:
+ *(int*)buff_ptr = chars_written;
+ break;
+ case short_argument:
+ *(signed short*)buff_ptr = chars_written;
+ break;
+ case long_argument:
+ *(signed long*)buff_ptr = chars_written;
+ break;
+ case intmax_argument:
+ *(intmax_t*)buff_ptr = chars_written;
+ break;
+ case size_t_argument:
+ *(size_t*)buff_ptr = chars_written;
+ break;
+ case ptrdiff_argument:
+ *(ptrdiff_t*)buff_ptr = chars_written;
+ break;
+ case long_long_argument:
+ *(signed long long*)buff_ptr = chars_written;
+ break;
+ }
+
+ continue;
+
+ case 'c':
+ buff_ptr = buff;
+ if (format.argument_options == wchar_argument) {
+ *buff_ptr = va_arg(args, long);
+ num_chars = 1;
+ } else {
+ char s;
+ s = va_arg(args, int);
+ num_chars = mbtowc(buff_ptr, &s, 1);
+ }
+ break;
+
+ case '%':
+ buff_ptr = buff;
+ *buff_ptr = '%';
+ num_chars = 1;
+ break;
+
+ case 0xFF:
+ default:
+ conversion_error:
+ num_chars = wcslen(curr_format);
+ chars_written += num_chars;
+
+ if (num_chars && !(*write_proc)(proc_data, curr_format, num_chars)) {
+ return -1;
+ }
+
+ return chars_written;
+ break;
+ }
+
+ field_width = num_chars;
+
+ if (format.justification_options != left_justification) {
+ fill_char = (format.justification_options == zero_fill) ? '0' : ' ';
+
+ if (((*buff_ptr == '+') || (*buff_ptr == '-') || (*buff_ptr == ' ')) &&
+ (fill_char == '0'))
+ {
+ if ((*write_proc)(proc_data, buff_ptr, 1) == 0) {
+ return -1;
+ }
+
+ ++buff_ptr;
+ num_chars--;
+ }
+
+ if ((format.justification_options == zero_fill) &&
+ ((format.conversion_char == 'a') || (format.conversion_char == 'A')))
+ {
+ if (num_chars < 2) {
+ return -1;
+ }
+
+ if ((*write_proc)(proc_data, buff_ptr, 2) == 0) {
+ return -1;
+ }
+
+ num_chars -= 2;
+ buff_ptr += 2;
+ }
+
+ while (field_width < format.field_width) {
+ if ((*write_proc)(proc_data, (wchar_t*)&fill_char, 1) == 0) {
+ return -1;
+ }
+
+ ++field_width;
+ }
+ }
+
+ if (num_chars && !(*write_proc)(proc_data, buff_ptr, num_chars)) {
+ return -1;
+ }
+
+ if (format.justification_options == left_justification) {
+ while (field_width < format.field_width) {
+ wchar_t blank = L' ';
+
+ if ((*write_proc)(proc_data, (wchar_t*)&blank, 1) == 0) {
+ return -1;
+ }
+
+ ++field_width;
+ }
+ }
+
+ chars_written += field_width;
+ }
+
+ return chars_written;
+}
+
+static int __wStringWrite(wString* dst, const void* data, size_t len) {
+ const __OutStrCtrl* osc = data;
+ size_t cur_len = dst->field_0x8;
+ size_t var_r7 = dst->field_0x4;
+ size_t write_cnt = cur_len + len <= var_r7 ? len : var_r7 - cur_len;
+ wmemcpy(dst->buffer + cur_len, (const wchar_t*)osc, write_cnt);
+ dst->field_0x8 += write_cnt;
+}
+
+int swprintf(wchar_t *dst, size_t maxlen, const wchar_t *fmt, ...) {
+ int written;
+ va_list args;
+ __OutStrCtrl ctx;
+
+ ctx.WCharStr = dst;
+
+ va_start(args, fmt);
+ ctx.MaxCharCount = maxlen;
+ ctx.CharsWritten = 0;
+ written = __wpformatter(__wStringWrite, &ctx, fmt, args, 0);
+ va_end(args);
+
+ if (written >= 0) {
+ if ((size_t)written < maxlen) {
+ dst[written] = '\0';
+ return written;
+ }
+ dst[maxlen - 1] = '\0';
+ return -1;
+ }
+}
+
+int vsnwprintf_s(wchar_t* str, size_t n, const wchar_t* fmt, va_list args) {
+ __OutStrCtrl osc;
+ int written_cnt;
+
+ if (str == NULL || fmt == NULL || n == 0 || n > 0x7FFFFFFFU) {
+ __msl_runtime_constraint_violation_s(0, 0, -1);
+ if (str != NULL && n != 0 && n <= 0x7FFFFFFFU) {
+ *str = 0;
+ }
+ return -1;
+ }
+
+ osc.MaxCharCount = n;
+ osc.WCharStr = str;
+ osc.CharsWritten = 0;
+ written_cnt = __wpformatter(__wStringWrite, &osc, fmt, args, 1);
+ if (written_cnt >= 0) {
+ if (written_cnt < n) {
+ str[written_cnt] = '\0';
+ return written_cnt;
+ }
+ str[n - 1] = '\0';
+ return written_cnt;
+ }
+ return written_cnt;
+}
diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wscanf.c b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wscanf.c
new file mode 100644
index 0000000000..1906be0b4e
--- /dev/null
+++ b/src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Src/wscanf.c
@@ -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;
+ }
+}
diff --git a/src/PowerPC_EABI_Support/Runtime/Src/GCN_Mem_Alloc.c b/src/PowerPC_EABI_Support/Runtime/Src/GCN_mem_alloc.c
index 33b700446d..33b700446d 100644
--- a/src/PowerPC_EABI_Support/Runtime/Src/GCN_Mem_Alloc.c
+++ b/src/PowerPC_EABI_Support/Runtime/Src/GCN_mem_alloc.c
diff --git a/src/TRK_MINNOW_DOLPHIN/debugger/embedded/MetroTRK/Portable/string_TRK.c b/src/TRK_MINNOW_DOLPHIN/debugger/embedded/MetroTRK/Portable/string_TRK.c
new file mode 100644
index 0000000000..4e84465331
--- /dev/null
+++ b/src/TRK_MINNOW_DOLPHIN/debugger/embedded/MetroTRK/Portable/string_TRK.c
@@ -0,0 +1,10 @@
+#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/string_TRK.h"
+
+int TRK_strlen(const char *str) {
+ // NONMATCHING for Wii - for some reason Wii uses cmplwi instead of cmpwi
+ int n = -1;
+ do {
+ n++;
+ } while (((unsigned char*)str)[n] != '\0');
+ return n;
+}
diff --git a/src/TRK_MINNOW_DOLPHIN/gamedev/cust_connection/utils/gc/cc_gdev.c b/src/TRK_MINNOW_DOLPHIN/gamedev/cust_connection/utils/gc/cc_gdev.c
new file mode 100644
index 0000000000..bcd089f75c
--- /dev/null
+++ b/src/TRK_MINNOW_DOLPHIN/gamedev/cust_connection/utils/gc/cc_gdev.c
@@ -0,0 +1,105 @@
+#include "TRK_MINNOW_DOLPHIN/utils/common/CircleBuffer.h"
+#include "odemuexi2/DebuggerDriver.h"
+
+#define GDEV_BUF_SIZE (0x500)
+
+static CircleBuffer gRecvCB;
+static u8 gRecvBuf[GDEV_BUF_SIZE];
+static BOOL gIsInitialized;
+
+int gdev_cc_initinterrupts() {
+ DBInitInterrupts();
+ return 0;
+}
+
+int gdev_cc_peek() {
+ u8 buf[GDEV_BUF_SIZE];
+ int len;
+
+ if ((len = DBQueryData()) <= 0) {
+ return 0;
+ }
+
+ if (DBRead((u32*)buf, len) == 0) {
+ CircleBufferWriteBytes(&gRecvCB, buf, len);
+ } else {
+ return 0xFFFFD8E7;
+ }
+
+ return len;
+}
+
+int gdev_cc_post_stop() {
+ DBOpen();
+ return 0;
+}
+
+int gdev_cc_pre_continue() {
+ DBClose();
+ return 0;
+}
+
+int gdev_cc_write(unsigned char* src, int size) {
+ if (!gIsInitialized) {
+ return 0xFFFFD8EF;
+ }
+
+ while (size > 0) {
+ u32 written_cnt = DBWrite(src, size);
+ if (written_cnt == 0) {
+ break;
+ }
+ src += written_cnt;
+ size -= written_cnt;
+ }
+
+ return 0;
+}
+
+int gdev_cc_read(u8* buf, u32 len) {
+ u8 buf_local[GDEV_BUF_SIZE];
+ int rv = 0;
+ int var_r29;
+
+ if (!gIsInitialized) {
+ return 0xFFFFD8EF;
+ }
+
+ while (CBGetBytesAvailableForRead(&gRecvCB) < len) {
+ rv = 0;
+ if ((var_r29 = DBQueryData()) == 0) {
+ continue;
+ }
+ rv = DBRead((u32*)buf_local, len);
+ if (rv == 0) {
+ CircleBufferWriteBytes(&gRecvCB, buf_local, var_r29);
+ }
+ }
+ if (rv == 0) {
+ CircleBufferReadBytes(&gRecvCB, buf, len);
+ }
+ return rv;
+}
+
+int gdev_cc_close() {
+ return 0;
+}
+
+int gdev_cc_open() {
+ if (gIsInitialized) {
+ return 0xFFFFD8EB;
+ }
+
+ gIsInitialized = 1;
+ return 0;
+}
+
+int gdev_cc_shutdown() {
+ return 0;
+}
+
+int gdev_cc_initialize(u8** a, MTRCallbackType b) {
+ DBInitComm(a, b);
+ CircleBufferInitialize(&gRecvCB, gRecvBuf, sizeof(gRecvBuf));
+ return 0;
+}
diff --git a/src/odemuexi2/DebuggerDriver.c b/src/odemuexi2/DebuggerDriver.c
index fef3707d92..2102bb8e16 100644
--- a/src/odemuexi2/DebuggerDriver.c
+++ b/src/odemuexi2/DebuggerDriver.c
@@ -1,8 +1,8 @@
+#include "odemuexi2/DebuggerDriver.h"
+
#include <dolphin/exi.h>
#include <dolphin/os.h>
-typedef void (*MTRCallbackType)(int);
-
static MTRCallbackType MTRCallback;
static void (*DBGCallback)(u32, OSContext*);