diff options
| author | Luke Street <luke@street.dev> | 2026-03-01 15:35:36 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-01 14:35:36 -0800 |
| commit | 9649319ec4926457ef85e6094f8207474c977c2d (patch) | |
| tree | 1c5cd4c7cc4c1aee03f28921213da47f2775444d /libs/JSystem/src/JHostIO | |
| parent | 6e149819e13b1f70ecbf8a4c66b030c17ffed2bb (diff) | |
Reorganize library code into `libs/` (#3119)
* Reorganize files into libs/{dolphin,JSystem,PowerPC_EABI_Support,revolution,TRK_MINNOW_DOLPHIN}
* Update configure.py and project.py for new libs structure
* Refactor `#include <dolphin/x.h>` -> `<x.h>`
* Remove `__REVOLUTION_SDK__` forwards from dolphin
* Fix dolphin/ references in revolution
* Wrap `#include <dolphin.h>` in `!__REVOLUTION_SDK__`
* Always build TRK against dolphin headers
* Resolve revolution SDK header resolution issues
Diffstat (limited to 'libs/JSystem/src/JHostIO')
| -rw-r--r-- | libs/JSystem/src/JHostIO/JHIComm.cpp | 302 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JHICommonMem.cpp | 18 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JHIMccBuf.cpp | 458 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JHIMemBuf.cpp | 75 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JHIRMcc.cpp | 123 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JHIhioASync.cpp | 174 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JOREntry.cpp | 24 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JORFile.cpp | 189 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JORHostInfo.cpp | 58 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JORMessageBox.cpp | 16 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JORServer.cpp | 822 | ||||
| -rw-r--r-- | libs/JSystem/src/JHostIO/JORShellExecute.cpp | 18 |
12 files changed, 2277 insertions, 0 deletions
diff --git a/libs/JSystem/src/JHostIO/JHIComm.cpp b/libs/JSystem/src/JHostIO/JHIComm.cpp new file mode 100644 index 0000000000..f406fb4a47 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JHIComm.cpp @@ -0,0 +1,302 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHIComm.h" + +static int min(int a, int b); + +void JHICommBufHeader::init() { + mp_memBuffer->writeIO(field_0x4 + field_0x1c, 0); + mp_memBuffer->writeIO(field_0x4 + field_0x18, 0); + mp_memBuffer->writeIO(field_0x4 + field_0x14, 'IS64'); +} + +void JHICommBufHeader::init(JHICommonMem* buffer, u32 param_1, u32 param_2, u32 alignment) { + m_alignment = alignment; + + if (alignment == 4) { + field_0x14 = 0x00; + field_0x18 = 0x08; + field_0x1c = 0x14; + field_0x20 = 0x18; + field_0x24 = 0x20; + field_0x2c = ~0x3; + } else if (alignment == 32) { + field_0x14 = 0x00; + field_0x18 = 0x20; + field_0x1c = 0x40; + field_0x20 = 0x60; + field_0x24 = 0x80; + field_0x2c = ~0x1F; + } + + mp_memBuffer = buffer; + field_0x4 = field_0x2c & (param_1 + m_alignment - 1); + + u32 var_r30 = field_0x2c & (param_1 + param_2); + m_msgBufSize = var_r30 - field_0x4 - field_0x24; + + init(); +} + +int JHICommBufHeader::load() { + u32 data; + mp_memBuffer->readIO(field_0x4 + field_0x14, &data); + if (data != 'IS64') { + return 1; + } + + mp_memBuffer->readIO(field_0x4 + field_0x18, &field_0xc); + mp_memBuffer->readIO(field_0x4 + field_0x1c, &field_0x10); + return 0; +} + +JHICommBufReader::JHICommBufReader(u32 param_0, u32 param_1, u32 alignment) { + mp_memBuffer = JHICommonMem::Instance(); + m_header.init(mp_memBuffer, param_0, param_1, alignment); +} + +void JHICommBufReader::Header::updateGetAdrs() { + if (field_0xc != field_0x30) { + mp_memBuffer->writeIO(field_0x4 + field_0x18, field_0xc); + } +} + +u32 JHICommBufReader::Header::getReadableSize() const { + u32 size; + if (field_0xc <= field_0x10) { + size = field_0x10 - field_0xc; + } else { + size = m_msgBufSize - (field_0xc - field_0x10); + } + + return size; +} + +int JHICommBufReader::readBegin() { + return m_header.load(); +} + +void JHICommBufReader::readEnd() { + m_header.updateGetAdrs(); +} + +int JHICommBufReader::read(void* param_0, int param_1) { + int sp2C = min(param_1, m_header.getReadableSize()); + u32 sp28; + int var_r28 = sp2C; + u8* var_r30 = (u8*)param_0; + + int sp24; + if (var_r28 > 0 && (sp24 = m_header.getContSize()) > 0) { + int sp20 = min(var_r28, 4 - sp24); + m_header.alignGetAdrs(); + + mp_memBuffer->readIO(m_header.getGetAdrs(), &sp28); + + int sp1C = sp24; + int sp18 = sp24 + sp20; + for (; sp1C < sp18; sp1C++) { + *var_r30 = sp28 >> ((3 - sp1C) * 8); + var_r30++; + } + + var_r28 -= sp20; + m_header.addGetAdrs(sp24 + sp20); + } + + while (var_r28 >= 4) { + mp_memBuffer->readIO(m_header.getGetAdrs(), &sp28); + var_r30[0] = sp28 >> 0x18; + var_r30[1] = sp28 >> 0x10; + var_r30[2] = sp28 >> 0x08; + var_r30[3] = sp28 >> 0x00; + + var_r30 += 4; + var_r28 -= 4; + + m_header.addGetAdrs(4); + } + + if (var_r28 > 0) { + int sp14 = var_r28; + mp_memBuffer->readIO(m_header.getGetAdrs(), &sp28); + + for (int i = 0; i < sp14; i++) { + *var_r30 = sp28 >> ((3 - i) * 8); + var_r30++; + } + + var_r28 -= sp14; + m_header.addGetAdrs(sp14); + } + + return sp2C; +} + +void JHICommBufReader::Header::addGetAdrs(int param_0) { + field_0xc += param_0; + if (field_0xc >= m_msgBufSize) { + field_0xc -= m_msgBufSize; + } +} + +u32 JHICommBufReader::Header::getGetAdrs() const { + return field_0xc + (field_0x4 + field_0x24); +} + +void JHICommBufReader::Header::alignGetAdrs() { + field_0xc &= ~0x3; +} + +int JHICommBufReader::Header::getContSize() { + return field_0xc & 3; +} + +static int min(int a, int b) { + return a < b ? a : b; +} + +JHICommBufWriter::JHICommBufWriter(u32 param_0, u32 param_1, u32 param_2) { + mp_memBuffer = JHICommonMem::Instance(); + m_header.init(mp_memBuffer, param_0, param_1, param_2); +} + +int JHICommBufWriter::Header::load() { + int var_r29 = JHICommBufHeader::load(); + if (var_r29 == 0) { + field_0x34 = field_0x10; + + if (getRemSize() > 0) { + u32 sp8; + mp_memBuffer->readIO(field_0x4 + field_0x20, &sp8); + + field_0x30 = sp8 >> 0x18; + field_0x31 = sp8 >> 0x10; + field_0x32 = sp8 >> 0x08; + field_0x33 = sp8 >> 0x00; + } + } + + return var_r29; +} + +int JHICommBufWriter::Header::getRemSize() { + return field_0x10 & 3; +} + +void JHICommBufWriter::Header::updatePutAdrs() { + if (field_0x10 != field_0x34) { + mp_memBuffer->writeIO(field_0x4 + field_0x1c, field_0x10); + + if (getRemSize() > 0) { + mp_memBuffer->writeIO(field_0x4 + field_0x20, + (field_0x30 << 0x18) | + (field_0x31 << 0x10) | + (field_0x32 << 0x08) | + (field_0x33 << 0x00)); + } + } +} + +u32 JHICommBufWriter::Header::getWritebleSize() const { + u32 var_r31 = field_0xc & ~0x3; + u32 var_r30; + + if (field_0x10 < var_r31) { + var_r30 = var_r31 - field_0x10; + } else { + var_r30 = var_r31 + (m_msgBufSize - field_0x10); + } + + return var_r30 - 4; +} + +int JHICommBufWriter::writeBegin() { + int var_r31; + if (m_header.load() != 0) { + var_r31 = -1; + } else { + var_r31 = m_header.getWritebleSize(); + } + + return var_r31; +} + +void JHICommBufWriter::writeEnd() { + m_header.updatePutAdrs(); +} + +int JHICommBufWriter::write(void* param_0, int param_1) { + int sp28 = min(param_1, m_header.getWritebleSize()); + int var_r27 = sp28; + u8* var_r29 = (u8*)param_0; + u8* var_r30 = &m_header.field_0x30; + + int sp24; + if (var_r27 > 0 && (sp24 = m_header.getRemSize()) > 0) { + int sp20 = min(4 - sp24, var_r27); + + int sp1C = sp24; + int sp18 = sp24 + sp20; + for (; sp1C < sp18; sp1C++) { + var_r30[sp1C] = *var_r29++; + } + + var_r27 -= sp20; + m_header.alignPutAdrs(); + + mp_memBuffer->writeIO(m_header.getPutAdrs(), + (var_r30[0] << 0x18) | + (var_r30[1] << 0x10) | + (var_r30[2] << 0x08) | + (var_r30[3] << 0x00)); + m_header.addPutAdrs(sp24 + sp20); + } + + while (var_r27 >= 4) { + mp_memBuffer->writeIO(m_header.getPutAdrs(), + (var_r29[0] << 0x18) | + (var_r29[1] << 0x10) | + (var_r29[2] << 0x08) | + (var_r29[3] << 0x00)); + + var_r29 += 4; + var_r27 -= 4; + + m_header.addPutAdrs(4); + } + + if (var_r27 > 0) { + int sp14 = var_r27; + + for (int i = 0; i < sp14; i++) { + var_r30[i] = *var_r29++; + } + + mp_memBuffer->writeIO(m_header.getPutAdrs(), + (var_r30[0] << 0x18) | + (var_r30[1] << 0x10) | + (var_r30[2] << 0x08) | + (var_r30[3] << 0x00)); + + var_r27 -= sp14; + m_header.addPutAdrs(sp14); + } + + return sp28; +} + +void JHICommBufWriter::Header::addPutAdrs(int param_0) { + field_0x10 += param_0; + if (field_0x10 >= m_msgBufSize) { + field_0x10 -= m_msgBufSize; + } +} + +u32 JHICommBufWriter::Header::getPutAdrs() const { + return field_0x10 + (field_0x4 + field_0x24); +} + +void JHICommBufWriter::Header::alignPutAdrs() { + field_0x10 &= ~0x3; +} diff --git a/libs/JSystem/src/JHostIO/JHICommonMem.cpp b/libs/JSystem/src/JHostIO/JHICommonMem.cpp new file mode 100644 index 0000000000..3d2f59fc49 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JHICommonMem.cpp @@ -0,0 +1,18 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHICommonMem.h" + +JHIMemBuf* JHICommonMem::instance; + +JHIMemBuf* JHICommonMem::Instance() { + if (instance == NULL) { + instance = new JHIMemBuf(); + } + + return instance; +} + +JHIMemBuf::JHIMemBuf() { + mp_buffer = NULL; + create(); +} diff --git a/libs/JSystem/src/JHostIO/JHIMccBuf.cpp b/libs/JSystem/src/JHostIO/JHIMccBuf.cpp new file mode 100644 index 0000000000..f013947e26 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JHIMccBuf.cpp @@ -0,0 +1,458 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHIMccBuf.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JHostIO/JHIRMcc.h" +#include <revolution/hio2.h> +#include <cstring> + +void JHIReport(const char* fmt, ...) {} + +void JHIHalt(const char* fmt, ...) {} + +u8* JHIMccBuf::mTempBuf; +u16 JHIMccBuf::mRefCount; + +JHIMccBuf::JHIMccBuf(u16 channel, u16 param_1, u32 param_2) { + initInstance(channel, param_1, param_2); + mRefCount++; +} + +void JHIMccBuf::initInstance(u16 channel, u16 param_1, u32 param_2) { + mTag = 'MCHI'; + field_0x8 = 0x20; + field_0xa = 0x40; + field_0xc = 0x60; + mChannel = channel; + field_0x10 = param_1; + field_0x20 = param_2; + mReadOffset = 0; + mWriteOffset = (int)(param_1 << 13) / 4; + field_0x1c = ((int)(param_1 << 13) / 4) - field_0xc; + mPortEnabled = false; +} + +void JHIMccBuf::init() { + if (mTempBuf != NULL) { + initBuf(); + } else { + mTempBuf = new (32) u8[0x18000]; + if (mTempBuf == NULL) { + JHIHalt("ERROR: JHIMccBuf cannot alloc temp buf.\n"); + } else { + JHIReport("DEBUG: JHIMccBuf alloc at %08x.\n", mTempBuf); + } + + initBuf(); + } +} + +void JHIMccBuf::initBuf() { + setHeaderToBuf(mTag, 0, 0x20); + setHeaderToBuf(field_0xc, field_0x8, 0x20); + setHeaderToBuf(field_0xc, field_0xa, 0x20); + + if (JHIMCCWrite(mChannel, mReadOffset, mTempBuf, 0x60)) { + JHIReport("DEBUG: Write to Channel:%d , Offset:%05x , Size: %d\n", mChannel, mReadOffset, 0x60); + + if (JHIMCCWrite(mChannel, mWriteOffset, mTempBuf, 0x60)) { + JHIReport("DEBUG: Write to Channel:%d , Offset:%05x , Size: %d\n", mChannel, mWriteOffset, 0x60); + } + } +} + +JHIMccBuf::~JHIMccBuf() { + mRefCount--; + if (mRefCount == 0) { + delete[] mTempBuf; + } +} + +void JHIMccBuf::setHeaderToBuf(u32 data, u32 position, u16 size) { + u8* ptr = mTempBuf + position; + ptr[0] = (data >> 0x18) & 0xFF; + ptr[1] = (data >> 0x10) & 0xFF; + ptr[2] = (data >> 0x08) & 0xFF; + ptr[3] = (data >> 0x00) & 0xFF; + + for (int i = 4; i < size; i++) { + ptr[i] = 0; + } +} + +// NONMATCHING - storing var_r28 to stack instead of register +u32 JHIMccBuf::setDataToBuf(void* pData, u16 size) { + u8* temp_buf = mTempBuf; + u32 i; + u8* data_buf = (u8*)pData; + + temp_buf[0] = (mTag >> 0x18) & 0xFF; + temp_buf[1] = (mTag >> 0x10) & 0xFF; + temp_buf[2] = (mTag >> 0x08) & 0xFF; + temp_buf[3] = (mTag >> 0x00) & 0xFF; + temp_buf[4] = (size >> 0x8) & 0xFF; + temp_buf[5] = size & 0xFF; + + for (i = 0; i < size; i++) { + temp_buf[6 + i] = data_buf[i]; + } + + u32 var_r28 = (size + 0x25) & ~0x1F; + for (i = size + 6; i < var_r28; i++) { + temp_buf[i] = 0; + } + + return var_r28; +} + +int JHIMccBuf::readData(u32 position, u32* pOutData) { + u8* temp_buf = mTempBuf; + u32 var_r30 = position; + + if (!JHIMCCRead(mChannel, var_r30, temp_buf, 0x20)) { + return 0; + } + + *pOutData = (temp_buf[0 + (position - var_r30)] << 0x18) | + (temp_buf[1 + (position - var_r30)] << 0x10) | + (temp_buf[2 + (position - var_r30)] << 0x08) | + (temp_buf[3 + (position - var_r30)] << 0x00); + return 1; +} + +int JHIMccBuf::readDataFromBuf(void* pBuf, u32 size) { + u8* temp_buf = mTempBuf; + u8* u_buf = (u8*)pBuf; + + u32 var_r28; + u32 var_r27 = 0; + u32 var_r26 = 0; + u32 var_r30 = 0; + while (var_r30 < size) { + u32 sp10 = (temp_buf[0 + var_r30] << 0x18) | + (temp_buf[1 + var_r30] << 0x10) | + (temp_buf[2 + var_r30] << 0x08) | + (temp_buf[3 + var_r30] << 0x00); + if (sp10 != mTag) { + return 0; + } + + var_r26 = (temp_buf[4 + var_r30] << 0x8) | + (temp_buf[5 + var_r30] << 0x0); + if (u_buf != NULL) { + for (var_r28 = 0; var_r28 < var_r26; var_r28++) { + u_buf[var_r27 + var_r28] = temp_buf[6 + (var_r30 + var_r28)]; + } + } + + var_r30 += (var_r26 + 0x25) & ~0x1F; + var_r27 += var_r26; + var_r26 = 0; + } + + return var_r27; +} + +int JHIMccBuf::JHIRead(u32 channel, u32 offset, void* buffer, u32 size) { + JHIReport("DEBUG: MCCRead(%d, %06x, %08x, %d);\n", channel, offset, buffer, size); + + if (!isPort()) { + memset(buffer, 0, size); + return 0; + } + + int attempts = 0; + DCInvalidateRange(buffer, size); + + if (offset & 3) { + disablePort(); + return 0; + } + + if (offset > (field_0x1c + field_0xc) * 2) { + OS_REPORT("ERROR: Illegal offset specified Error. -HIOWrite()\n"); + OS_REPORT("ERROR: offset: %08x low:%08x high:%08x\n", offset, 0, (field_0x1c + field_0xc) * 2); + disablePort(); + return 0; + } + +#if VERSION < VERSION_SHIELD_DEBUG + while (HIORead(offset + field_0x20, buffer, size) == 0 && attempts < 30) { + attempts++; + } +#else + while (HIO2Read(JHIGetHIO2Handle(), offset + field_0x20, buffer, size) == 0 && attempts < 30) { + attempts++; + } +#endif + + if (attempts >= 30) { + OS_REPORT("ERROR: Communication Error. -HIORead()\n"); + memset(buffer, 0, size); + disablePort(); + return 0; + } + + return 1; +} + +int JHIMccBuf::JHIWrite(u32 channel, u32 offset, void* buffer, u32 size) { + JHIReport("DEBUG: MCCWrite(%d, %06x, %08x, %d);\n", channel, offset, buffer, size); + + if (!isPort()) { + return 0; + } + + int attempts = 0; + DCFlushRange(buffer, size); + + if (offset & 3) { + disablePort(); + return 0; + } + + if (offset > (field_0x1c + field_0xc) * 2) { + OS_REPORT("ERROR: Illegal offset specified Error. -HIOWrite()\n"); + OS_REPORT("ERROR: offset: %08x low:%08x high:%08x\n", offset, 0, (field_0x1c + field_0xc) * 2); + disablePort(); + return 0; + } + +#if VERSION < VERSION_SHIELD_DEBUG + while (HIOWrite(offset + field_0x20, buffer, size) == 0 && attempts < 30) { + attempts++; + } +#else + while (HIO2Write(JHIGetHIO2Handle(), offset + field_0x20, buffer, size) == 0 && attempts < 30) { + attempts++; + } +#endif + + if (attempts >= 30) { + JHIReport("ERROR: Communication Error. -HIOWrite()\n"); + disablePort(); + return 0; + } + + return 1; +} + +int JHIMccBuf::JHIMCCRead(u32 channel, u32 offset, void* buffer, u32 size) { + JHIReport("DEBUG: JHIMCCRead(%d, %06x, %08x, %d);\n", channel, offset, buffer, size); + if (!JHIRead(channel, offset, buffer, size)) { + return 0; + } + + return 1; +} + +int JHIMccBuf::JHIMCCWrite(u32 channel, u32 offset, void* buffer, u32 size) { + JHIReport("DEBUG: JHIMCCWrite(%d, %06x, %08x, %d);\n", channel, offset, buffer, size); + if (!JHIWrite(channel, offset, buffer, size)) { + return 0; + } + + return 1; +} + +JHIMccBufReader::JHIMccBufReader(u16 channel, u16 param_1, u32 param_2) + : JHIMccBuf(channel, param_1, param_2) {} + +JHIMccBufReader::~JHIMccBufReader() {} + +u32 JHIMccBufReader::available() { + u32 var_r30 = 0; + + if (!isPort()) { + return 0; + } + + if (!readData(mReadOffset + field_0x8, &mBeginPos)) { + return 0; + } + + if (!readData(mReadOffset + field_0xa, &mEndPos)) { + return 0; + } + + if (mBeginPos < mEndPos) { + var_r30 = mEndPos - mBeginPos; + } else if (mBeginPos > mEndPos) { + var_r30 = field_0x1c - (mBeginPos - mEndPos); + } + + return var_r30; +} + +int JHIMccBufReader::readBegin() { + if (!isPort()) { + return 0; + } + + if (!readData(mReadOffset + field_0x8, &mBeginPos)) { + return 0; + } + + if (!readData(mReadOffset + field_0xa, &mEndPos)) { + return 0; + } + + JHIReport("DEBUG: readBegin: R:%08x W:%08x\n", mBeginPos, mEndPos); + return 1; +} + +int JHIMccBufReader::read(void* pBuf) { + if (!isPort()) { + return 0; + } + + u32 size; + int var_r28 = 0; + + if (mBeginPos < mEndPos) { + size = mEndPos - mBeginPos; + if (!JHIMCCRead(mChannel, mReadOffset + mBeginPos, mTempBuf, size)) { + return 0; + } + + var_r28 = readDataFromBuf(pBuf, size); + } else if (mBeginPos > mEndPos) { + size = field_0x1c - (mBeginPos - mEndPos); + u32 var_r25 = (field_0xc + field_0x1c); + u32 var_r27 = var_r25 - mBeginPos; + u32 var_r26 = size - var_r27; + + if (!JHIMCCRead(mChannel, mReadOffset + mBeginPos, mTempBuf, var_r27)) { + return 0; + } else if (var_r26 != 0) { + if (!JHIMCCRead(mChannel, mReadOffset + field_0xc, mTempBuf + var_r27, var_r26)) { + return 0; + } + } + + var_r28 = readDataFromBuf(pBuf, size); + } + + return var_r28; +} + +void JHIMccBufReader::readEnd() { + if (isPort()) { + setHeaderToBuf(mEndPos, 0, 0x20); + + JHIReport("DEBUG: readEnd: Point:%08x\n", mEndPos); + + if (!JHIMCCWrite(mChannel, mReadOffset + field_0x8, mTempBuf, 0x20)) { + return; + } + } +} + +JHIMccBufWriter::JHIMccBufWriter(u16 channel, u16 param_1, u32 param_2) + : JHIMccBuf(channel, param_1, param_2) {} + +JHIMccBufWriter::~JHIMccBufWriter() {} + +int JHIMccBufWriter::writeBegin() { + int var_r29 = 0; + + if (!isPort()) { + return 0; + } + + if (!readData(mWriteOffset + field_0x8, &mBeginPos)) { + return 0; + } + + if (!readData(mWriteOffset + field_0xa, &mEndPos)) { + return 0; + } + + u32 var_r30; + if (mBeginPos == field_0xc) { + var_r30 = field_0x1c + field_0xc; + var_r30 -= 0x20; + } else { + var_r30 = mBeginPos - 0x20; + } + + if (mEndPos > var_r30) { + var_r29 = (field_0x1c - (mEndPos - var_r30)) - 0x20; + } else if (mEndPos < var_r30) { + var_r29 = (var_r30 - mEndPos) - 0x20; + } + + JHIReport("DEBUG: writeBegin: R:%08x W:%08x\n", mBeginPos, mEndPos); + return var_r29; +} + +int JHIMccBufWriter::write(void* pBuffer, u32 size) { + if (!isPort()) { + return 0; + } + + u32 var_r26; + u32 var_r27; + u32 var_r28; + + // Probably fake match + var_r28 = var_r28; + + u32 var_r29 = setDataToBuf(pBuffer, size); + if (mBeginPos == field_0xc) { + var_r27 = field_0x1c + field_0xc; + var_r27 -= 0x20; + } else { + var_r27 = mBeginPos - 0x20; + } + + if (mEndPos > var_r27) { + int x; + var_r26 = field_0x1c - (mEndPos - var_r27); + var_r28 = (field_0x1c + field_0xc) - mEndPos; + + if (var_r28 >= var_r29) { + if (!JHIMCCWrite(mChannel, mWriteOffset + mEndPos, mTempBuf, var_r29)) { + return 0; + } + + mEndPos += var_r29; + } else { + if (!JHIMCCWrite(mChannel, mWriteOffset + mEndPos, mTempBuf, var_r28)) { + return 0; + } else if (var_r29 - var_r28 != 0) { + if (!JHIMCCWrite(mChannel, mWriteOffset + field_0xc, mTempBuf + var_r28, var_r29 - var_r28)) { + return 0; + } + } + + mEndPos = field_0xc + (var_r29 - var_r28); + } + } else if (mEndPos < var_r27) { + var_r26 = var_r27 - mEndPos; + + if (!JHIMCCWrite(mChannel, mWriteOffset + mEndPos, mTempBuf, var_r29)) { + return 0; + } + + mEndPos += var_r29; + } + + if (mEndPos == field_0xc + field_0x1c) { + mEndPos = field_0xc; + } + + return var_r29; +} + +void JHIMccBufWriter::writeEnd() { + if (isPort()) { + setHeaderToBuf(mEndPos, 0, 0x20); + + JHIReport("DEBUG: writeEnd: Point:%08x\n", mEndPos); + + if (!JHIMCCWrite(mChannel, mWriteOffset + field_0xa, mTempBuf, 0x20)) { + return; + } + } +} diff --git a/libs/JSystem/src/JHostIO/JHIMemBuf.cpp b/libs/JSystem/src/JHostIO/JHIMemBuf.cpp new file mode 100644 index 0000000000..4fec9ad532 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JHIMemBuf.cpp @@ -0,0 +1,75 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHICommonMem.h" +#include "JSystem/JKernel/JKRHeap.h" +#ifdef __REVOLUTION_SDK__ +#include <revolution.h> +#else +#include <dolphin.h> +#endif + +int JHIMemBuf::create() { + int rt = 1; + if (mp_buffer == NULL) { + mp_buffer = new (32) u8[0x20000]; + + if (mp_buffer == NULL) { + rt = 0; + OS_REPORT("ERROR: hioSync Alloc Mem NG!\n"); + } else { + OS_REPORT("INFO: hioSync Alloc Mem OK! %08x\n", mp_buffer); + } + } + + return rt; +} + +int JHIMemBuf::open() { + return 1; +} + +void JHIMemBuf::close() { + if (mp_buffer != NULL) { + delete[] mp_buffer; + } +} + +JHIMemBuf::~JHIMemBuf() { + close(); +} + +u8* JHIMemBuf::getPointer() const { + return mp_buffer; +} + +u32 JHIMemBuf::readIO(u32 position) const { + u32 data; + readIO(position, &data); + return data; +} + +void JHIMemBuf::readIO(u32 position, u32* out_data) const { + u8* read_ptr = getPointer() + position; + *out_data = (read_ptr[0] << 0x18) | + (read_ptr[1] << 0x10) | + (read_ptr[2] << 0x08) | + (read_ptr[3] << 0x00); +} + +void JHIMemBuf::writeIO(u32 position, u8* src_data, u32 length) const { + u8* write_ptr = getPointer() + position; + + while (--length != 0) { + *write_ptr = *src_data++; + write_ptr++; + } +} + +void JHIMemBuf::writeIO(u32 position, u32 data) const { + u8* write_ptr = getPointer() + position; + + *write_ptr++ = data >> 0x18; + *write_ptr++ = data >> 0x10; + *write_ptr++ = data >> 0x08; + *write_ptr++ = data >> 0x00; +} diff --git a/libs/JSystem/src/JHostIO/JHIRMcc.cpp b/libs/JSystem/src/JHostIO/JHIRMcc.cpp new file mode 100644 index 0000000000..b22a19d365 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JHIRMcc.cpp @@ -0,0 +1,123 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHIMccBuf.h" +#include <revolution/hio2.h> + +HIO2DeviceType gExiDevice = HIO2_DEVICE_INVALID; +u8 data_8074bd04 = 1; + +s32 ghHIO2; +JHIMccContext tContext_old; +JHIMccContext tContext_new; +bool data_8074d138; +u8 data_8074d139; + +BOOL JHIhio2CallbackEnum(HIO2DeviceType type) { + gExiDevice = type; + return 0; +} + +void JHIhio2DisconnectCallback(s32) { + gExiDevice = HIO2_DEVICE_INVALID; +} + +u32 JHIInitInterface() { + if (data_8074bd04) { + if (!HIO2Init()) { + return 0; + } + + if (!HIO2EnumDevices(JHIhio2CallbackEnum)) { + return 0; + } + + data_8074bd04 = 0; + } + + if (gExiDevice == HIO2_DEVICE_INVALID) { + return 0; + } + + if (data_8074d139 != 0) { + HIO2Close(ghHIO2); + data_8074d139 = 0; + } + + if (data_8074d139 == 0) { + ghHIO2 = HIO2Open(gExiDevice, 0, JHIhio2DisconnectCallback); + if (ghHIO2 == -1) { + return 0; + } + + data_8074d139 = 1; + } + + return 1; +} + +bool JHINegotiateInterface(u32) { + return 0; +} + +JHIMccContext JHIGetHiSpeedContext() { + if (tContext_new.mp_reader == NULL) { + tContext_new.mp_reader = new JHIMccBufReader(1, 0x18, 0x6000); + } + + if (tContext_new.mp_writer == NULL) { + tContext_new.mp_writer = new JHIMccBufWriter(1, 0x18, 0x6000); + } + + return tContext_new; +} + +JHIMccContext JHIGetLowSpeedContext() { + if (tContext_old.mp_reader == NULL) { + tContext_old.mp_reader = new JHIMccBufReader(1, 2, 0); + } + + if (tContext_old.mp_writer == NULL) { + tContext_old.mp_writer = new JHIMccBufWriter(1, 2, 0); + } + + return tContext_old; +} + +BOOL JHIInitMCC(JHIMccContext* pCtx, bool* param_1) { + JHIGetHiSpeedContext(); + JHIGetLowSpeedContext(); + + if (!JHIInitInterface()) { + *pCtx = tContext_old; + return FALSE; + } + + data_8074d138 = JHINegotiateInterface(800); + if (data_8074d138) { + tContext_new.mp_reader->enablePort(); + tContext_new.mp_writer->enablePort(); + tContext_new.mp_reader->init(); + tContext_new.mp_writer->init(); + } else { + tContext_old.mp_reader->enablePort(); + tContext_old.mp_writer->enablePort(); + tContext_old.mp_reader->init(); + tContext_old.mp_writer->init(); + } + + if (param_1 != NULL) { + *param_1 = data_8074d138; + } + + if (data_8074d138) { + *pCtx = tContext_new; + } else { + *pCtx = tContext_old; + } + + return TRUE; +} + +s32 JHIGetHIO2Handle() { + return ghHIO2; +} diff --git a/libs/JSystem/src/JHostIO/JHIhioASync.cpp b/libs/JSystem/src/JHostIO/JHIhioASync.cpp new file mode 100644 index 0000000000..bc8c5b9e2c --- /dev/null +++ b/libs/JSystem/src/JHostIO/JHIhioASync.cpp @@ -0,0 +1,174 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHIMccBuf.h" +#include "JSystem/JHostIO/JHIRMcc.h" +#ifdef __REVOLUTION_SDK__ +#include <revolution.h> +#else +#include <dolphin.h> +#endif +#include "global.h" + +u32 gsEnableHostio; +u32 gsEnableInterface; +u32 gsDataToRead; + +u8* gsReadBuf; +u8* gsWriteBuf; +JHICommBufReader* gsJHIrecvBuf; +JHICommBufWriter* gsJHIsendBuf; + +JHIMccContext gMccContext; + +BOOL JHIInit(u32 enabled) { + gsEnableHostio = enabled; + gsDataToRead = 0; + gsEnableInterface = TRUE; + + if (gsEnableHostio) { + OS_REPORT("INFO:********************************\n"); + OS_REPORT("INFO: Opening Hostio service...\n"); + + if (!JHIInitMCC(&gMccContext, NULL)) { + gsEnableInterface = FALSE; + OS_REPORT("ERROR: Cannot Open HostIO Interface..\n"); + OS_REPORT("INFO: *** Disable JHostIO ***\n"); + } + + gsReadBuf = new (32) u8[0xC000]; + gsWriteBuf = new (32) u8[0xC000]; + + if (gsReadBuf == NULL || gsWriteBuf == NULL) { + gsEnableInterface = FALSE; + OS_REPORT("ERROR: Cannot alloc transport buffer..\n"); + OS_REPORT("INFO: *** Disable JHostIO ***\n"); + } + } + + return gsEnableInterface && gsEnableHostio; +} + +static void dummyString() { + DEAD_STRING("INFO:Quitting Hostio..."); +} + +u32 JHIEventLoop() { + static u32 tNowWrite; + static u32 tNowRead; + static u8* tReadBuf; + static u8* tWriteBuf; + + int var_r30; + u32 available_size; + + if (gsEnableHostio && gsEnableInterface) { + if (tNowRead != 0) { + var_r30 = gsJHIsendBuf->writeBegin(); + if (var_r30 >= tNowRead) { + gsJHIsendBuf->write(tReadBuf, tNowRead); + gsJHIsendBuf->writeEnd(); + tNowRead = 0; + tReadBuf = gsReadBuf; + } else if (var_r30 != 0) { + gsJHIsendBuf->write(tReadBuf, var_r30); + gsJHIsendBuf->writeEnd(); + tNowRead -= var_r30; + tReadBuf += var_r30; + } + } else { + available_size = gMccContext.mp_reader->available(); + if (available_size != 0) { + JHIReport("DEBUG: Dolphin <- PC Data Available : Size:%d\n", available_size); + gMccContext.mp_reader->readBegin(); + + u32 var_r27 = gMccContext.mp_reader->read(gsReadBuf); + if (var_r27 != 0) { + gMccContext.mp_reader->readEnd(); + tNowRead = 0; + tReadBuf = gsReadBuf; + + u32 var_r28 = gsJHIsendBuf->writeBegin(); + if (var_r28 >= var_r27) { + gsJHIsendBuf->write(tReadBuf, var_r27); + gsJHIsendBuf->writeEnd(); + } else { + if (var_r28 != 0) { + gsJHIsendBuf->write(tReadBuf, var_r28); + gsJHIsendBuf->writeEnd(); + } + tNowRead = var_r27 - var_r28; + tReadBuf = gsReadBuf + var_r28; + } + } + } + } + + if (tNowWrite != 0) { + var_r30 = gMccContext.mp_writer->writeBegin(); + if (var_r30 > tNowWrite) { + gMccContext.mp_writer->write(tWriteBuf, tNowWrite); + gMccContext.mp_writer->writeEnd(); + tNowWrite = 0; + tWriteBuf = gsWriteBuf; + } else if (var_r30 != 0) { + gMccContext.mp_writer->write(tWriteBuf, var_r30); + gMccContext.mp_writer->writeEnd(); + tNowWrite -= var_r30; + tWriteBuf += var_r30; + } + } else { + available_size = gsJHIrecvBuf->available(); + if (available_size != 0) { + JHIReport("DEBUG: Dolphin -> PC Data Available : Size:%d\n", available_size); + + u32 temp_r26 = available_size < 0xC000 ? available_size : 0xC000; + gsJHIrecvBuf->readBegin(); + gsJHIrecvBuf->read(gsWriteBuf, temp_r26); + gsJHIrecvBuf->readEnd(); + tNowWrite = 0; + tWriteBuf = gsWriteBuf; + + var_r30 = gMccContext.mp_writer->writeBegin(); + if (var_r30 > temp_r26) { + gMccContext.mp_writer->write(tWriteBuf, temp_r26); + gMccContext.mp_writer->writeEnd(); + } else if (var_r30 != 0) { + gMccContext.mp_writer->write(tWriteBuf, var_r30); + gMccContext.mp_writer->writeEnd(); + tNowWrite = temp_r26 - var_r30; + tWriteBuf = gsWriteBuf + var_r30; + } + } + } + + if (!gMccContext.mp_reader->isPort() || !gMccContext.mp_writer->isPort()) { + gsEnableInterface = 0; + } + (void)0; + } else if (!gsEnableInterface && gsEnableHostio != 0 && JHIInitInterface()) { + OS_REPORT("INFO: JHostIO: Enabled USB2EXI Interface\n"); + bool sp8 = JHINegotiateInterface(800); + if (sp8) { + gMccContext = JHIGetHiSpeedContext(); + } else { + gMccContext = JHIGetLowSpeedContext(); + } + + gMccContext.mp_reader->enablePort(); + gMccContext.mp_writer->enablePort(); + gMccContext.mp_reader->init(); + gMccContext.mp_writer->init(); + gsEnableInterface = TRUE; + } + + return 0; +} + +BOOL JOR_CHECKINTERFACE() { + return (gsEnableInterface && gsEnableHostio) != 0; +} + +void JHISetBuffer(JHIContext* pCtx) { + gsJHIrecvBuf = pCtx->mp_reader; + gsJHIsendBuf = pCtx->mp_writer; +} diff --git a/libs/JSystem/src/JHostIO/JOREntry.cpp b/libs/JSystem/src/JHostIO/JOREntry.cpp new file mode 100644 index 0000000000..0a6b0271c3 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JOREntry.cpp @@ -0,0 +1,24 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JORServer.h" +#include "JSystem/JHostIO/JOREntry.h" +#include "JSystem/JHostIO/JHIhioASync.h" + +void JORInit() { + JHIInit(TRUE); + + JHICommBufWriter* pComWriter = new JHICommBufWriter(0x10000, 0x10000, 4); + JHICommBufReader* pComReader = new JHICommBufReader(0, 0x10000, 4); + + JHIContext ctx; + ctx.mp_reader = new JHICommBufReader(0x10000, 0x10000, 4); + ctx.mp_writer = new JHICommBufWriter(0, 0x10000, 4); + + JHIComPortManager<JHICmnMem>* pPortMng = JHIComPortManager<JHICmnMem>::create(); + pPortMng->getRefPort().setBuf(pComReader, pComWriter); + JHISetBuffer(&ctx); + + JORServer* pServer = JORServer::create(); + pPortMng->addTag(pServer); + pServer->sendReset(); +} diff --git a/libs/JSystem/src/JHostIO/JORFile.cpp b/libs/JSystem/src/JHostIO/JORFile.cpp new file mode 100644 index 0000000000..f689f06534 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JORFile.cpp @@ -0,0 +1,189 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JORFile.h" +#include "JSystem/JHostIO/JORServer.h" +#ifdef __REVOLUTION_SDK__ +#include <revolution.h> +#else +#include <dolphin.h> +#endif + +JORFile::JORFile() +: mHandle(0), + mFileLength(0), + mStatus(EStatus_WAIT), + mNFileName(0), + field_0x18(0), + mDataStream() {} + +int JORFile::countMaskSize(const char* mask) { + u32 var_r28 = 0; + u32 var_r30 = 0; + + while (true) { + u32 var_r27 = var_r30; + + while (mask[var_r30] != 0) { + var_r30++; + if (var_r30 - var_r27 > 0xFF) { + return 0; + } + } + + var_r30++; + while (mask[var_r30] != 0) { + var_r30++; + if (var_r30 - var_r27 > 0xFF) { + return 0; + } + } + + var_r30++; + if (mask[var_r30] == 0) { + return var_r30 + 1; + } + + var_r28++; + if (var_r28 > 0x28) { + return 0; + } + } +} + +void JORFile::waitMessage_() { + while (mStatus == EStatus_WAIT) { + JOR_MESSAGELOOP(); + } +} + +int JORFile::open(const char* path, u32 flags, const char* extMask, const char* defaultExt, const char* param_4, const char* fileSuffix) { + if (mHandle != 0) { + return 0; + } + + mStatus = EStatus_WAIT; + mFlags = flags; + + if (extMask == NULL) { + extMask = ""; + } + + u32 mask_size = countMaskSize(extMask); + JORMContext* mctx = JORServer::getInstance()->attachMCTX(MCTX_MSG_FIO); + mctx->openFile(this, mFlags, path, extMask, mask_size, defaultExt, param_4, fileSuffix); + JORServer::getInstance()->releaseMCTX(mctx); + + waitMessage_(); + + if (mHandle == 0) { + return 0; + } + + return 1; +} + +void JORFile::close() { + JORMContext* mctx; + if (mHandle != 0) { + mStatus = EStatus_WAIT; + mctx = JORServer::getInstance()->attachMCTX(MCTX_MSG_FIO); + mctx->closeFile(this); + JORServer::getInstance()->releaseMCTX(mctx); + + waitMessage_(); + mHandle = 0; + } +} + +void JORFile::readBegin_(s32 len) { + mStatus = EStatus_WAIT; + JORMContext* mctx = JORServer::getInstance()->attachMCTX(MCTX_MSG_FIO); + mctx->readBegin(this, len); + JORServer::getInstance()->releaseMCTX(mctx); + + waitMessage_(); +} + +void JORFile::readLoop_() { + mStatus = EStatus_WAIT; + JORMContext* mctx = JORServer::getInstance()->attachMCTX(MCTX_MSG_FIO); + mctx->readData(this); + JORServer::getInstance()->releaseMCTX(mctx); + + waitMessage_(); +} + +s32 JORFile::readData(void* buffer, s32 length) { + if (mHandle == 0) { + return 0; + } + + s32 len = length == 0 ? mFileLength : length; + setBuffer(buffer, len); + readBegin_(len); + + do { + readLoop_(); + if (mStatus == EStatus_READ_BEGIN) { + setBuffer(NULL, 0); + return 0; + } + } while (mStatus != EStatus_WRITE_END); + + setBuffer(NULL, 0); + DCFlushRange(buffer, len); + return len; +} + +void JORFile::setBuffer(void* buffer, s32 length) { + mDataStream.setBuffer(buffer, length); +} + +void JORFile::writeBegin_(s32 len) { + mStatus = EStatus_WAIT; + JORMContext* mctx = JORServer::getInstance()->attachMCTX(MCTX_MSG_FIO); + mctx->writeBegin(this, mFlags, len); + JORServer::getInstance()->releaseMCTX(mctx); + + waitMessage_(); +} + +void JORFile::writeLoop_(const void* pBuffer, s32 size, u32 pos) { + mStatus = EStatus_WAIT; + JORMContext* mctx = JORServer::getInstance()->attachMCTX(MCTX_MSG_FIO); + mctx->writeData(this, pBuffer, size, pos); + JORServer::getInstance()->releaseMCTX(mctx); + + waitMessage_(); +} + +void JORFile::writeDone_(s32 len) { + mStatus = EStatus_WAIT; + JORMContext* mctx = JORServer::getInstance()->attachMCTX(MCTX_MSG_FIO); + mctx->writeDone(this, len); + JORServer::getInstance()->releaseMCTX(mctx); + + waitMessage_(); +} + +s32 JORFile::writeData(const void* buffer, s32 length) { + if (mHandle == 0) { + return 0; + } + + s32 len = length == 0 ? mFileLength : length; + writeBegin_(len); + + u32 pos = 0; + s32 size = 0; + u8* buf_start = (u8*)buffer; + do { + size = len - pos > 0xF00 ? 0xF00 : len - pos; + writeLoop_(buf_start + pos, size, pos); + + pos += size; + } while (len - pos != 0); + + writeDone_(len); + return len; +} diff --git a/libs/JSystem/src/JHostIO/JORHostInfo.cpp b/libs/JSystem/src/JHostIO/JORHostInfo.cpp new file mode 100644 index 0000000000..904cb27fbf --- /dev/null +++ b/libs/JSystem/src/JHostIO/JORHostInfo.cpp @@ -0,0 +1,58 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JORHostInfo.h" +#include "JSystem/JHostIO/JORServer.h" + +// End of each month in standard year +static s32 YearDays[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, +}; + +// End of each month in leap year +static s32 LeapYearDays[] = { + 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, +}; + +static BOOL IsLeapYear(int year) { + return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); +} + +BOOL JORGetYearDays(int year, int mon) { + s32* days = IsLeapYear(year) ? LeapYearDays : YearDays; + return days[mon]; +} + +bool JORGetHostInfo(u32 request_type, JORHostInfo* pHostinfo) { + JORMContext* mctx = JORServer::getInstance()->attachMCTX(MCTX_MSG_GET_HOST_INFO); + mctx->sendHostInfoRequest(request_type, pHostinfo); + JORServer::getInstance()->releaseMCTX(mctx); + + while (pHostinfo->getResult() == 0) { + JOR_MESSAGELOOP(); + } + + return pHostinfo->getResult() == 1; +} + +void JORGetComputerName(char* buffer, u32 buffer_size) { + JORHostInfo_String string; + string.setStringBuffer(buffer); + string.setBufferSize(buffer_size); + + JORGetHostInfo(HOSTINFO_REQ_COMPUTER_NAME, &string); +} + +void JORGetUserName(char* buffer, u32 buffer_size) { + JORHostInfo_String string; + string.setStringBuffer(buffer); + string.setBufferSize(buffer_size); + + JORGetHostInfo(HOSTINFO_REQ_USERNAME, &string); +} + +void JORGetLocalTime(OSCalendarTime* pCalendarTime) { + JORHostInfo_CalendarTime calendar_time; + calendar_time.setCalendarTimeBuffer(pCalendarTime); + + JORGetHostInfo(HOSTINFO_REQ_LOCAL_TIME, &calendar_time); +} diff --git a/libs/JSystem/src/JHostIO/JORMessageBox.cpp b/libs/JSystem/src/JHostIO/JORMessageBox.cpp new file mode 100644 index 0000000000..e7ce1cc954 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JORMessageBox.cpp @@ -0,0 +1,16 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JORServer.h" + +u32 JORMessageBox(const char* message, const char* title, u32 style) { + u32 status = 0; + JORMContext* mctx = JORServer::getInstance()->attachMCTX(MCTX_MSG_OPEN_MESSAGE_BOX); + mctx->openMessageBox(&status, style, message, title); + JORServer::getInstance()->releaseMCTX(mctx); + + while (status == 0) { + JOR_MESSAGELOOP(); + } + + return status; +} diff --git a/libs/JSystem/src/JHostIO/JORServer.cpp b/libs/JSystem/src/JHostIO/JORServer.cpp new file mode 100644 index 0000000000..18086d36d8 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JORServer.cpp @@ -0,0 +1,822 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JORServer.h" +#include "JSystem/JHostIO/JORReflexible.h" +#include "JSystem/JHostIO/JORFile.h" +#include "JSystem/JHostIO/JORHostInfo.h" +#include "JSystem/JSupport/JSUMemoryStream.h" +#include <cstring> + +void JOREventCallbackListNode::JORAppend() { + JORServer* pServer = JORServer::getInstance(); + JUT_ASSERT(51, pServer!=NULL); + pServer->appendEventCallbackListNode(this); +} + +void JOREventCallbackListNode::JORRemove() { + JORServer* pServer = JORServer::getInstance(); + JUT_ASSERT(57, pServer!=NULL); + pServer->removeEventCallbackListNode(this); +} + +JOREventCallbackListNode::JOREventCallbackListNode(u32 param_0, u32 param_1, bool append) { + field_0xc = param_0; + field_0x10 = param_1; + + if (append) { + JORAppend(); + } +} + +JOREventCallbackListNode::~JOREventCallbackListNode() { + JORRemove(); +} + +void JORReflexible::listen(u32 command, const JOREvent* event) { + switch (command) { + case JORServer::ECommand_GenObjInfo: + genObjectInfo((JORGenEvent*)event); + break; + case JORServer::ECommand_NodeEvent: + listenNodeEvent((JORNodeEvent*)event); + break; + case JORServer::ECommand_PropertyEvent: + listenPropertyEvent((JORPropertyEvent*)event); + break; + } +} + +void JORReflexible::genObjectInfo(const JORGenEvent* event) { + JORMContext* mctx = getJORServer()->attachMCTX(MCTX_MSG_GEN_OBJ_INFO); + mctx->startNode("", this, 0, 0); + genMessage(mctx); + mctx->endNode(); + getJORServer()->releaseMCTX(mctx); +} + +void JORReflexible::listenNodeEvent(const JORNodeEvent*) {} + +void JORReflexible::listenPropertyEvent(const JORPropertyEvent* pEvent) { + if (pEvent->kind & JORPropertyEvent::EKind_HasListener) { + JORServer* pServer = getJORServer(); + + JORPropertyEvent* event = (JORPropertyEvent*)pEvent; + event->kind &= ~JORPropertyEvent::EKind_HasListener; + + switch (pEvent->type) { + case 'RNGf': + case 'RNGi': + case 'RBTN': + case 'CMBX': + if (pEvent->field_0x14 >= 4) { + pEvent->field_0x10->listenPropertyEvent(pEvent); + } + break; + case 'CHBX': + if (pEvent->field_0x14 >= 4) { + pEvent->field_0x10->listenPropertyEvent(pEvent); + } + break; + case 'EDBX': + case 'BUTN': + pEvent->field_0x10->listenPropertyEvent(pEvent); + break; + } + + event->kind |= JORPropertyEvent::EKind_HasListener; + } else if (!(pEvent->kind & JORPropertyEvent::EKind_ValueID)) { + switch (pEvent->type) { + case 'RBTN': + case 'RNGi': + case 'RNGf': + case 'CMBX': + if (pEvent->field_0x14 >= 4) { + JORPropertyEvent* event = (JORPropertyEvent*)pEvent; + JORServer::defSetVal((void*)event->id, event->kind, event->field_0x18.U32); + } + break; + case 'CHBX': + if (pEvent->field_0x14 >= 4) { + JORPropertyEvent* event = (JORPropertyEvent*)pEvent; + JORServer::defSetBitVal((void*)event->id, event->kind, (u16)event->field_0x18.U16[0], (u16)event->field_0x18.U16[1]); + } + break; + case 'EDBX': + JORPropertyEvent* event = (JORPropertyEvent*)pEvent; + JSUMemoryInputStream stream(&event->field_0x18, event->field_0x14); + stream >> (char*)event->id; + break; + } + return; + } +} + +JORServer* JORServer::instance; + +JORServer* JORServer::create() { + if (instance == NULL) { + instance = new JORServer(); + } + + return instance; +} + +void JORServer::defSetVal(void* ptr, u32 kind, s32 val) { + switch (jhostio::GetEKindSize(kind)) { + case jhostio::EKind_8B: + *(u8*)ptr = val; + break; + case jhostio::EKind_16B: + *(u16*)ptr = val; + break; + case jhostio::EKind_32B: + *(u32*)ptr = val; + break; + } +} + +void JORServer::defSetBitVal(void* ptr, u32 kind, u16 param_2, u16 param_3) { + param_2 &= param_3; + + switch (jhostio::GetEKindSize(kind)) { + case jhostio::EKind_8B: { + u8* kptr = (u8*)ptr; + *kptr &= (u8)~param_3; + *kptr |= (u8)param_2; + break; + } + case jhostio::EKind_16B: { + u16* kptr = (u16*)ptr; + *kptr &= (u16)~param_3; + *kptr |= param_2; + } + } +} + +JORMContext* JORServer::attachMCTX(u32 msgID) { + m_context.bufInit(); + m_context.putMsgID(msgID); + return &m_context; +} + +void JORServer::releaseMCTX(JORMContext* mctx) { + ASSERTMSGLINE(292, mctx->msgSize() < 0x10000, "JORServer:releaseMCTX: context buffer probably overflowed.\n"); + + if (mctx->msgSize() > 4) { + const s32 var_r28 = send(mctx->msgPtr(), mctx->msgSize()); + } +} + +void JORServer::receive(const char* pBuffer, s32 length) { + JSUMemoryInputStream stream(pBuffer, length); + + u32 command; + stream >> command; + + if (!stream.isGood()) { + OS_REPORT("JORServer::receive : データが足りない\n"); + OS_REPORT("JORServer::receive : データが足りない\n"); + return; + } + + switch (command) { + case ECommand_GetRootObj: + if (mp_rootObj != NULL) { + OS_REPORT("Get RootObject ref(%08X)\n", mp_rootObj); + m_context.bufInit(); + m_context.putMsgID(MCTX_MSG_GET_ROOT_OBJ); + m_context.genRootNode(m_rootName, mp_rootObj, field_0x10064, field_0x10068); + send(m_context.msgPtr(), m_context.msgSize()); + } + break; + case ECommand_NodeEvent: { + u32 obj_addr; + stream.read(obj_addr); + JORNodeEvent* pEvent = (JORNodeEvent*)(pBuffer + stream.getPosition()); + stream.skip(4); + + if (stream.isGood()) { + reinterpret_cast<JORReflexible*>(obj_addr)->listen(command, pEvent); + } + } + break; + case ECommand_PropertyEvent: { + u32 obj_addr; + stream.read(obj_addr); + JORPropertyEvent* pEvent = (JORPropertyEvent*)(pBuffer + stream.getPosition()); + stream.skip(0x18); + + if (stream.isGood()) { + stream.skip(pEvent->field_0x14); + } + + if (stream.isGood()) { + reinterpret_cast<JORReflexible*>(obj_addr)->listen(command, pEvent); + } + } + break; + case ECommand_GenObjInfo: { + u32 obj_addr; + stream.read(obj_addr); + + if (stream.isGood()) { + reinterpret_cast<JORReflexible*>(obj_addr)->listen(command, NULL); + } + } + break; + case ECommand_FIO: + fio_dispatchMessage_(stream); + break; + case ECommand_DIR: + dir_dispatchMessage_(stream); + break; + case ECommand_ReadResultS32: + readResultS32_(stream); + break; + case ECommand_HostInfo: + hostinfo_dispatchMessage_(stream); + break; + case ECommand_ReadResultU32: + readResultU32_(stream); + break; + case ECommand_ReadOrEvent: + readOrEvent_(stream); + break; + } +} + +void JORServer::fio_openFile_(JSUMemoryInputStream& stream) { + u32 file_addr; + stream >> file_addr; + JORFile* file = (JORFile*)file_addr; + + u32 handle; + stream >> handle; + + u32 file_len; + stream >> file_len; + + u16 filename_len; + u16 basename_len; + u16 extension_name_len; + stream >> filename_len >> basename_len >> extension_name_len; + + strncpy(file->getFilename(), (const char*)stream.getPointer(), filename_len); + file->getFilename()[filename_len] = 0; + + file->setHandle(handle); + file->setFileLength(file_len); + file->setNFileName((u16)filename_len); + file->setNBaseName((u16)basename_len); + file->setNExtensionName((u16)extension_name_len); + file->setStatus(JORFile::EStatus_READ_DATA); +} + +void JORServer::fio_closeFile_(JSUMemoryInputStream& stream) { + u32 file_addr; + stream >> file_addr; + JORFile* file = (JORFile*)file_addr; + + u32 sp8; + stream >> sp8; + + if (sp8 == 0) { + OS_REPORT("Close Failed!\n"); + } + + file->setStatus(JORFile::EStatus_READ_END); +} + +void JORServer::fio_readData_(JSUMemoryInputStream& stream) { + u32 file_addr; + stream >> file_addr; + JORFile* file = (JORFile*)file_addr; + + u32 status; + stream >> status; + + if (status == JORFile::EStatus_READ_BEGIN) { + file->setStatus(status); + } else if (status == JORFile::EStatus_WRITE_BEGIN) { + file->setStatus(status); + } else if (status == JORFile::EStatus_WRITE_DATA) { + u32 position, data; + stream >> position >> data; + file->getDataStream().seek(position, JSUStreamSeekFrom_SET); + + file->getDataStream().write(stream.getPointer(), data); + file->setStatus(status); + } else if (status == JORFile::EStatus_WRITE_END) { + file->setStatus(status); + } +} + +void JORServer::fio_writeData_(JSUMemoryInputStream& stream) { + u32 file_addr; + stream >> file_addr; + JORFile* file = (JORFile*)file_addr; + + u32 status; + stream >> status; + + file->setStatus(status); +} + +void JORServer::fio_dispatchMessage_(JSUMemoryInputStream& stream) { + u32 command; + stream >> command; + + switch (command) { + case JORFile::ECommand_OPEN: + fio_openFile_(stream); + break; + case JORFile::ECommand_CLOSE: + fio_closeFile_(stream); + break; + case JORFile::ECommand_READ: + fio_readData_(stream); + break; + case JORFile::ECommand_WRITE: + fio_writeData_(stream); + break; + } +} + +void JORServer::dir_dispatchMessage_(JSUMemoryInputStream& stream) { + u32 command, status, dir_addr; + stream >> command >> dir_addr >> status; + + JORDir* dir = (JORDir*)dir_addr; + dir->setStatus(status); + + if (status != 2) { + switch (command) { + case 1: + break; + case 2: + dir_findFirstFile_(stream, dir); + break; + case 3: + dir_findNextFile_(stream, dir); + break; + case 0: + dir_browseForFolder_(stream, dir); + break; + case 5: + dir_browseForFolder_(stream, dir); + break; + } + } +} + +void JORServer::dir_findFirstFile_(JSUMemoryInputStream& stream, JORDir* directory) { + char namebuf[256]; + u32 attribute, lo_time, hi_time, handle; + stream >> handle >> attribute >> lo_time >> hi_time >> namebuf; + + directory->setFindHandle(handle); + directory->setFileAttribute(attribute); + directory->setLowDateTime(lo_time); + directory->setHighDateTime(hi_time); + strncpy(directory->getFilename(), namebuf, sizeof(namebuf) - 1); +} + +void JORServer::dir_findNextFile_(JSUMemoryInputStream& stream, JORDir* directory) { + char namebuf[256]; + u32 attribute, lo_time, hi_time; + stream >> attribute >> lo_time >> hi_time >> namebuf; + + directory->setFileAttribute(attribute); + directory->setLowDateTime(lo_time); + directory->setHighDateTime(hi_time); + strncpy(directory->getFilename(), namebuf, sizeof(namebuf) - 1); +} + +void JORServer::dir_browseForFolder_(JSUMemoryInputStream& stream, JORDir* directory) { + char namebuf[256]; + u32 attribute, lo_time, hi_time; + stream >> attribute >> lo_time >> hi_time >> namebuf; + + directory->setFileAttribute(attribute); + directory->setLowDateTime(lo_time); + directory->setHighDateTime(hi_time); + strncpy(directory->getFilename(), namebuf, sizeof(namebuf) - 1); +} + +void JORServer::hostinfo_dispatchMessage_(JSUMemoryInputStream& stream) { + u32 command, spC, hostinfo_addr; + stream >> command >> hostinfo_addr >> spC; + + JORHostInfo* hostinfo = (JORHostInfo*)hostinfo_addr; + hostinfo->setResult(spC != 0 ? 1 : 2); + + if (spC != 0) { + switch (command) { + case HOSTINFO_REQ_COMPUTER_NAME: + hostinfo_recvString_(stream, (JORHostInfo_String*)hostinfo); + break; + case HOSTINFO_REQ_USERNAME: + hostinfo_recvString_(stream, (JORHostInfo_String*)hostinfo); + break; + case HOSTINFO_REQ_LOCAL_TIME: + hostinfo_localTime_(stream, (JORHostInfo_CalendarTime*)hostinfo); + break; + } + } +} + +void JORServer::hostinfo_recvString_(JSUMemoryInputStream& stream, JORHostInfo_String* pString) { + char buffer[256]; + stream >> buffer; + strncpy(pString->getString(), buffer, pString->getBufferSize()); +} + +void JORServer::hostinfo_localTime_(JSUMemoryInputStream& stream, JORHostInfo_CalendarTime* pCalendarTime) { + u16 year, month, weekday, monthday, hours, minutes, seconds, milliseconds; + stream >> year + >> month + >> weekday + >> monthday + >> hours + >> minutes + >> seconds + >> milliseconds; + + OSCalendarTime* pTime = pCalendarTime->getCalendarTime(); + pTime->sec = seconds; + pTime->min = minutes; + pTime->hour = hours; + pTime->mday = monthday; + pTime->mon = month - 1; + pTime->year = year; + pTime->wday = weekday; + pTime->msec = milliseconds; + pTime->usec = 0; + pTime->yday = monthday + JORGetYearDays(year, month - 1); +} + +void JORServer::sendReset() { + u32 spC = JHIhtonl(0); + send(&spC, 4); +} + +void JORServer::setRootNode(const char* name, JORReflexible* node, u32 param_2, u32 param_3) { + mp_rootObj = node; + if (name == NULL) { + name = "ルート"; + } + + strncpy(m_rootName, name, sizeof(m_rootName) - 1); + m_rootName[sizeof(m_rootName) - 1] = 0; + field_0x10064 = param_2; + field_0x10068 = param_3; +} + +void JORServer::readResultU32_(JSUMemoryInputStream& stream) { + u32 ptr_addr, val; + stream >> ptr_addr >> val; + + u32* ptr = (u32*)ptr_addr; + *ptr = val; +} + +void JORServer::readResultS32_(JSUMemoryInputStream& stream) { + u32 ptr_addr, val; + stream >> ptr_addr >> val; + + s32* ptr = (s32*)ptr_addr; + *ptr = val; +} + +void JORServer::readOrEvent_(JSUMemoryInputStream& stream) { + if (m_eventDone) { + stream >> m_eventNum; + + u16 name_len; + stream >> name_len; + if (name_len >= 0x1000) { + name_len = 0x1000 - 1; + } + + stream.read(m_eventName, name_len); + m_eventName[name_len] = 0; + m_event = true; + } +} + +void JORServer::doneEvent() { + if (!m_eventDone) { + m_eventDone = true; + + u32 sp8 = JHIhtonl(0x10); + send(&sp8, 4); + } +} + +void JORMContext::genNodeSub(const char* name, JORReflexible* node, u32 param_2, u32 param_3) { + mOutputStream << name; + putNode(node); + + mOutputStream << param_2; + + if (param_2 & 4) { + mOutputStream << param_3; + } +} + +void JORMContext::endNode() { + mOutputStream << MCTX_COMMAND_END_NODE; +} + +void JORMContext::invalidNode(JORReflexible* node, u32 param_1) { + mOutputStream << MCTX_COMMAND_INVALID_NODE; + putNode(node); + + mOutputStream << param_1; +} + +void JORMContext::genControl(u32 type, u32 kind, const char* label, u32 style, u32 id, + JOREventListener* pListener, u32 initValue) +{ + mOutputStream << type << kind << label << style << id; + + if (kind & JORPropertyEvent::EKind_HasListener) { + mOutputStream << (uintptr_t)pListener; + } + + if ((kind & JORPropertyEvent::EKind_ValueID) && type != 'EDBX') { + kind |= 0x20; + } + + if (jhostio::GetEKindSize(kind) != 0) { + mOutputStream << initValue; + } +} + +void JORMContext::genSliderSub(u32 kind, const char* label, u32 id, u32 style, s32 initValue, s32 rangeMin, + s32 rangeMax, JOREventListener* pListener, u16 posX, u16 posY, + u16 width, u16 height) +{ + if (pListener != NULL) { + kind |= JORPropertyEvent::EKind_HasListener; + } + + mOutputStream << MCTX_COMMAND_GEN_CONTROL; + genControl(kind & JORPropertyEvent::EKind_FloatValue ? 'RNGf' : 'RNGi', kind, label, style, id, pListener, initValue); + + mOutputStream << rangeMin << rangeMax; + mOutputStream << posX << posY << width << height; +} + +void JORMContext::genCheckBoxSub(u32 kind, const char* label, u32 id, u32 style, u16 initValue, u16 mask, + JOREventListener* pListener, u16 posX, u16 posY, u16 width, + u16 height) +{ + if (pListener != NULL) { + kind |= JORPropertyEvent::EKind_HasListener; + } + + mOutputStream << MCTX_COMMAND_GEN_CONTROL; + genControl('CHBX', kind, label, style, id, pListener, (mask << 0x10) | initValue); + + mOutputStream << posX << posY << width << height; +} + +void JORMContext::startSelectorSub(u32 type, u32 kind, const char* label, u32 id, u32 style, s32 initValue, + JOREventListener* pListener, u16 posX, u16 posY, u16 width, + u16 height) +{ + if (pListener != NULL) { + kind |= JORPropertyEvent::EKind_HasListener; + } + + mOutputStream << MCTX_COMMAND_START_SELECTOR; + genControl(type, kind, label, style, id, pListener, initValue); + + mOutputStream << posX << posY << width << height; +} + +void JORMContext::endSelectorSub() { + mOutputStream << MCTX_COMMAND_END_SELECTOR; +} + +void JORMContext::genSelectorItemSub(const char* label, s32 itemNo, u32 param_2, u16 posX, + u16 posY, u16 width, u16 height) +{ + mOutputStream << MCTX_COMMAND_SELECTOR_ITEM << label << (u32)itemNo; + mOutputStream << param_2 << posX << posY << width << height; +} + +void JORMContext::genButton(const char* label, u32 id, u32 style, JOREventListener* pListener, + u16 posX, u16 posY, u16 width, u16 height) +{ + u32 kind = 0; + if (pListener != NULL) { + kind |= JORPropertyEvent::EKind_HasListener; + } + + mOutputStream << MCTX_COMMAND_GEN_CONTROL; + genControl('BUTN', kind, label, style, id, pListener, 0); + + mOutputStream << posX << posY << width << height; +} + +void JORMContext::genLabel(const char* label, u32 id, u32 style, JOREventListener* pListener, + u16 posX, u16 posY, u16 width, u16 height) +{ + u32 kind = 0; + if (pListener != NULL) { + kind |= JORPropertyEvent::EKind_HasListener; + } + + mOutputStream << MCTX_COMMAND_GEN_CONTROL; + genControl('LABL', kind, label, style, id, pListener, 0); + + mOutputStream << posX << posY << width << height; +} + +void JORMContext::genGroupBox(const char* label, u32 id, u32 style, JOREventListener* pListener, + u16 posX, u16 posY, u16 width, u16 height) +{ + u32 kind = 0; + if (pListener != NULL) { + kind |= JORPropertyEvent::EKind_HasListener; + } + + mOutputStream << MCTX_COMMAND_GEN_CONTROL; + genControl('GRBX', kind, label, style, id, pListener, 0); + + mOutputStream << posX << posY << width << height; +} + +void JORMContext::genEditBoxID(const char* label, u32 id, const char* string, u16 length, u32 style, + JOREventListener* pListener, u16 posX, u16 posY, u16 width, u16 height) +{ + u32 kind = 0; + if (pListener != NULL) { + kind |= JORPropertyEvent::EKind_HasListener; + } + + mOutputStream << MCTX_COMMAND_GEN_CONTROL; + genControl('EDBX', kind | JORPropertyEvent::EKind_ValueID, label, style, id, pListener, 0); + + mOutputStream << length << string; + mOutputStream << posX << posY << width << height; +} + +void JORMContext::updateControl(u32 mode, u32 id, u32 param_2) { + mOutputStream << MCTX_COMMAND_UPDATE_CONTROL << mode << id; + + if (mode & 1) { + mOutputStream << param_2; + } +} + +void JORMContext::updateControl(u32 mode, u32 id, const char* param_2) { + if (mode & 2) { + mOutputStream << MCTX_COMMAND_UPDATE_CONTROL << mode << id << param_2; + } +} + +void JORMContext::updateSliderSub(u32 mode, u32 id, s32 value, s32 rangeMin, s32 rangeMax, u32 param_5) { + updateControl(mode, id, param_5); + + if (mode & 2) { + mOutputStream << value; + } + + if (mode & 4) { + mOutputStream << rangeMin << rangeMax; + } +} + +void JORMContext::updateCheckBoxSub(u32 mode, u32 id, u16 value, u16 mask, u32 param_4) { + mOutputStream << MCTX_COMMAND_UPDATE_CONTROL << (mode | JORPropertyEvent::EKind_HasListener) << id << (u32)mask; + + if (mode & 1) { + mOutputStream << param_4; + } + + if (mode & 2) { + mOutputStream << (u32)((mask << 0x10) | value); + } +} + +void JORMContext::updateSelectorSub(u32 mode, u32 id, s32 value, u32 param_3) { + updateControl(mode, id, param_3); + + if (mode & 2) { + mOutputStream << value; + } +} + +void JORMContext::updateEditBoxID(u32 mode, u32 id, const char* string, u32 param_3, u16 length) { + updateControl(mode, id, param_3); + + if (mode & 2) { + mOutputStream << string; + } + + if (mode & 0x10) { + mOutputStream << length; + } +} + +void JORMContext::editComboBoxItem(u32 param_0, u32 id, const char* param_2, s32 param_3, u32 param_4) { + updateControl(8, id, (u32)0); + + mOutputStream << param_0 << param_4 << param_2 << param_3; +} + +void JORMContext::openFile(JORFile* pFile, u32 flags, const char* path, const char* extMask, + u32 maskSize, const char* defaultExt, const char* param_6, const char* fileSuffix) +{ + if (defaultExt != NULL) { + flags |= JORFile::EFlags_DEFAULT_EXT; + } + + if (param_6 != NULL) { + flags |= JORFile::EFlags_UNK_0x20; + } + + if (fileSuffix != NULL) { + flags |= JORFile::EFlags_HAS_SUFFIX; + } + + mOutputStream << (u32)JORFile::ECommand_OPEN << (uintptr_t)pFile << flags << path; + mOutputStream << (u16)maskSize; + mOutputStream.write(extMask, maskSize); + + if (defaultExt != NULL) { + mOutputStream << defaultExt; + } + + if (param_6 != NULL) { + mOutputStream << param_6; + } + + if (fileSuffix != NULL) { + mOutputStream << fileSuffix; + } +} + +void JORMContext::closeFile(JORFile* pFile) { + mOutputStream << (u32)JORFile::ECommand_CLOSE << (uintptr_t)pFile << pFile->getHandle(); +} + +void JORMContext::readBegin(JORFile* pFile, s32 size) { + mOutputStream << (u32)JORFile::ECommand_READ + << (u32)JORFile::EStatus_READ_BEGIN + << (uintptr_t)pFile + << pFile->getHandle() + << (u32)size; +} + +void JORMContext::readData(JORFile* pFile) { + mOutputStream << (u32)JORFile::ECommand_READ + << (u32)JORFile::EStatus_READ_DATA + << (uintptr_t)pFile + << pFile->getHandle(); +} + +void JORMContext::writeBegin(JORFile* pFile, u16 flags, u32 size) { + mOutputStream << (u32)JORFile::ECommand_WRITE + << (u32)JORFile::EStatus_WRITE_BEGIN + << (uintptr_t)pFile + << pFile->getHandle() + << (u32)size + << (u32)flags; +} + +void JORMContext::writeData(JORFile* pFile, const void* pBuffer, s32 size, u32 position) { + mOutputStream << (u32)JORFile::ECommand_WRITE + << (u32)JORFile::EStatus_WRITE_DATA + << (uintptr_t)pFile + << pFile->getHandle() + << (u32)position; + + mOutputStream << (u16)size; + mOutputStream.write(pBuffer, size); +} + +void JORMContext::writeDone(JORFile* pFile, u32 size) { + mOutputStream << (u32)JORFile::ECommand_WRITE + << (u32)JORFile::EStatus_WRITE_END + << (uintptr_t)pFile + << pFile->getHandle() + << (u32)size; +} + +void JORMContext::openMessageBox(void* param_0, u32 style, const char* message, const char* title) { + mOutputStream << (uintptr_t)param_0 << (u32)style << message << title; +} + +void JORMContext::sendHostInfoRequest(u32 requestType, JORHostInfo* pHostInfo) { + mOutputStream << requestType << (uintptr_t)pHostInfo; +} + +void JORMContext::sendShellExecuteRequest(void* param_0, const char* param_1, const char* param_2, + const char* param_3, const char* param_4, int param_5) +{ + mOutputStream << (uintptr_t)param_0 << param_1 << param_2 << param_3 << param_4 << (u32)param_5; +} diff --git a/libs/JSystem/src/JHostIO/JORShellExecute.cpp b/libs/JSystem/src/JHostIO/JORShellExecute.cpp new file mode 100644 index 0000000000..107c978e49 --- /dev/null +++ b/libs/JSystem/src/JHostIO/JORShellExecute.cpp @@ -0,0 +1,18 @@ +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JORServer.h" + +int JORShellExecute(const char* param_0, const char* param_1, const char* param_2, const char* param_3, int param_4) { + int rt = 0; + JORServer* instance = JORServer::getInstance(); + + JORMContext* mctx = instance->attachMCTX(MCTX_MSG_SHELL_EXEC); + mctx->sendShellExecuteRequest(&rt, param_0, param_1, param_2, param_3, param_4); + instance->releaseMCTX(mctx); + + while (rt == 0) { + JOR_MESSAGELOOP(); + } + + return rt; +} |
