diff --git a/configure.py b/configure.py index 5c25c4b61..77ac5c60d 100755 --- a/configure.py +++ b/configure.py @@ -999,6 +999,7 @@ config.libs = [ [ Object(Matching, "JSystem/JSupport/JSUList.cpp"), Object(Matching, "JSystem/JSupport/JSUInputStream.cpp"), + Object(DEBUG_ONLY, "JSystem/JSupport/JSUOutputStream.cpp"), Object(Matching, "JSystem/JSupport/JSUMemoryStream.cpp"), Object(Matching, "JSystem/JSupport/JSUFileStream.cpp"), ], @@ -1107,6 +1108,23 @@ config.libs = [ Object(Matching, "JSystem/JMath/random.cpp"), ], ), + JSystemLib( + "JHostIO", + [ + Object(DEBUG_ONLY, "JSystem/JHostIO/JHIComm.cpp"), + Object(DEBUG_ONLY, "JSystem/JHostIO/JHICommonMem.cpp"), + Object(DEBUG_ONLY, "JSystem/JHostIO/JORServer.cpp"), + Object(DEBUG_ONLY, "JSystem/JHostIO/JOREntry.cpp", extra_cflags=["-sym off"]), + Object(DEBUG_ONLY, "JSystem/JHostIO/JORFile.cpp", extra_cflags=["-sym off"]), + Object(DEBUG_ONLY, "JSystem/JHostIO/JORMessageBox.cpp"), + Object(DEBUG_ONLY, "JSystem/JHostIO/JORHostInfo.cpp", extra_cflags=["-sym off"]), + Object(DEBUG_ONLY, "JSystem/JHostIO/JORShellExecute.cpp"), + Object(DEBUG_ONLY, "JSystem/JHostIO/JHIMemBuf.cpp"), + Object(DEBUG_ONLY, "JSystem/JHostIO/JHIhioASync.cpp", extra_cflags=["-sym off"]), + Object(DEBUG_ONLY, "JSystem/JHostIO/JHIMccBuf.cpp", extra_cflags=["-sym off"]), + Object(DEBUG_ONLY, "JSystem/JHostIO/JHIRMcc.cpp"), + ], + ), DolphinLib( "base", [ @@ -1244,6 +1262,12 @@ config.libs = [ Object(Matching, "dolphin/card/CARDNet.c"), ], ), + DolphinLib( + "hio", + [ + Object(Matching, "dolphin/hio/hio.c"), + ], + ), DolphinLib( "gx", [ @@ -1937,10 +1961,24 @@ def link_order_callback(module_id: int, objects: List[str]) -> List[str]: # objects.insert(objects.index("d/actor/d_a_agb.cpp"), "d/d_debug_camera.cpp") # objects.insert(objects.index("d/actor/d_a_agb.cpp"), "d/d_event_debug.cpp") # objects.insert(objects.index("d/actor/d_a_agb.cpp"), "d/d_kankyo_debug.cpp") + objects.insert(objects.index("JSystem/JSupport/JSUMemoryStream.cpp"), "JSystem/JSupport/JSUOutputStream.cpp") objects.insert(objects.index("JSystem/JGadget/binary.cpp"), "JSystem/JGadget/define.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JHIComm.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JHICommonMem.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JORServer.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JOREntry.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JORFile.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JORMessageBox.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JORHostInfo.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JORShellExecute.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JHIMemBuf.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JHIhioASync.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JHIMccBuf.cpp") + objects.insert(objects.index("dolphin/base/PPCArch.c"), "JSystem/JHostIO/JHIRMcc.cpp") objects.insert(objects.index("dolphin/pad/Padclamp.c"), "dolphin/vi/i2c.c") objects.insert(objects.index("dolphin/pad/Padclamp.c"), "dolphin/vi/initphilips.c") objects.insert(objects.index("dolphin/pad/Padclamp.c"), "dolphin/vi/gpioexi.c") + objects.insert(objects.index("dolphin/gx/GXInit.c"), "dolphin/hio/hio.c") objects.insert(objects.index("dolphin/gx/GXPixel.c"), "dolphin/gx/GXDraw.c") # Example of adding new files for modding: diff --git a/include/JSystem/JHostIO/JHIComm.h b/include/JSystem/JHostIO/JHIComm.h new file mode 100644 index 000000000..bbdf3cb20 --- /dev/null +++ b/include/JSystem/JHostIO/JHIComm.h @@ -0,0 +1,132 @@ +#ifndef JHICOMM_H +#define JHICOMM_H + +#include "JSystem/JHostIO/JHICommonMem.h" + +class JHICommBufHeader { +public: + void init(); + void init(JHICommonMem*, u32, u32, u32); + int load(); + + u32 getMsgBufSize() { return m_msgBufSize; } + + /* 0x00 */ JHICommonMem* mp_memBuffer; + /* 0x04 */ u32 field_0x4; + /* 0x08 */ u32 m_msgBufSize; + /* 0x0C */ u32 field_0xc; + /* 0x10 */ u32 field_0x10; + /* 0x14 */ u32 field_0x14; + /* 0x18 */ u32 field_0x18; + /* 0x1C */ u32 field_0x1c; + /* 0x20 */ u32 field_0x20; + /* 0x24 */ u32 field_0x24; + /* 0x28 */ u32 m_alignment; + /* 0x2C */ u32 field_0x2c; +}; + +class JHICommBufWriter { +public: + struct Header : public JHICommBufHeader { + int load(); + int getRemSize(); + void updatePutAdrs(); + u32 getWritebleSize() const; + void alignPutAdrs(); + void addPutAdrs(int); + u32 getPutAdrs() const; + + /* 0x30 */ u8 field_0x30; + /* 0x31 */ u8 field_0x31; + /* 0x32 */ u8 field_0x32; + /* 0x33 */ u8 field_0x33; + /* 0x34 */ u32 field_0x34; + }; + + JHICommBufWriter(u32, u32, u32 alignment); + int writeBegin(); + void writeEnd(); + int write(void*, int); + + void init() { m_header.init(); } + + /* 0x00 */ Header m_header; + /* 0x38 */ JHIMemBuf* mp_memBuffer; +}; + +class JHICommBufReader { +public: + struct Header : public JHICommBufHeader { + void updateGetAdrs(); + u32 getReadableSize() const; + void addGetAdrs(int); + u32 getGetAdrs() const; + void alignGetAdrs(); + int getContSize(); + + int load() { + int result = JHICommBufHeader::load(); + if (!result) { + field_0x30 = field_0xc; + } + return result; + } + + /* 0x30 */ u32 field_0x30; + }; + + JHICommBufReader(u32, u32, u32 alignment); + int readBegin(); + void readEnd(); + int read(void*, int); + + u32 getMsgBufSize() { return m_header.getMsgBufSize(); } + void init() { m_header.init(); } + + u32 available() { + if (m_header.load()) { + return 0xFFFFFFFF; + } else { + return m_header.getReadableSize(); + } + } + + /* 0x00 */ Header m_header; + /* 0x34 */ JHIMemBuf* mp_memBuffer; +}; + +struct JHICmnMem { + u32 sendBegin() { return mp_writeBuf->writeBegin(); } + int sendCont(const void* param_0, int param_1) { return mp_writeBuf->write((void*)param_0, param_1); } + void sendEnd() { mp_writeBuf->writeEnd(); } + u32 available() { return mp_readBuf->available(); } + u32 getMaxReaderableSize() { return mp_readBuf->getMsgBufSize(); } + + void setBuf(JHICommBufReader* pReader, JHICommBufWriter* pWriter) { + mp_readBuf = pReader; + mp_writeBuf = pWriter; + } + + void initBuffers() { + mp_readBuf->init(); + mp_writeBuf->init(); + } + + int receive(void* param_1, int param_2) { + int result = 0; + result = mp_readBuf->read(param_1, param_2); + mp_readBuf->readEnd(); + return result; + } + + /* 0x0 */ JHICommBufReader* mp_readBuf; + /* 0x4 */ JHICommBufWriter* mp_writeBuf; + /* 0x8 */ u8 field_0x8; +}; + +struct JHIContext { + JHICommBufReader* mp_reader; + JHICommBufWriter* mp_writer; +}; + +#endif /* JHICOMM_H */ diff --git a/include/JSystem/JHostIO/JHICommonMem.h b/include/JSystem/JHostIO/JHICommonMem.h new file mode 100644 index 000000000..d515de4ac --- /dev/null +++ b/include/JSystem/JHostIO/JHICommonMem.h @@ -0,0 +1,83 @@ +#ifndef JHICOMMONMEM_H +#define JHICOMMONMEM_H + +#include "dolphin/types.h" + +inline u32 JHIhtonl(u32 v) { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + return v; +#else + // todo +#endif +} + +inline u32 JHIntohl(u32 v) { + return v; +} + +template class JHIComPortManager; + +template +struct JHITag { + JHITag(u32 tag) { + m_tag = tag; + mp_data = NULL; + } + + s32 send(const void* param_0, s32 param_1) { + u32 sp10[2]; + sp10[0] = JHIhtonl(m_tag); + sp10[1] = JHIhtonl(param_1); + + if (mp_data->port.sendBegin() >= param_1 + 8) { + mp_data->port.sendCont(sp10, 8); + mp_data->port.sendCont(param_0, param_1); + mp_data->port.sendEnd(); + } + + return param_1; + } + + virtual ~JHITag() {} + virtual void receive(const char*, s32) {} + + /* 0x4 */ u32 m_tag; + /* 0x8 */ JHIComPortManager* mp_data; +}; + +class JHIMemBuf; + +class JHICommonMem { +public: + virtual ~JHICommonMem() {} + virtual int create() = 0; + virtual int open() = 0; + virtual void close() = 0; + virtual u8* getPointer() const = 0; + virtual void readIO(u32 position, u32* out_data) const = 0; + virtual u32 readIO(u32 position) const = 0; + virtual void writeIO(u32 position, u32 data) const = 0; + virtual void writeIO(u32 position, u8* src_data, u32 length) const = 0; + + static JHIMemBuf* Instance(); + static JHIMemBuf* instance; +}; + +class JHIMemBuf : public JHICommonMem { +public: + JHIMemBuf(); + + virtual ~JHIMemBuf(); + virtual int create(); + virtual int open(); + virtual void close(); + virtual u8* getPointer() const; + virtual void readIO(u32 position, u32* out_data) const; + virtual u32 readIO(u32 position) const; + virtual void writeIO(u32 position, u32 data) const; + virtual void writeIO(u32 position, u8* src_data, u32 length) const; + + /* 0x4 */ u8* mp_buffer; +}; + +#endif /* JHICOMMONMEM_H */ diff --git a/include/JSystem/JHostIO/JHIMccBuf.h b/include/JSystem/JHostIO/JHIMccBuf.h new file mode 100644 index 000000000..7343b8837 --- /dev/null +++ b/include/JSystem/JHostIO/JHIMccBuf.h @@ -0,0 +1,77 @@ +#ifndef JORMCCBUF_H_H +#define JORMCCBUF_H_H + +#include "JSystem/JHostIO/JHIComm.h" +#include "JSystem/JKernel/JKRHeap.h" + +class JHIMccBuf { +public: + JHIMccBuf(u16 channel, u16, u32); + + void setHeaderToBuf(u32 data, u32 position, u16 size); + u32 setDataToBuf(void* pData, u16 size); + int readData(u32 position, u32* pOutData); + int readDataFromBuf(void* pBuf, u32 size); + + int JHIRead(u32 channel, u32 offset, void* buffer, u32 size); + int JHIWrite(u32 channel, u32 offset, void* buffer, u32 size); + + int JHIMCCWrite(u32 channel, u32 offset, void* buffer, u32 size); + int JHIMCCRead(u32 channel, u32 offset, void* buffer, u32 size); + + virtual ~JHIMccBuf(); + virtual void initInstance(u16 channel, u16, u32); + virtual void init(); + virtual void initBuf(); + virtual void enablePort() { mPortEnabled = true; } + virtual void disablePort() { mPortEnabled = false; } + virtual bool isPort() { return mPortEnabled; } + + static u8* mTempBuf; + static u16 mRefCount; + + /* 0x04 */ u32 mTag; + /* 0x08 */ u16 field_0x8; + /* 0x0A */ u16 field_0xa; + /* 0x0C */ u16 field_0xc; + /* 0x0E */ u16 mChannel; + /* 0x10 */ u16 field_0x10; + /* 0x14 */ int mReadOffset; + /* 0x18 */ int mWriteOffset; + /* 0x1C */ int field_0x1c; + /* 0x20 */ u32 field_0x20; + /* 0x24 */ u32 mBeginPos; + /* 0x28 */ u32 mEndPos; + /* 0x2C */ bool mPortEnabled; +}; + +class JHIMccBufReader : public JHIMccBuf { +public: + JHIMccBufReader(u16 channel, u16, u32); + virtual ~JHIMccBufReader(); + + u32 available(); + int readBegin(); + int read(void* pBuf); + void readEnd(); +}; + +class JHIMccBufWriter : public JHIMccBuf { +public: + JHIMccBufWriter(u16 channel, u16, u32); + virtual ~JHIMccBufWriter(); + + int writeBegin(); + int write(void* pBuf, u32 size); + void writeEnd(); +}; + +struct JHIMccContext { + JHIMccBufReader* mp_reader; + JHIMccBufWriter* mp_writer; +}; + +void JHIReport(const char* fmt, ...); +void JHIHalt(const char* fmt, ...); + +#endif /* JORMCCBUF_H_H */ diff --git a/include/JSystem/JHostIO/JHIRMcc.h b/include/JSystem/JHostIO/JHIRMcc.h new file mode 100644 index 000000000..a16c9a939 --- /dev/null +++ b/include/JSystem/JHostIO/JHIRMcc.h @@ -0,0 +1,16 @@ +#ifndef JHIRMCC_H +#define JHIRMCC_H + +#include "dolphin/types.h" + +struct JHIMccContext; + +BOOL JHIhioCallbackEnum(s32 type); +void JHIEnumDevices(s32*, u32*); +u32 JHIInitInterface(); +bool JHINegotiateInterface(u32); +JHIMccContext JHIGetHiSpeedContext(); +JHIMccContext JHIGetLowSpeedContext(); +BOOL JHIInitMCC(JHIMccContext* pCtx, bool* param_1); + +#endif /* JHIRMCC_H */ diff --git a/include/JSystem/JHostIO/JHIhioASync.h b/include/JSystem/JHostIO/JHIhioASync.h new file mode 100644 index 000000000..82db20712 --- /dev/null +++ b/include/JSystem/JHostIO/JHIhioASync.h @@ -0,0 +1,13 @@ +#ifndef JHIHIOASYNC_H +#define JHIHIOASYNC_H + +#include "dolphin/types.h" + +struct JHIContext; + +BOOL JHIInit(u32 enabled); +u32 JHIEventLoop(); +BOOL JOR_CHECKINTERFACE(); +void JHISetBuffer(JHIContext* pCtx); + +#endif /* JHIHIOASYNC_H */ diff --git a/include/JSystem/JHostIO/JOREntry.h b/include/JSystem/JHostIO/JOREntry.h new file mode 100644 index 000000000..445c5f038 --- /dev/null +++ b/include/JSystem/JHostIO/JOREntry.h @@ -0,0 +1,113 @@ +#ifndef JORENTRY_H +#define JORENTRY_H + +#include "JSystem/JHostIO/JHIComm.h" +#include "dolphin/os/OS.h" + +template +class JHIpvector { +public: + JHIpvector() { m_size = 0; } + + s32 size() const { return m_size; } + T get(u32 i) const { return m_vector[i]; } + + s32 push_back(T p) { + if (m_size >= I) { + return 0; + } + + m_vector[m_size++] = p; + return 1; + } + + /* 0x00 */ T m_vector[I]; + /* 0x28 */ s32 m_size; +}; + +template +class JHIComPortManager { +public: + JHIComPortManager() { + field_0x10040 = 0; + field_0x10041 = 0; + } + + T& getRefPort() { return port; } + + void addTag(JHITag* pTag) { + pTag->mp_data = this; + field_0xc.push_back(pTag); + } + + JHITag* find(u32 param_1) { + for (u32 i = 0; i < field_0xc.size(); i++) { + JHITag* tag = field_0xc.get(i); + if (tag->m_tag == param_1) { + return tag; + } + } + return NULL; + } + + void dispatchMessage() { + u32 r29 = port.available(); + while (true) { + if (!field_0x10040) { + if (r29 < 8) { + return; + } + port.receive(&field_0x10038, 8); + r29 -= 8; + field_0x10038 = JHIntohl(field_0x10038); + field_0x1003c = JHIntohl(field_0x1003c); + field_0x10040 = 1; + JHITag* r27 = find(field_0x10038); + if (field_0x1003c > port.getMaxReaderableSize()) { + port.initBuffers(); + OSReport("JHostIO::ERROR: JHIComportManager: invalid datasize ( port.initialized )\n"); + } else if (!r27) { + OSReport("JHostIO::ERROR: JHIComportManager: invalid tag message\n"); + } + } + if (!field_0x10040) { + continue; + } + + if (r29 < field_0x1003c) { + return; + } + u32 r26 = port.receive(field_0x38, field_0x1003c); + r29 -= r26; + JHITag* r28 = find(field_0x10038); + field_0x10040 = 0; + if (r28) { + r28->receive(field_0x38, field_0x1003c); + } + } + } + + static JHIComPortManager* create() { + if (instance == NULL) { + instance = new JHIComPortManager(); + } + + return instance; + } + + static JHIComPortManager* getInstance() { return instance; } + + static JHIComPortManager* instance; + + /* 0x00000 */ T port; + /* 0x0000C */ JHIpvector*, 10> field_0xc; + /* 0x00038 */ char field_0x38[0x10000]; + /* 0x10038 */ u32 field_0x10038; + /* 0x1003C */ u32 field_0x1003c; + /* 0x10040 */ u8 field_0x10040; + /* 0x10041 */ u8 field_0x10041; +}; + +void JORInit(); + +#endif /* JORENTRY_H */ diff --git a/include/JSystem/JHostIO/JOREvent.h b/include/JSystem/JHostIO/JOREvent.h new file mode 100644 index 000000000..c507d4812 --- /dev/null +++ b/include/JSystem/JHostIO/JOREvent.h @@ -0,0 +1,36 @@ +#ifndef JOREVENT_H +#define JOREVENT_H + +#include "dolphin/types.h" + +class JORReflexible; + +struct JOREvent {}; + +struct JORPropertyEvent : JOREvent { + enum EKind { + EKind_HasListener = (1 << 30), + EKind_ValueID = (1 << 29), + EKind_FloatValue = (1 << 9), + }; + + /* 0x00 */ u8 field_0x0[0x4 - 0x0]; + /* 0x04 */ u32 type; + /* 0x08 */ u32 kind; + /* 0x0C */ char* id; // id? + /* 0x10 */ JORReflexible* field_0x10; // ? + /* 0x14 */ u32 field_0x14; + union { + u32 U32; + u16 U16[2]; + } + /* 0x18 */ field_0x18; +}; + +struct JORGenEvent : JOREvent {}; + +struct JORNodeEvent : JOREvent { + /* 0x00 */ u32 field_0x0; +}; + +#endif /* JOREVENT_H */ diff --git a/include/JSystem/JHostIO/JORFile.h b/include/JSystem/JHostIO/JORFile.h new file mode 100644 index 000000000..e2123d8f4 --- /dev/null +++ b/include/JSystem/JHostIO/JORFile.h @@ -0,0 +1,99 @@ +#ifndef JORFILE_H +#define JORFILE_H + +#include "JSystem/JSupport/JSUMemoryStream.h" + +class JORDir { +public: + void setStatus(u32 status) { m_status = status; } + void setFindHandle(u32 handle) { m_findHandle = handle; } + void setFileAttribute(u32 attribute) { m_fileAttribute = attribute; } + void setLowDateTime(u32 time) { m_lowDateTime = time; } + void setHighDateTime(u32 time) { m_highDateTime = time; } + + char* getFilename() { return m_filename; } + + /* 0x00 */ u32 m_status; + /* 0x04 */ u32 m_findHandle; + /* 0x08 */ u32 m_fileAttribute; + /* 0x0C */ u32 m_lowDateTime; + /* 0x10 */ u32 m_highDateTime; + /* 0x14 */ char m_filename[]; +}; + +class JORFile { +public: + enum ECommand { + ECommand_OPEN, + ECommand_CLOSE, + ECommand_READ, + ECommand_WRITE, + }; + + enum EStatus { + EStatus_WAIT, + EStatus_READ_BEGIN, + EStatus_READ_DATA, + EStatus_READ_END, + EStatus_WRITE_BEGIN, + EStatus_WRITE_DATA, + EStatus_WRITE_END, + }; + + enum EFlags { + EFlags_READ = (1 << 0), + EFlags_WRITE = (1 << 1), + EFlags_UNK_0x4 = (1 << 2), + EFlags_DEFAULT_EXT = (1 << 4), + EFlags_UNK_0x20 = (1 << 5), + EFlags_HAS_SUFFIX = (1 << 6), + }; + + JORFile(); + + int countMaskSize(const char* mask); + void setBuffer(void* buffer, s32 length); + + char* getFilename() { return mFilename; } + u32 getHandle() const { return mHandle; } + + JSUMemoryOutputStream& getDataStream() { return mDataStream; } + + void setHandle(u32 handle) { mHandle = handle; } + void setFileLength(s32 length) { mFileLength = length; } + void setNFileName(u16 length) { mNFileName = length; } + void setNBaseName(u16 length) { mNBaseName = length; } + void setNExtensionName(u16 length) { mNExtensionName = length; } + void setStatus(s32 status) { mStatus = status; } + + virtual ~JORFile() { + close(); + } + virtual int open(const char* path, u32 flags, const char* extMask, const char* defaultExt, const char* param_4, const char* fileSuffix); + virtual int open(u32 flags, const char* extMask, const char* defaultExt, const char* param_4, const char* fileSuffix) { + return open(NULL, flags, extMask, defaultExt, param_4, fileSuffix); + } + virtual void close(); + virtual s32 readData(void* buffer, s32 length); + virtual s32 writeData(const void* buffer, s32 length); + virtual void readBegin_(s32 len); + virtual void readLoop_(); + virtual void writeBegin_(s32 len); + virtual void writeLoop_(const void* pBuffer, s32 size, u32 pos); + virtual void writeDone_(s32 len); + virtual void waitMessage_(); + virtual s32 getFileSize() const { return mFileLength; } + + /* 0x04 */ u32 mHandle; + /* 0x08 */ s32 mFileLength; + /* 0x0C */ s32 mStatus; + /* 0x10 */ u16 mNFileName; + /* 0x12 */ u16 mNBaseName; + /* 0x14 */ u16 mNExtensionName; + /* 0x16 */ u16 mFlags; + /* 0x18 */ int field_0x18; + /* 0x1C */ JSUMemoryOutputStream mDataStream; + /* 0x30 */ char mFilename[256]; +}; + +#endif /* JORFILE_H */ diff --git a/include/JSystem/JHostIO/JORHostInfo.h b/include/JSystem/JHostIO/JORHostInfo.h new file mode 100644 index 000000000..af93d996d --- /dev/null +++ b/include/JSystem/JHostIO/JORHostInfo.h @@ -0,0 +1,53 @@ +#ifndef JORHOSTINFO_H +#define JORHOSTINFO_H + +#include "dolphin/os/OSTime.h" +#include "dolphin/types.h" + +#define HOSTINFO_REQ_COMPUTER_NAME 0 +#define HOSTINFO_REQ_USERNAME 1 +#define HOSTINFO_REQ_LOCAL_TIME 2 + +class JORHostInfo { +public: + /* 0x0 */ s32 m_result; + + void setResult(s32 result) { m_result = result; } + s32 getResult() { return m_result; } + + JORHostInfo() { m_result = 0; } + virtual ~JORHostInfo() {} +}; + +class JORHostInfo_String : public JORHostInfo { +public: + virtual ~JORHostInfo_String() {} + + JORHostInfo_String() { + m_stringBuffer = NULL; + m_bufferSize = 0; + } + + void setStringBuffer(char* buffer) { m_stringBuffer = buffer; } + void setBufferSize(u32 size) { m_bufferSize = size; } + char* getString() { return m_stringBuffer; } + u32 getBufferSize() { return m_bufferSize; } + + /* 0x8 */ char* m_stringBuffer; + /* 0xC */ u32 m_bufferSize; +}; + +class JORHostInfo_CalendarTime : public JORHostInfo { +public: + JORHostInfo_CalendarTime() { m_calendarTimeBuffer = NULL; } + virtual ~JORHostInfo_CalendarTime() {} + + void setCalendarTimeBuffer(OSCalendarTime* pCalendarTime) { m_calendarTimeBuffer = pCalendarTime; } + OSCalendarTime* getCalendarTime() { return m_calendarTimeBuffer; } + + /* 0x8 */ OSCalendarTime* m_calendarTimeBuffer; +}; + +BOOL JORGetYearDays(int year, int mon); + +#endif /* JORHOSTINFO_H */ diff --git a/include/JSystem/JHostIO/JORMContext.h b/include/JSystem/JHostIO/JORMContext.h new file mode 100644 index 000000000..63706f665 --- /dev/null +++ b/include/JSystem/JHostIO/JORMContext.h @@ -0,0 +1,331 @@ +#ifndef JORMCONTEXT_H +#define JORMCONTEXT_H + +#include +#include "JSystem/JHostIO/JOREvent.h" +#include "JSystem/JSupport/JSUMemoryStream.h" +#include "dolphin/os/OS.h" + +#define MCTX_MSG_RESET 0 +#define MCTX_MSG_GET_ROOT_OBJ 2 +#define MCTX_MSG_GEN_OBJ_INFO 4 +#define MCTX_MSG_INVALID_NODE 5 +#define MCTX_MSG_UPDATE_NODE 8 +#define MCTX_MSG_FIO 9 +#define MCTX_MSG_OPEN_MESSAGE_BOX 10 +#define MCTX_MSG_START_NODE 12 +#define MCTX_MSG_GET_HOST_INFO 14 +#define MCTX_MSG_SHELL_EXEC 15 + +#define MCTX_COMMAND_START_NODE (u32)0 +#define MCTX_COMMAND_END_NODE (u32)1 +#define MCTX_COMMAND_GEN_CONTROL (u32)2 +#define MCTX_COMMAND_GEN_NODE (u32)3 +#define MCTX_COMMAND_START_SELECTOR (u32)4 +#define MCTX_COMMAND_END_SELECTOR (u32)5 +#define MCTX_COMMAND_SELECTOR_ITEM (u32)6 +#define MCTX_COMMAND_INVALID_NODE (u32)7 +#define MCTX_COMMAND_UPDATE_CONTROL (u32)8 + +#define JORM_DEFAULT_WIDTH 0x200 +#define JORM_DEFAULT_HEIGHT 0x18 +#define JORM_DEFAULT_COMBOBOX_WIDTH 0x100 +#define JORM_DEFAULT_COMBOBOX_HEIGHT 0x1a + +#define DEFINE_GEN_CHECKBOX(T, kind) \ + void genCheckBox(const char* label, T* pSrc, T mask, u32 style = 0, \ + JOREventListener* pListener = NULL, u16 posX = -1, u16 posY = -1, \ + u16 width = JORM_DEFAULT_WIDTH, u16 height = JORM_DEFAULT_HEIGHT) { \ + genCheckBoxSub(kind, label, (uintptr_t)pSrc, style, *pSrc, mask, pListener, posX, posY, \ + width, height); \ + } + +#define DEFINE_GEN_CHECKBOX_ID(T, kind) \ + void genCheckBoxID(const char* label, u32 id, T mask, T initValue, u32 style = 0, \ + JOREventListener* pListener = NULL, u16 posX = -1, u16 posY = -1, \ + u16 width = JORM_DEFAULT_WIDTH, u16 height = JORM_DEFAULT_HEIGHT) { \ + genCheckBoxSub(kind, label, id, style, initValue, mask, pListener, posX, posY, width, \ + height); \ + } + +#define DEFINE_GEN_SLIDER(T, kind) \ + void genSlider(const char* label, T* pSrc, T rangeMin, T rangeMax, u32 style = 0, \ + JOREventListener* pListener = NULL, u16 posX = -1, u16 posY = -1, \ + u16 width = JORM_DEFAULT_WIDTH, u16 height = JORM_DEFAULT_HEIGHT) { \ + genSliderSub(kind, label, (uintptr_t)pSrc, style, *pSrc, rangeMin, rangeMax, pListener, \ + posX, posY, width, height); \ + } + +#define DEFINE_GEN_SLIDER_ID(T, kind) \ + void genSliderID(const char* label, u32 id, T data, T rangeMin, T rangeMax, u32 style = 0, \ + JOREventListener* pListener = NULL, u16 posX = -1, u16 posY = -1, \ + u16 width = JORM_DEFAULT_WIDTH, u16 height = JORM_DEFAULT_HEIGHT) { \ + genSliderSub(kind, label, id, style, data, rangeMin, rangeMax, pListener, posX, posY, \ + width, height); \ + } + +#define DEFINE_START_COMBO_BOX(T, kind) \ + void startComboBox(const char* label, T* pSrc, u32 style = 0, \ + JOREventListener* pListener = NULL, u16 posX = -1, u16 posY = -1, \ + u16 width = JORM_DEFAULT_COMBOBOX_WIDTH, \ + u16 height = JORM_DEFAULT_COMBOBOX_HEIGHT) { \ + startSelectorSub('CMBX', kind, label, (uintptr_t)pSrc, style, *pSrc, pListener, posX, \ + posY, width, height); \ + } + +#define DEFINE_START_COMBO_BOX_ID(T, kind) \ + void startComboBoxID(const char* label, u32 id, T data, u32 style = 0, \ + JOREventListener* pListener = NULL, u16 posX = -1, u16 posY = -1, \ + u16 width = JORM_DEFAULT_WIDTH, u16 height = JORM_DEFAULT_HEIGHT) { \ + startSelectorSub('CMBX', kind, label, id, style, data, pListener, posX, posY, width, \ + height); \ + } + +#define DEFINE_UPDATE_COMBO_BOX(T) \ + void updateComboBox(u32 mode, T* pSrc, u32 param_2) { \ + updateSelectorSub(mode, (uintptr_t)pSrc, *pSrc, param_2); \ + } + +#define DEFINE_UPDATE_COMBO_BOX_ID(T) \ + void updateComboBoxID(u32 mode, u32 id, T value, u32 param_4) { \ + updateSelectorSub(mode, id, value, param_4); \ + } + +#define DEFINE_UPDATE_SLIDER(T) \ + void updateSlider(u32 mode, T* pSrc, T rangeMin, T rangeMax, u32 param_5) { \ + updateSliderSub(mode, (uintptr_t)pSrc, *pSrc, rangeMin, rangeMax, param_5); \ + } + +#define DEFINE_UPDATE_SLIDER_ID(T) \ + void updateSliderID(u32 mode, u32 id, T value, T rangeMin, T rangeMax, u32 param_5) { \ + updateSliderSub(mode, id, value, rangeMin, rangeMax, param_5); \ + } + +#define DEFINE_START_RADIO_BUTTON(T, kind) \ + void startRadioButton(const char* label, T* pSrc, u32 style, JOREventListener* pListener, \ + u16 posX, u16 posY, u16 width, u16 height) { \ + startSelectorSub('RBTN', kind, label, (uintptr_t)pSrc, style, *pSrc, pListener, posX, \ + posY, width, height); \ + } + +namespace jhostio { +enum EKind { + EKind_8B = 0x08, + EKind_16B = 0x10, + EKind_32B = 0x20, +}; + +inline u32 GetEKindSize(u32 param_0) { + return param_0 & 0xFF; +} +} // namespace jhostio + +class JORReflexible; +class JORFile; +class JOREventListener; +class JORHostInfo; + +class JORMContext { +public: + JORMContext() : mOutputStream(this, 0x10000) {} + + void bufInit() { mOutputStream.seek(0, JSUStreamSeekFrom_SET); } + void putMsgID(u32 msgID) { mOutputStream << msgID; } + s32 msgSize() { return mOutputStream.getPosition(); } + u8* msgPtr() { return mBuffer; } + + void openFile(JORFile* pFile, u32 flags, const char* path, const char* extMask, u32 maskSize, + const char* defaultExt, const char* param_6, const char* fileSuffix); + void closeFile(JORFile* pFile); + void readBegin(JORFile* pFile, s32 size); + void readData(JORFile* pFile); + void writeBegin(JORFile* pFile, u16 flags, u32 size); + void writeData(JORFile* pFile, const void* pBuffer, s32 size, u32 position); + void writeDone(JORFile* pFile, u32 size); + void sendShellExecuteRequest(void*, const char*, const char*, const char*, const char*, int); + void sendHostInfoRequest(u32 requestType, JORHostInfo* pHostInfo); + void endNode(); + + void genRootNode(const char* label, JORReflexible* obj, u32 param_2, u32 param_3) { + genNodeSub(label, obj, param_2, param_3); + } + + void genNode(const char* label, JORReflexible* obj, u32 param_2, u32 param_3) { + mOutputStream << MCTX_COMMAND_GEN_NODE; + genNodeSub(label, obj, param_2, param_3); + } + + void genNode(JORReflexible* parentObj, u32 param_1, const char* label, JORReflexible* obj, + u32 param_4, u32 param_5) { + ASSERTMSGLINE(97, parentObj != NULL, + "JORMContext: genNode must specify strict( not null node ) parent object\n"); + + mOutputStream << MCTX_COMMAND_GEN_NODE; + mOutputStream << param_1; + putNode(parentObj); + genNodeSub(label, obj, param_4, param_5); + } + + void startNode(JORReflexible* parentObj, u32 param_1, const char* label, JORReflexible* obj, + u32 param_4, u32 param_5) { + ASSERTMSGLINE( + 113, parentObj != NULL, + "JORMContext: startNode must specify strict( not null node ) parent object\n"); + + mOutputStream << MCTX_COMMAND_START_NODE; + mOutputStream << param_1; + putNode(parentObj); + genNodeSub(label, obj, param_4, param_5); + } + + void startNode(const char* label, JORReflexible* obj, u32 param_2, u32 param_3) { + mOutputStream << MCTX_COMMAND_START_NODE; + genNodeSub(label, obj, param_2, param_3); + } + + void endUpdateNode() { + // empty function + } + + void startUpdateNode(JORReflexible* obj) { putNode(obj); } + + void genNodeSub(const char* label, JORReflexible* i_node, u32, u32); + void putNode(JORReflexible* obj) { mOutputStream << (uintptr_t)obj; } + void invalidNode(JORReflexible* i_node, u32); + + void genControl(u32 type, u32 kind, const char* label, u32 style, u32 id, + JOREventListener* pListener, u32 initValue); + + void 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); + + void genCheckBoxSub(u32 kind, const char* label, u32 id, u32 style, u16 initValue, u16 mask, + JOREventListener* pListener, u16 posX, u16 posY, u16 width, u16 height); + + void startSelectorSub(u32 type, u32 kind, const char* label, u32 id, u32 style, s32 initValue, + JOREventListener* pListener, u16 posX, u16 posY, u16 width, u16 height); + + void endSelectorSub(); + + void genSelectorItemSub(const char* label, s32 itemNo, u32 param_2, u16 posX, u16 posY, + u16 width, u16 height); + + void genButton(const char* label, u32 id, u32 style = 0, JOREventListener* pListener = NULL, + u16 posX = -1, u16 posY = -1, u16 width = JORM_DEFAULT_WIDTH, + u16 height = JORM_DEFAULT_HEIGHT); + + void updateButton(u32 param_1, u32 param_2, u32 param_3) { + updateControl(param_1, param_2, param_3); + } + + void genLabel(const char* label, u32 id, u32 style = 0, JOREventListener* pListener = NULL, + u16 posX = -1, u16 posY = -1, u16 width = JORM_DEFAULT_WIDTH, + u16 height = JORM_DEFAULT_HEIGHT); + + void genGroupBox(const char* label, u32 id, u32 style = 0, JOREventListener* pListener = NULL, + u16 posX = -1, u16 posY = -1, u16 width = JORM_DEFAULT_WIDTH, + u16 height = JORM_DEFAULT_HEIGHT); + + void genEditBoxID(const char* label, u32 id, const char* string, u16 length, u32 style = 0, + JOREventListener* pListener = NULL, u16 posX = -1, u16 posY = -1, + u16 width = JORM_DEFAULT_WIDTH, u16 height = JORM_DEFAULT_HEIGHT); + + /** + * === CHECKBOX === + */ + DEFINE_GEN_CHECKBOX(u8, 0x100 | jhostio::EKind_8B) + DEFINE_GEN_CHECKBOX(u16, 0x100 | jhostio::EKind_16B) + + DEFINE_GEN_CHECKBOX_ID(u16, JORPropertyEvent::EKind_ValueID | 0x100) + + /** + * === SLIDER === + */ + DEFINE_GEN_SLIDER(u8, 0x100 | jhostio::EKind_8B) + DEFINE_GEN_SLIDER(s16, jhostio::EKind_16B) + DEFINE_GEN_SLIDER(f32, JORPropertyEvent::EKind_FloatValue | jhostio::EKind_32B) + DEFINE_GEN_SLIDER(s32, jhostio::EKind_32B) + + DEFINE_GEN_SLIDER_ID(f64, JORPropertyEvent::EKind_ValueID | JORPropertyEvent::EKind_FloatValue) + DEFINE_GEN_SLIDER_ID(int, JORPropertyEvent::EKind_ValueID) + + DEFINE_UPDATE_SLIDER(u8) + DEFINE_UPDATE_SLIDER(s16) + DEFINE_UPDATE_SLIDER(f32) + DEFINE_UPDATE_SLIDER(s32) + + DEFINE_UPDATE_SLIDER_ID(f64) + DEFINE_UPDATE_SLIDER_ID(int) + + /** + * === COMBO BOX === + */ + DEFINE_START_COMBO_BOX(u8, 0x100 | jhostio::EKind_8B) + DEFINE_START_COMBO_BOX(s16, jhostio::EKind_16B) + DEFINE_START_COMBO_BOX(s32, jhostio::EKind_32B) + + DEFINE_START_COMBO_BOX_ID(s32, JORPropertyEvent::EKind_ValueID) + + DEFINE_UPDATE_COMBO_BOX(u8) + DEFINE_UPDATE_COMBO_BOX(s32) + + DEFINE_UPDATE_COMBO_BOX_ID(s32) + + void endComboBox() { endSelectorSub(); } + + void genComboBoxItem(const char* label, s32 itemNo) { + genSelectorItemSub(label, itemNo, 0, 0, 0, 0, 0); + } + + void editComboBoxItem(u32 param_0, u32 param_1, const char* param_2, s32 param_3, u32 param_4); + + void addComboBoxItem(u32 param_1, s32* param_2, const char* param_3, s32 param_4, u32 param_5) { + editComboBoxItem(param_1, (uintptr_t)param_2, param_3, param_4, param_5); + } + + void removeComboBoxItem(u32 param_1, s32* param_2, u32 param_3) { + editComboBoxItem(param_1, (uintptr_t)param_2, NULL, 0, param_3); + } + + /** + * === RADIO BUTTON === + */ + DEFINE_START_RADIO_BUTTON(u8, 0x100 | jhostio::EKind_8B) + DEFINE_START_RADIO_BUTTON(s16, jhostio::EKind_16B) + DEFINE_START_RADIO_BUTTON(s32, jhostio::EKind_32B) + + void endRadioButton() { endSelectorSub(); } + + void genRadioButtonItem(const char* label, s32 itemNo, u32 param_2, u16 posX, u16 posY, + u16 width, u16 height) { + genSelectorItemSub(label, itemNo, param_2, posX, posY, width, height); + } + + void updateControl(u32 mode, u32 id, u32 param_2); + void updateControl(u32 mode, u32 id, const char* param_2); + void updateLabel(u32 mode, u32 id, const char* param_2) { updateControl(mode, id, param_2); } + void updateSliderSub(u32 mode, u32 id, s32 value, s32 rangeMin, s32 rangeMax, u32 param_5); + void updateCheckBoxSub(u32 mode, u32 id, u16 value, u16 mask, u32 param_4); + void updateSelectorSub(u32 mode, u32 id, s32 value, u32 param_3); + void updateEditBoxID(u32 mode, u32 id, const char* string, u32 param_3, u16 length); + + void updateCheckBox(u32 mode, u8* pSrc, u8 mask, u32 param_4) { + updateCheckBoxSub(mode, (uintptr_t)pSrc, *pSrc, mask, param_4); + } + + void updateCheckBoxID(u32 mode, u32 id, u8 value, u8 mask, u32 param_4) { + updateCheckBoxSub(mode, id, value, mask, param_4); + } + + void updateRadioButton(u32 mode, s16* pSrc, u32 param_3) { + updateSelectorSub(mode, (uintptr_t)pSrc, *pSrc, param_3); + } + + void openMessageBox(void* param_0, u32 style, const char* message, const char* title); + + /* 0x00000 */ u8 mBuffer[0x10000]; + /* 0x10000 */ JSUMemoryOutputStream mOutputStream; +}; + +#endif /* JORMCONTEXT_H */ diff --git a/include/JSystem/JHostIO/JORReflexible.h b/include/JSystem/JHostIO/JORReflexible.h new file mode 100644 index 000000000..30c45c07f --- /dev/null +++ b/include/JSystem/JHostIO/JORReflexible.h @@ -0,0 +1,37 @@ +#ifndef JORREFLEXIBLE_H +#define JORREFLEXIBLE_H + +#include "dolphin/types.h" +#include "JSystem/JHostIO/JORServer.h" + +struct JOREvent; +struct JORPropertyEvent; +struct JORGenEvent; +struct JORNodeEvent; + +class JORMContext; +class JORServer; + +class JOREventListener { +public: +#if DEBUG + JOREventListener() {} + virtual void listenPropertyEvent(const JORPropertyEvent*) = 0; +#endif +}; + +class JORReflexible : public JOREventListener { +public: +#if DEBUG + JORReflexible() {} + static JORServer* getJORServer() { return JORServer::getInstance(); } + + virtual void listenPropertyEvent(const JORPropertyEvent*); + virtual void listen(u32, const JOREvent*); + virtual void genObjectInfo(const JORGenEvent*); + virtual void genMessage(JORMContext*) = 0; + virtual void listenNodeEvent(const JORNodeEvent*); +#endif +}; + +#endif /* JORREFLEXIBLE_H */ diff --git a/include/JSystem/JHostIO/JORServer.h b/include/JSystem/JHostIO/JORServer.h new file mode 100644 index 000000000..2c2ebf72d --- /dev/null +++ b/include/JSystem/JHostIO/JORServer.h @@ -0,0 +1,195 @@ +#ifndef JORSERVER_H +#define JORSERVER_H + +#include "JSystem/JHostIO/JOREntry.h" +#include "JSystem/JHostIO/JORMContext.h" +#include "JSystem/JHostIO/JHIComm.h" +#include "JSystem/JHostIO/JHIhioASync.h" +#include "JSystem/JGadget/linklist.h" +#include "JSystem/JUtility/JUTAssert.h" + +u32 JORMessageBox(const char* message, const char* title, u32 style); +int JORShellExecute(const char* param_0, const char* param_1, const char* param_2, const char* param_3, int param_4); + +struct JOREventCallbackListNode { + JOREventCallbackListNode(u32, u32, bool); + void JORAppend(); + void JORRemove(); + + virtual int JORAct(u32, const char*); + virtual ~JOREventCallbackListNode(); + + bool JORIsAcceptableID(u32 eventID) const { + bool result = false; + if (field_0xc <= eventID && eventID <= field_0x10) { + result = true; + } + return result; + } + + /* 0x04 */ JGadget::TLinkListNode m_node; + /* 0x0C */ u32 field_0xc; + /* 0x10 */ u32 field_0x10; +}; + +class JORFile; +class JORDir; +class JORHostInfo_String; +class JORHostInfo_CalendarTime; + +class JORServer : public JHITag { +public: + typedef void (*EventFunc)(u32,char *); + typedef JGadget::TLinkList CallbackLinkList; + + enum ECommand { + ECommand_GetRootObj = 1, + ECommand_GenObjInfo = 3, + ECommand_NodeEvent = 6, + ECommand_PropertyEvent = 7, + ECommand_FIO = 9, + ECommand_ReadResultS32 = 10, + ECommand_ReadOrEvent = 11, + ECommand_DIR = 13, + ECommand_HostInfo = 14, + ECommand_ReadResultU32 = 15, + }; + + JORServer() : JHITag('ORef'), + m_event(false), + m_eventDone(true), + m_eventFunc(NULL), + m_isEventCallbackListEnabled(false) + {} + + static JORServer* create(); + void receive(const char*, s32); + + JORMContext* attachMCTX(u32); + void releaseMCTX(JORMContext*); + + void appendEventCallbackListNode(JOREventCallbackListNode* p) { + JUT_ASSERT(256, p!=NULL); + m_eventCallbackList.Push_front(p); + } + + void removeEventCallbackListNode(JOREventCallbackListNode* p) { + JUT_ASSERT(257, p!=NULL); + m_eventCallbackList.Remove(p); + } + + static void defSetVal(void*, u32, s32); + static void defSetBitVal(void*, u32, u16, u16); + + void fio_openFile_(JSUMemoryInputStream&); + void fio_closeFile_(JSUMemoryInputStream&); + void fio_readData_(JSUMemoryInputStream&); + void fio_writeData_(JSUMemoryInputStream&); + void fio_dispatchMessage_(JSUMemoryInputStream&); + + void dir_findFirstFile_(JSUMemoryInputStream&, JORDir*); + void dir_findNextFile_(JSUMemoryInputStream&, JORDir*); + void dir_browseForFolder_(JSUMemoryInputStream&, JORDir*); + + void readResultS32_(JSUMemoryInputStream&); + void readOrEvent_(JSUMemoryInputStream&); + void dir_dispatchMessage_(JSUMemoryInputStream&); + void hostinfo_dispatchMessage_(JSUMemoryInputStream&); + void hostinfo_recvString_(JSUMemoryInputStream&, JORHostInfo_String*); + void hostinfo_localTime_(JSUMemoryInputStream&, JORHostInfo_CalendarTime*); + void readResultU32_(JSUMemoryInputStream&); + + void sendReset(); + + void setRootNode(const char*, JORReflexible*, u32, u32); + void doneEvent(); + + bool getEvent() { return m_event; } + void setEvent(bool event) { m_event = event; } + void setEventDone(bool eventDone) { m_eventDone = eventDone; } + u32 getEventNum() { return m_eventNum; } + char* getEventName() { return m_eventName; } + EventFunc getEventFunc() { return m_eventFunc; } + void setEventFunc(EventFunc func) { m_eventFunc = func; } + bool isEventCallbackListEnabled() const { return m_isEventCallbackListEnabled; } + void enableEventCallbackList(bool enable) { m_isEventCallbackListEnabled = enable; } + CallbackLinkList* referEventCallbackList() { return &m_eventCallbackList; } + + static JORServer* getInstance() { return instance; } + static JORServer* instance; + + /* 0x0000C */ JORMContext m_context; + /* 0x10020 */ JORReflexible* mp_rootObj; + /* 0x10024 */ char m_rootName[64]; + /* 0x10064 */ u32 field_0x10064; + /* 0x10068 */ u32 field_0x10068; + /* 0x1006C */ bool m_event; + /* 0x1006D */ bool m_eventDone; + /* 0x10070 */ u32 m_eventNum; + /* 0x10074 */ char m_eventName[0x1000]; + /* 0x11074 */ EventFunc m_eventFunc; + /* 0x11078 */ bool m_isEventCallbackListEnabled; + /* 0x1107C */ CallbackLinkList m_eventCallbackList; +}; + +inline u32 JOR_MESSAGELOOP() { + JORServer* server = JORServer::getInstance(); + JHIComPortManager::getInstance()->dispatchMessage(); + if (server->getEvent()) { + server->setEvent(false); + server->setEventDone(false); + u32 eventNum = server->getEventNum(); + char* eventName = server->getEventName(); + if (server->isEventCallbackListEnabled() && eventNum >= 0x80000000) { + JORServer::CallbackLinkList* list = server->referEventCallbackList(); + JORServer::CallbackLinkList::iterator end = list->end(); + for (JORServer::CallbackLinkList::iterator it = list->begin(); it != end;) { + JOREventCallbackListNode& callback = *it; + ++it; + if (!callback.JORIsAcceptableID(eventNum)) { + continue; + } + if (callback.JORAct(eventNum, eventName)) { + break; + } + } + } else { + JORServer::EventFunc func = server->getEventFunc(); + if (func) { + func(eventNum, eventName); + } + } + server->doneEvent(); + } + return JHIEventLoop(); +} + +inline void JOR_INIT() { + JORInit(); + JORServer::getInstance()->setEventFunc(NULL); +} +inline void JOR_SETROOTNODE(const char* name, JORReflexible* node, u32 param_3, u32 param_4) { + JORServer::getInstance()->setRootNode(name, node, param_3, param_4); +} + +inline JORMContext* attachJORMContext(u32 msgID) { + return JORServer::getInstance()->attachMCTX(msgID); +} + +inline JORMContext* JORAttachMContext(u32 msgID) { + return JORServer::getInstance()->attachMCTX(msgID); +} + +inline void releaseJORMContext(JORMContext* mctx) { + JORServer::getInstance()->releaseMCTX(mctx); +} + +inline void JORReleaseMContext(JORMContext* mctx) { + JORServer::getInstance()->releaseMCTX(mctx); +} + +inline void JOR_ENABLEEVENTCALLBACKLIST(bool enable) { + JORServer::getInstance()->enableEventCallbackList(enable); +} + +#endif /* JORSERVER_H */ diff --git a/include/JSystem/JSupport/JSUInputStream.h b/include/JSystem/JSupport/JSUInputStream.h index ac36bac18..46cf4cc4f 100644 --- a/include/JSystem/JSupport/JSUInputStream.h +++ b/include/JSystem/JSupport/JSUInputStream.h @@ -3,12 +3,6 @@ #include "JSystem/JSupport/JSUIosBase.h" -enum JSUStreamSeekFrom { - JSUStreamSeekFrom_SET = 0, // absolute - JSUStreamSeekFrom_CUR = 1, // relative - JSUStreamSeekFrom_END = 2, // relative to end -}; - class JSUInputStream : public JSUIosBase { public: JSUInputStream() {} @@ -66,8 +60,40 @@ public: return val; } + JSUInputStream& operator>>(u32& dest) { + read(&dest, 4); + return *this; + } + + JSUInputStream& operator>>(u16& dest) { + read(&dest, 2); + return *this; + } + + JSUInputStream& operator>>(u8& dest) { + read(&dest, 1); + return *this; + } + + JSUInputStream& operator>>(s16& dest) { + read(&dest, 2); + return *this; + } + + JSUInputStream& operator>>(char* dest) { + read(dest); + return *this; + } + + s32 read(bool& val) { return read(&val, sizeof(bool)); } + + s32 read(u8& val) { return read(&val, sizeof(u8)); } + + s32 read(u32& param_0) { return read(¶m_0, 4); } + // TODO: return value probably wrong s32 read(void*, s32); + char* read(char*); }; // Size = 0x8 // move? diff --git a/include/JSystem/JSupport/JSUIosBase.h b/include/JSystem/JSupport/JSUIosBase.h index c44a81e2f..6ebcbe8c2 100644 --- a/include/JSystem/JSupport/JSUIosBase.h +++ b/include/JSystem/JSupport/JSUIosBase.h @@ -3,12 +3,19 @@ #include "dolphin/types.h" -enum EIoState { - IOS_STATE_1 = 1, +enum JSUStreamSeekFrom { + JSUStreamSeekFrom_SET = 0, // absolute + JSUStreamSeekFrom_CUR = 1, // relative + JSUStreamSeekFrom_END = 2, // relative to end }; class JSUIosBase { public: + enum EIoState { + IOS_STATE_1 = 1, + IOS_STATE_2 = 2, + }; + JSUIosBase() { mState = false; } virtual ~JSUIosBase() {} @@ -18,7 +25,7 @@ public: void setState(EIoState state) { mState |= state; } private: - u8 mState; + bool mState; }; // Size = 0x8 #endif diff --git a/include/JSystem/JSupport/JSUMemoryStream.h b/include/JSystem/JSupport/JSUMemoryStream.h index de5135ed4..6d6e37ac7 100644 --- a/include/JSystem/JSupport/JSUMemoryStream.h +++ b/include/JSystem/JSupport/JSUMemoryStream.h @@ -2,10 +2,11 @@ #define JSUMEMORYSTREAM_H #include "JSystem/JSupport/JSURandomInputStream.h" +#include "JSystem/JSupport/JSURandomOutputStream.h" class JSUMemoryInputStream : public JSURandomInputStream { public: - JSUMemoryInputStream(const void* res, u32 size) { setBuffer(res, size); } + JSUMemoryInputStream(const void* res, s32 size) { setBuffer(res, size); } virtual ~JSUMemoryInputStream() {} void setBuffer(void const*, s32); @@ -14,10 +15,31 @@ public: s32 getLength() const; s32 getPosition() const; + void* getPointer() const { return (u8*)mBuffer + mPosition; } + private: /* 0x08 */ const void* mBuffer; /* 0x0C */ s32 mLength; /* 0x10 */ s32 mPosition; }; // Size = 0x14 +class JSUMemoryOutputStream : public JSURandomOutputStream { +public: + JSUMemoryOutputStream() { setBuffer(NULL, 0); } + JSUMemoryOutputStream(void* buffer, s32 len) { setBuffer(buffer, len); } + + void setBuffer(void* buffer, s32 len); + + virtual ~JSUMemoryOutputStream() {} + virtual s32 writeData(const void*, s32); + virtual s32 getLength() const; + virtual s32 getPosition() const { return mPosition; } + virtual s32 seekPos(s32, JSUStreamSeekFrom); + +private: + /* 0x08 */ void* mBuffer; + /* 0x0C */ s32 mLength; + /* 0x10 */ s32 mPosition; +}; // Size = 0x14 + #endif /* JSUMEMORYSTREAM_H */ diff --git a/include/JSystem/JSupport/JSUOutputStream.h b/include/JSystem/JSupport/JSUOutputStream.h new file mode 100644 index 000000000..9d43692e3 --- /dev/null +++ b/include/JSystem/JSupport/JSUOutputStream.h @@ -0,0 +1,42 @@ +#ifndef JSUOUTPUTSTREAM_H +#define JSUOUTPUTSTREAM_H + +#include "JSystem/JSupport/JSUIosBase.h" + +class JSUOutputStream : public JSUIosBase { +public: + JSUOutputStream() {} + virtual ~JSUOutputStream(); + + virtual s32 skip(s32, s8); + virtual s32 writeData(const void*, s32) = 0; + + s32 write(const void*, s32); + void write(const char*); + +#define JSU_OUTPUTSTREAM_OPERATOR(T) \ + JSUOutputStream& operator<<(T val) { \ + write(&val, sizeof(T)); \ + return *this; \ + } + + JSU_OUTPUTSTREAM_OPERATOR(signed char) + JSU_OUTPUTSTREAM_OPERATOR(unsigned char) + JSU_OUTPUTSTREAM_OPERATOR(signed short) + JSU_OUTPUTSTREAM_OPERATOR(unsigned short) + JSU_OUTPUTSTREAM_OPERATOR(int) + JSU_OUTPUTSTREAM_OPERATOR(unsigned int) + JSU_OUTPUTSTREAM_OPERATOR(signed long) + JSU_OUTPUTSTREAM_OPERATOR(unsigned long) + JSU_OUTPUTSTREAM_OPERATOR(signed long long) + JSU_OUTPUTSTREAM_OPERATOR(unsigned long long) + +#undef JSU_OUTPUTSTREAM_OPERATOR + + JSUOutputStream& operator<<(const char* param_0) { + write(param_0); + return *this; + } +}; // Size = 0x8 + +#endif /* JSUOUTPUTSTREAM_H */ diff --git a/include/JSystem/JSupport/JSURandomOutputStream.h b/include/JSystem/JSupport/JSURandomOutputStream.h new file mode 100644 index 000000000..ce377f319 --- /dev/null +++ b/include/JSystem/JSupport/JSURandomOutputStream.h @@ -0,0 +1,20 @@ +#ifndef JSURANDOMOUTPUTSTREAM_H +#define JSURANDOMOUTPUTSTREAM_H + +#include "JSystem/JSupport/JSUInputStream.h" +#include "JSystem/JSupport/JSUOutputStream.h" + +class JSURandomOutputStream : public JSUOutputStream { +public: + JSURandomOutputStream() {} + virtual ~JSURandomOutputStream() {} + + /* vt[4] */ virtual s32 writeData(const void*, s32) = 0; + /* vt[5] */ virtual s32 getLength() const = 0; + /* vt[6] */ virtual s32 getPosition() const = 0; + /* vt[7] */ virtual s32 seek(s32, JSUStreamSeekFrom); + /* vt[8] */ virtual s32 getAvailable() const; + /* vt[9] */ virtual s32 seekPos(s32, JSUStreamSeekFrom) = 0; +}; // Size = 0x8 + +#endif /* JSURANDOMOUTPUTSTREAM_H */ diff --git a/include/dolphin/hio.h b/include/dolphin/hio.h new file mode 100644 index 000000000..dc83ee19a --- /dev/null +++ b/include/dolphin/hio.h @@ -0,0 +1,28 @@ +#ifndef _DOLPHIN_HIO_H_ +#define _DOLPHIN_HIO_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*HIOCallback)(void); +typedef BOOL (*HIOEnumCallback)(s32 chan); + +BOOL HIOEnumDevices(HIOEnumCallback callback); +BOOL HIOInit(s32 chan, HIOCallback callback); +BOOL HIOInitEx(s32 chan, u32 dev, HIOCallback callback); +BOOL HIOReadMailbox(u32* word); +BOOL HIOWriteMailbox(u32 word); +BOOL HIORead(u32 addr, void* buffer, s32 size); +BOOL HIOWrite(u32 addr, void* buffer, s32 size); +BOOL HIOReadAsync(u32 addr, void* buffer, s32 size, HIOCallback callback); +BOOL HIOWriteAsync(u32 addr, void* buffer, s32 size, HIOCallback callback); +BOOL HIOReadStatus(u32* status); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/m_Do/m_Do_hostIO.h b/include/m_Do/m_Do_hostIO.h index 39719834b..8a1836415 100644 --- a/include/m_Do/m_Do_hostIO.h +++ b/include/m_Do/m_Do_hostIO.h @@ -1,59 +1,22 @@ #ifndef M_DO_M_DO_HOSTIO_H #define M_DO_M_DO_HOSTIO_H +#include "JSystem/JHostIO/JORReflexible.h" #include "dolphin/types.h" #include -// move JOR stuff later -class JOREventListener; -class JORPropertyEvent; -class JORNodeEvent; -class JORGenEvent; -class JOREvent; -class JORServer; - #if VERSION == VERSION_DEMO #define HIO(name) l_HIO.name #else #define HIO(name) L_HIO::name #endif -class JORMContext { -public: - void genCheckBox(const char* param_1, u8* param_2, u8 param_3, u32 param_4, JOREventListener* param_5, u16 param_6, u16 param_7, u16 param_8, u16 param_9) { - genCheckBoxSub(0x108, param_1, (uintptr_t)param_2, param_4, *param_2, param_3, param_5, param_6, param_7, param_8, param_9); - } - void genCheckBoxSub(u32, const char*, uintptr_t, u32, u16, u16, JOREventListener*, u16, u16, u16, u16); -}; - -class JOREventListener { -public: -#ifdef DEBUG - virtual void listenPropertyEvent(const JORPropertyEvent*) = 0; -#endif -}; - -class JORReflexible : public JOREventListener { -public: -#ifdef DEBUG - JORReflexible() {} - static JORServer* getJORServer(); - - virtual void listenPropertyEvent(const JORPropertyEvent*) {} - virtual void listen(u32, const JOREvent*) {} - virtual void genObjectInfo(const JORGenEvent*) {} - virtual void genMessage(JORMContext*) = 0; - virtual void listenNodeEvent(const JORNodeEvent*) {} -#endif -}; - class mDoHIO_child_c { public: mDoHIO_child_c() { field_0x18 = 0; mPt = NULL; } - ~mDoHIO_child_c() {} const char* getName() { return mName; } @@ -66,33 +29,36 @@ public: /* 0x1C */ JORReflexible* mPt; }; -class mDoHIO_subRoot_c { +class mDoHIO_subRoot_c : public JORReflexible { public: virtual ~mDoHIO_subRoot_c() {} - s8 createChild(const char*, JORReflexible*); + void updateChild(s8); void deleteChild(s8); + s8 createChild(const char*, JORReflexible*); - void updateChild(s8) {} + void genMessage(JORMContext*); private: - /* 0x4 */ mDoHIO_child_c mChild[64]; + /* 0x4 */ mDoHIO_child_c mChildren[64]; }; -class mDoHIO_root_c { +class mDoHIO_root_c : public JORReflexible { public: + mDoHIO_root_c() {} virtual ~mDoHIO_root_c() {} void update(); - - s8 createChild(const char* name, JORReflexible* hio) { - return m_subroot.createChild(name, hio); - } + void updateChild(s8); void deleteChild(s8 childID) { - m_subroot.deleteChild(childID); + mSub.deleteChild(childID); } + s8 createChild(const char* name, JORReflexible* hio) { + return mSub.createChild(name, hio); + } + void genMessage(JORMContext*); - /* 0x0 */ mDoHIO_subRoot_c m_subroot; + /* 0x0 */ mDoHIO_subRoot_c mSub; }; class mDoHIO_entry_c : public JORReflexible { diff --git a/src/JSystem/JGadget/define.cpp b/src/JSystem/JGadget/define.cpp index ea26b5710..6b8deff90 100644 --- a/src/JSystem/JGadget/define.cpp +++ b/src/JSystem/JGadget/define.cpp @@ -1,3 +1,6 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + #include "JSystem/JSystem.h" // IWYU pragma: keep #include "JSystem/JGadget/define.h" diff --git a/src/JSystem/JHostIO/JHIComm.cpp b/src/JSystem/JHostIO/JHIComm.cpp new file mode 100644 index 000000000..94c59b48e --- /dev/null +++ b/src/JSystem/JHostIO/JHIComm.cpp @@ -0,0 +1,305 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#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/src/JSystem/JHostIO/JHICommonMem.cpp b/src/JSystem/JHostIO/JHICommonMem.cpp new file mode 100644 index 000000000..f16701ffc --- /dev/null +++ b/src/JSystem/JHostIO/JHICommonMem.cpp @@ -0,0 +1,21 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#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/src/JSystem/JHostIO/JHIMccBuf.cpp b/src/JSystem/JHostIO/JHIMccBuf.cpp new file mode 100644 index 000000000..657f03f19 --- /dev/null +++ b/src/JSystem/JHostIO/JHIMccBuf.cpp @@ -0,0 +1,449 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHIMccBuf.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JHostIO/JHIRMcc.h" +#include "dolphin/hio.h" +#include + +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) { + OSReport("ERROR: Illegal offset specified Error. -HIOWrite()\n"); + OSReport("ERROR: offset: %08x low:%08x high:%08x\n", offset, 0, (field_0x1c + field_0xc) * 2); + disablePort(); + return 0; + } + + while (HIORead(offset + field_0x20, buffer, size) == 0 && attempts < 30) { + attempts++; + } + + if (attempts >= 30) { + OSReport("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) { + OSReport("ERROR: Illegal offset specified Error. -HIOWrite()\n"); + OSReport("ERROR: offset: %08x low:%08x high:%08x\n", offset, 0, (field_0x1c + field_0xc) * 2); + disablePort(); + return 0; + } + + while (HIOWrite(offset + field_0x20, buffer, size) == 0 && attempts < 30) { + attempts++; + } + + 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/src/JSystem/JHostIO/JHIMemBuf.cpp b/src/JSystem/JHostIO/JHIMemBuf.cpp new file mode 100644 index 000000000..a4b454b71 --- /dev/null +++ b/src/JSystem/JHostIO/JHIMemBuf.cpp @@ -0,0 +1,73 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHICommonMem.h" +#include "JSystem/JKernel/JKRHeap.h" + +int JHIMemBuf::create() { + int rt = 1; + if (mp_buffer == NULL) { + mp_buffer = new (32) u8[0x20000]; + + if (mp_buffer == NULL) { + rt = 0; + OSReport("ERROR: hioSync Alloc Mem NG!\n"); + } else { + OSReport("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/src/JSystem/JHostIO/JHIRMcc.cpp b/src/JSystem/JHostIO/JHIRMcc.cpp new file mode 100644 index 000000000..d4728fe49 --- /dev/null +++ b/src/JSystem/JHostIO/JHIRMcc.cpp @@ -0,0 +1,92 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHIMccBuf.h" +#include "dolphin/hio.h" + +s32 gExiChannel = -1; + +JHIMccContext tContext_old; +JHIMccContext tContext_new; +bool initialized_; +u8 negotiate_; + +BOOL JHIhioCallbackEnum(s32 type) { + gExiChannel = type; + return 0; +} + +void JHIEnumDevices(s32*, u32*) { + /* Nonmatching */ +} + +u32 JHIInitInterface() { + /* Nonmatching */ + return 1; +} + +bool JHINegotiateInterface(u32) { + /* Nonmatching */ + 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; + } + + initialized_ = JHINegotiateInterface(800); + if (initialized_) { + 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 = initialized_; + } + + if (initialized_) { + *pCtx = tContext_new; + } else { + *pCtx = tContext_old; + } + + return TRUE; +} diff --git a/src/JSystem/JHostIO/JHIhioASync.cpp b/src/JSystem/JHostIO/JHIhioASync.cpp new file mode 100644 index 000000000..29f61ffb4 --- /dev/null +++ b/src/JSystem/JHostIO/JHIhioASync.cpp @@ -0,0 +1,172 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JHIMccBuf.h" +#include "JSystem/JHostIO/JHIRMcc.h" +#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) { + OSReport("INFO:********************************\n"); + OSReport("INFO: Opening Hostio service...\n"); + + if (!JHIInitMCC(&gMccContext, NULL)) { + gsEnableInterface = FALSE; + OSReport("ERROR: Cannot Open HostIO Interface..\n"); + OSReport("INFO: *** Disable JHostIO ***\n"); + } + + gsReadBuf = new (32) u8[0xC000]; + gsWriteBuf = new (32) u8[0xC000]; + + if (gsReadBuf == NULL || gsWriteBuf == NULL) { + gsEnableInterface = FALSE; + OSReport("ERROR: Cannot alloc transport buffer..\n"); + OSReport("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()) { + OSReport("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/src/JSystem/JHostIO/JOREntry.cpp b/src/JSystem/JHostIO/JOREntry.cpp new file mode 100644 index 000000000..542fc3cfd --- /dev/null +++ b/src/JSystem/JHostIO/JOREntry.cpp @@ -0,0 +1,27 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#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* pPortMng = JHIComPortManager::create(); + pPortMng->getRefPort().setBuf(pComReader, pComWriter); + JHISetBuffer(&ctx); + + JORServer* pServer = JORServer::create(); + pPortMng->addTag(pServer); + pServer->sendReset(); +} diff --git a/src/JSystem/JHostIO/JORFile.cpp b/src/JSystem/JHostIO/JORFile.cpp new file mode 100644 index 000000000..03a433823 --- /dev/null +++ b/src/JSystem/JHostIO/JORFile.cpp @@ -0,0 +1,187 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JHostIO/JORFile.h" +#include "JSystem/JHostIO/JORServer.h" + +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/src/JSystem/JHostIO/JORHostInfo.cpp b/src/JSystem/JHostIO/JORHostInfo.cpp new file mode 100644 index 000000000..5bea41f5f --- /dev/null +++ b/src/JSystem/JHostIO/JORHostInfo.cpp @@ -0,0 +1,61 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#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/src/JSystem/JHostIO/JORMessageBox.cpp b/src/JSystem/JHostIO/JORMessageBox.cpp new file mode 100644 index 000000000..8cf36822f --- /dev/null +++ b/src/JSystem/JHostIO/JORMessageBox.cpp @@ -0,0 +1,19 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#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/src/JSystem/JHostIO/JORServer.cpp b/src/JSystem/JHostIO/JORServer.cpp new file mode 100644 index 000000000..e7cd5f025 --- /dev/null +++ b/src/JSystem/JHostIO/JORServer.cpp @@ -0,0 +1,825 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#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 + +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()) { + OSReport("JORServer::receive : データが足りない\n"); + OSReport("JORServer::receive : データが足りない\n"); + return; + } + + switch (command) { + case ECommand_GetRootObj: + if (mp_rootObj != NULL) { + OSReport("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(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(obj_addr)->listen(command, pEvent); + } + } + break; + case ECommand_GenObjInfo: { + u32 obj_addr; + stream.read(obj_addr); + + if (stream.isGood()) { + reinterpret_cast(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) { + OSReport("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->seconds = seconds; + pTime->minutes = minutes; + pTime->hours = hours; + pTime->day_of_month = monthday; + pTime->month = month - 1; + pTime->year = year; + pTime->week_day = weekday; + pTime->milliseconds = milliseconds; + pTime->microseconds = 0; + pTime->year_day = 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/src/JSystem/JHostIO/JORShellExecute.cpp b/src/JSystem/JHostIO/JORShellExecute.cpp new file mode 100644 index 000000000..a53265ec5 --- /dev/null +++ b/src/JSystem/JHostIO/JORShellExecute.cpp @@ -0,0 +1,21 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#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; +} diff --git a/src/JSystem/JSupport/JSUInputStream.cpp b/src/JSystem/JSupport/JSUInputStream.cpp index 432844987..4a631a18c 100644 --- a/src/JSystem/JSupport/JSUInputStream.cpp +++ b/src/JSystem/JSupport/JSUInputStream.cpp @@ -11,8 +11,9 @@ /* 802BF3F4-802BF47C .text __dt__14JSUInputStreamFv */ JSUInputStream::~JSUInputStream() { - if (!isGood()) + if (!isGood()) { OSReport("JSUInputStream: occur error.\n"); + } } /* 802BF47C-802BF4D4 .text read__14JSUInputStreamFPvl */ @@ -24,29 +25,46 @@ s32 JSUInputStream::read(void* buffer, s32 numBytes) { return bytesRead; } +char* JSUInputStream::read(char* str) { + u16 sp8; + if (readData(&sp8, sizeof(sp8)) != sizeof(sp8)) { + *str = 0; + setState(IOS_STATE_1); + return 0; + } + + s32 len = readData(str, sp8); + str[len] = 0; + if (len != sp8) { + setState(IOS_STATE_1); + } + return str; +} + /* 802BF4D4-802BF554 .text skip__14JSUInputStreamFl */ s32 JSUInputStream::skip(s32 count) { - s32 skipCount = 0; - u8 buffer[1]; - while (count > skipCount) { - if (readData(&buffer, 1) != 1) { + s32 skipCount; + for (skipCount = 0; skipCount < count; skipCount++) { + u8 buffer; + if (readData(&buffer, sizeof(buffer)) != sizeof(buffer)) { setState(IOS_STATE_1); break; } - skipCount++; } + return skipCount; } /* 802BF554-802BF5E0 .text align__20JSURandomInputStreamFl */ s32 JSURandomInputStream::align(s32 alignment) { + s32 seekLen = 0; s32 currentPos = getPosition(); - s32 offset = (alignment + currentPos); - offset -= 1; - offset &= ~(alignment - 1); + + s32 offset = (alignment - 1 + currentPos) & ~(alignment - 1); s32 alignmentOffset = offset - currentPos; + if (alignmentOffset != 0) { - s32 seekLen = seekPos(offset, JSUStreamSeekFrom_SET); + seekLen = seekPos(offset, JSUStreamSeekFrom_SET); if (seekLen != alignmentOffset) { setState(IOS_STATE_1); } diff --git a/src/JSystem/JSupport/JSUMemoryStream.cpp b/src/JSystem/JSupport/JSUMemoryStream.cpp index f984e472b..945cde5e2 100644 --- a/src/JSystem/JSupport/JSUMemoryStream.cpp +++ b/src/JSystem/JSupport/JSUMemoryStream.cpp @@ -65,3 +65,52 @@ s32 JSUMemoryInputStream::getLength() const { s32 JSUMemoryInputStream::getPosition() const { return mPosition; } + +void JSUMemoryOutputStream::setBuffer(void* pBuffer, s32 length) { + mBuffer = pBuffer; + mLength = length; + mPosition = 0; +} + +s32 JSUMemoryOutputStream::writeData(const void* pData, s32 length) { + if (mPosition + length > mLength) { + length = mLength - mPosition; + } + + if (length > 0) { + memcpy((void*)((s32)mBuffer + mPosition), pData, length); + mPosition += length; + } + + return length; +} + +s32 JSUMemoryOutputStream::seekPos(s32 pos, JSUStreamSeekFrom seekFrom) { + s32 oldPos = mPosition; + + switch (seekFrom) { + case JSUStreamSeekFrom_SET: + mPosition = pos; + break; + case JSUStreamSeekFrom_END: + mPosition = mLength - pos; + break; + case JSUStreamSeekFrom_CUR: + mPosition += pos; + break; + } + + if (mPosition < 0) { + mPosition = 0; + } + + if (mPosition > mLength) { + mPosition = mLength; + } + + return mPosition - oldPos; +} + +s32 JSUMemoryOutputStream::getLength() const { + return mLength; +} diff --git a/src/JSystem/JSupport/JSUOutputStream.cpp b/src/JSystem/JSupport/JSUOutputStream.cpp new file mode 100644 index 000000000..2f33d7dc7 --- /dev/null +++ b/src/JSystem/JSupport/JSUOutputStream.cpp @@ -0,0 +1,63 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#include "JSystem/JSystem.h" // IWYU pragma: keep + +#include "JSystem/JSupport/JSUOutputStream.h" +#include "JSystem/JSupport/JSURandomOutputStream.h" +#include + +JSUOutputStream::~JSUOutputStream() { + if (!isGood()) { + OSReport("JSUOutputStream: occur error.\n"); + } +} + +s32 JSUOutputStream::write(const void* buffer, s32 numBytes) { + s32 bytesWrote = writeData(buffer, numBytes); + if (bytesWrote != numBytes) { + setState(IOS_STATE_1); + } + return bytesWrote; +} + +void JSUOutputStream::write(const char* str) { + if (str == NULL) { + u16 spA = 0; + if (writeData(&spA, sizeof(spA)) != sizeof(spA)) { + setState(IOS_STATE_1); + } + } else { + int len = strlen(str); + if (len >= 0x10000) { + setState(IOS_STATE_2); + } else { + u16 sp8 = len; + if (writeData(&sp8, sizeof(sp8)) != sizeof(sp8) || writeData(str, len) != len) { + setState(IOS_STATE_1); + } + } + } +} + +s32 JSUOutputStream::skip(s32 count, s8 param_1) { + s32 skipCount = 0; + for (; skipCount < count; skipCount++) { + if (writeData(¶m_1, sizeof(param_1)) != sizeof(param_1)) { + setState(IOS_STATE_1); + break; + } + } + + return skipCount; +} + +s32 JSURandomOutputStream::seek(s32 param_0, JSUStreamSeekFrom param_1) { + s32 seekResult = seekPos(param_0, param_1); + clrState(IOS_STATE_1); + return seekResult; +} + +s32 JSURandomOutputStream::getAvailable() const { + return getLength() - getPosition(); +} diff --git a/src/d/actor/d_a_sail.cpp b/src/d/actor/d_a_sail.cpp index 987c3822b..78512b410 100644 --- a/src/d/actor/d_a_sail.cpp +++ b/src/d/actor/d_a_sail.cpp @@ -570,7 +570,7 @@ static BOOL daSail_Delete(sail_class* i_this) { dComIfG_resDeleteDemo(&i_this->mKaizokusenPhase, "Kaizokusen"); if (l_HIO.mNo >= 0) { - mDoHIO_root.m_subroot.deleteChild(l_HIO.mNo); + mDoHIO_deleteChild(l_HIO.mNo); l_HIO.mNo = -1; } @@ -622,7 +622,7 @@ static cPhs_State daSail_Create(fopAc_ac_c* i_actor) { if (phase_state == cPhs_COMPLEATE_e) { if (fopAcM_entrySolidHeap(i_this, daSail_checkCreateHeap, 0x4C0)) { if (l_HIO.mNo < 0) { - l_HIO.mNo = mDoHIO_root.m_subroot.createChild("海賊船の帆", &l_HIO); // "Pirate Ship's Sail" + l_HIO.mNo = mDoHIO_createChild("海賊船の帆", &l_HIO); // "Pirate Ship's Sail" } i_this->mSailPacket.m1C44 = 0.0f; diff --git a/src/d/d_debug_pad.cpp b/src/d/d_debug_pad.cpp index 3d7b51463..cccf26e09 100644 --- a/src/d/d_debug_pad.cpp +++ b/src/d/d_debug_pad.cpp @@ -1,5 +1,5 @@ // Debug-only file. This file is known to have existed for TWW based on the debug maps. -// The contents of this are copied from the TP debug build decomp and may or may not match the actual TWW debug build. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. #include "d/d_debug_pad.h" #include "m_Do/m_Do_controller_pad.h" diff --git a/src/d/d_debug_viewer.cpp b/src/d/d_debug_viewer.cpp index 6801ebffd..1857f3842 100644 --- a/src/d/d_debug_viewer.cpp +++ b/src/d/d_debug_viewer.cpp @@ -1,5 +1,5 @@ // Debug-only file. This file is known to have existed for TWW based on the debug maps. -// The contents of this are copied from the TP debug build decomp and may or may not match the actual TWW debug build. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. #include "d/dolzel.h" // IWYU pragma: keep diff --git a/src/d/d_menu_fmap2.cpp b/src/d/d_menu_fmap2.cpp index 517ae2487..81947a3e8 100644 --- a/src/d/d_menu_fmap2.cpp +++ b/src/d/d_menu_fmap2.cpp @@ -149,7 +149,7 @@ void dMenu_Fmap2_c::_create() { JUT_ASSERT(VERSION_SELECT(323, 323, 346, 346), mCmapTxtMain_p[1] != NULL); screenSet(); field_0x27fb = 0; - g_mf2HIO.mNo = mDoHIO_root.m_subroot.createChild("フィールドマップ画面2", &g_mf2HIO); + g_mf2HIO.mNo = mDoHIO_createChild("フィールドマップ画面2", &g_mf2HIO); } /* 801BBA2C-801BCC74 .text screenSet__13dMenu_Fmap2_cFv */ diff --git a/src/d/d_s_name.cpp b/src/d/d_s_name.cpp index 96a64dcad..12e1b54a8 100644 --- a/src/d/d_s_name.cpp +++ b/src/d/d_s_name.cpp @@ -181,7 +181,7 @@ cPhs_State dScnName_c::create() { dFs_c->_create(); - g_snHIO.mNo = mDoHIO_root.m_subroot.createChild("名前登録シーン", &g_snHIO); + g_snHIO.mNo = mDoHIO_createChild("名前登録シーン", &g_snHIO); #if VERSION == VERSION_DEMO mDoExt_restoreCurrentHeap(); @@ -648,7 +648,7 @@ dScnName_c::~dScnName_c() { dFe_c->_deleteSp(); } s8 no = g_snHIO.mNo; - mDoHIO_root.m_subroot.deleteChild(no); + mDoHIO_deleteChild(no); mDoExt_destroySolidHeap(heap); dComIfG_deleteStageRes("Stage"); dComIfGp_setWindowNum(0); @@ -673,7 +673,7 @@ dScnName_c::~dScnName_c() { mArchive->unmountFixed(); delete cloth.cloth_c; s8 no = g_snHIO.mNo; - mDoHIO_root.m_subroot.deleteChild(no); + mDoHIO_deleteChild(no); JKRSetCurrentHeap(oldHeap); heap->destroy(); dComIfG_deleteStageRes("Stage"); diff --git a/src/dolphin/hio/hio.c b/src/dolphin/hio/hio.c new file mode 100644 index 000000000..2ff0a0973 --- /dev/null +++ b/src/dolphin/hio/hio.c @@ -0,0 +1,411 @@ +// Debug-only file. This file is known to have existed for TWW based on the debug maps. +// The contents of this are based on the TP debug build decomp and may or may not match the actual TWW debug build. + +#include "dolphin/exi/EXIBios.h" +#include "dolphin/os/OS.h" +#include + +static u32 Dev; +#define HIO_DEV Dev + +#if DEBUG +const char* __HIOVersion = "<< Dolphin SDK - HIO\tdebug build: Apr 5 2004 03:57:05 (0x2301) >>"; +#else +const char* __HIOVersion = "<< Dolphin SDK - HIO\trelease build: Apr 5 2004 04:15:47 (0x2301) >>"; +#endif + +static char __HIODigest1[71] = "\"HIO library - Copyright (C) 2000-2002 Nintendo. All rights reserved.\""; + +#if DEBUG +static char __HIODigest2[34] = "\"HIO built: Apr 5 2004 03:57:05\""; +#else +static char __HIODigest2[34] = "\"HIO built: Apr 5 2004 04:15:47\""; +#endif + +static s32 Chan = -1; +static HIOCallback ExiCallback; +static HIOCallback TxCallback; +static HIOCallback RxCallback; + +static void ExtHandler(s32 chan, OSContext *context) { + Chan = -1; + HIO_DEV = 0; + + if (chan < 2 && HIO_DEV == 0) { + EXISetExiCallback(chan, NULL); + } else if (chan == 0 && HIO_DEV == 2) { + EXISetExiCallback(2, NULL); + } +} + +static void ExiHandler(s32 chan, OSContext* context) { + if (ExiCallback) { + ExiCallback(); + } +} + +static void DbgHandler(__OSInterrupt interrupt, OSContext *context) { + OSContext exceptionContext; + + __PIRegs[0] = 0x1000; + if (ExiCallback) { + OSClearContext(&exceptionContext); + OSSetCurrentContext(&exceptionContext); + ExiCallback(); + OSClearContext(&exceptionContext); + OSSetCurrentContext(context); + } +} + +static void TxHandler(s32 chan, OSContext* context) { + EXIDeselect(Chan); + EXIUnlock(Chan); + if (TxCallback) { + TxCallback(); + } +} + +static void RxHandler(s32 chan, OSContext* context) { + EXIDeselect(Chan); + EXIUnlock(Chan); + if (RxCallback) { + RxCallback(); + } +} + +BOOL HIOEnumDevices(HIOEnumCallback callback) { + s32 chan; + u32 id; + + if (Chan != -1 || callback == NULL) { + return 0; + } + + HIO_DEV = 0; + for (chan = 0; chan <= 2; chan++) { + if (chan < 2) { + while (EXIProbeEx(chan) == 0) {} + } + + if (EXIGetID(chan, HIO_DEV, &id) != 0 && id - 0x1010000 == 0 && !callback(chan)) { + return 1; + } + } + + return 1; +} + +static inline int CheckConsoleType() { + if (__OSGetDIConfig() == 0xFF) { + if (((OSGetConsoleType() & 0xF0000000) + 0xE0000000) == 0) { + return 1; + } + + switch (__OSDeviceCode) { + case 0x8200: + return 1; + } + + return 0; + } + + return 1; +} + +BOOL HIOInit(s32 chan, HIOCallback callback) { + int err; + u32 cmd; + u32 id; + + while (__OSDeviceCode == 0) {} + + if (CheckConsoleType() == 0) { + Chan = -1; + HIO_DEV = 0; + OSReport("%s\n", __HIODigest1, __HIODigest2); + return 0; + } + + if (Chan != -1) { + return 1; + } + + Chan = chan; + ExiCallback = callback; + TxCallback = NULL; + RxCallback = NULL; + + if (chan < 2 && HIO_DEV == 0) { + while (EXIProbeEx(Chan) == 0) {} + + if (EXIAttach(Chan, ExtHandler) == 0) { + Chan = -1; + HIO_DEV = 0; + return 0; + } + } + + if (EXILock(Chan, HIO_DEV, 0) == 0) { + EXIDetach(Chan); + Chan = -1; + HIO_DEV = 0; + return 0; + } + + if (EXISelect(Chan, HIO_DEV, 0) == 0) { + EXIUnlock(Chan); + EXIDetach(Chan); + Chan = -1; + HIO_DEV = 0; + return 0; + } + + cmd = 0; + err = 0; + err |= !EXIImm(Chan, &cmd, 2, 1, 0); + err |= !EXISync(Chan); + err |= !EXIImm(Chan, &id, 4, 0, 0); + err |= !EXISync(Chan); + err |= !EXIDeselect(Chan); + EXIUnlock(Chan); + + if (err != 0 || id != 0x1010000) { + if (chan < 2 && HIO_DEV == 0) { + EXIDetach(Chan); + } + EXIUnlock(Chan); + Chan = -1; + HIO_DEV = 0; + return 0; + } + + if (ExiCallback) { + if (chan < 2) { + if (HIO_DEV == 0) { + EXISetExiCallback(Chan, ExiHandler); + } else { + ASSERTLINE(331, HIO_DEV == 2); + EXISetExiCallback(2, ExiHandler); + } + } else { + __OSSetInterruptHandler(0x19, DbgHandler); + __OSUnmaskInterrupts(0x40); + } + } + + OSRegisterVersion(__HIOVersion); + return 1; +} + +BOOL HIOInitEx(s32 chan, u32 dev, HIOCallback callback) { + ASSERTLINE(348, dev == 0 || chan == 0 && dev == 2); + + if (dev != 0 && (chan != 0 || dev != 2)) { + return 0; + } + + if (Chan != -1) { + return 1; + } + + HIO_DEV = dev; + return HIOInit(chan, callback); +} + +BOOL HIOReadMailbox(u32* word) { + int err; + u32 cmd; + + if (Chan == -1 || CheckConsoleType() == 0) { + return 0; + } + + if (EXILock(Chan, HIO_DEV, 0) == 0) { + return 0; + } + + if (EXISelect(Chan, HIO_DEV, 4) == 0) { + EXIUnlock(Chan); + return 0; + } + + cmd = 0x60000000; + err = 0; + err |= !EXIImm(Chan, &cmd, 2, 1, 0); + err |= !EXISync(Chan); + err |= !EXIImm(Chan, word, 4, 0, 0); + err |= !EXISync(Chan); + err |= !EXIDeselect(Chan); + EXIUnlock(Chan); + return !err; +} + +BOOL HIOWriteMailbox(u32 word) { + int err; + u32 cmd; + + if (Chan == -1 || CheckConsoleType() == 0) { + return 0; + } + + if (EXILock(Chan, HIO_DEV, 0) == 0) { + return 0; + } + + if (EXISelect(Chan, HIO_DEV, 4) == 0) { + EXIUnlock(Chan); + return 0; + } + + cmd = (word & 0x1FFFFFFF) | 0xC0000000; + err = 0; + err |= !EXIImm(Chan, &cmd, 4, 1, 0); + err |= !EXISync(Chan); + err |= !EXIDeselect(Chan); + EXIUnlock(Chan); + return !err; +} + +BOOL HIORead(u32 addr, void* buffer, s32 size) { + int err; + u32 cmd; + + if (Chan == -1 || CheckConsoleType() == 0) { + return 0; + } + + ASSERTLINE(436, (addr % 4) == 0); + + if (EXILock(Chan, HIO_DEV, 0) == 0) { + return 0; + } + + if (EXISelect(Chan, HIO_DEV, 4) == 0) { + EXIUnlock(Chan); + return 0; + } + + cmd = ((addr << 8) & 0x01FFFC00) | 0x20000000; + err = 0; + err |= !EXIImm(Chan, &cmd, 4, 1, 0); + err |= !EXISync(Chan); + err |= !EXIDma(Chan, buffer, size, 0, NULL); + err |= !EXISync(Chan); + err |= !EXIDeselect(Chan); + EXIUnlock(Chan); + return !err; +} + +BOOL HIOWrite(u32 addr, void* buffer, s32 size) { + int err; + u32 cmd; + + if (Chan == -1 || CheckConsoleType() == 0) { + return 0; + } + + ASSERTLINE(470, (addr % 4) == 0); + + if (EXILock(Chan, HIO_DEV, 0) == 0) { + return 0; + } + + if (EXISelect(Chan, HIO_DEV, 4) == 0) { + EXIUnlock(Chan); + return 0; + } + + cmd = ((addr << 8) & 0x01FFFC00) | 0xA0000000; + err = 0; + err |= !EXIImm(Chan, &cmd, 4, 1, 0); + err |= !EXISync(Chan); + err |= !EXIDma(Chan, buffer, size, 1, NULL); + err |= !EXISync(Chan); + err |= !EXIDeselect(Chan); + EXIUnlock(Chan); + return !err; +} + +BOOL HIOReadAsync(u32 addr, void* buffer, s32 size, HIOCallback callback) { + int err; + u32 cmd; + + if (Chan == -1 || CheckConsoleType() == 0) { + return 0; + } + + ASSERTLINE(504, (addr % 4) == 0); + RxCallback = callback; + + if (EXILock(Chan, HIO_DEV, 0) == 0) { + return 0; + } + + if (EXISelect(Chan, HIO_DEV, 4) == 0) { + EXIUnlock(Chan); + return 0; + } + + cmd = ((addr << 8) & 0x01FFFC00) | 0x20000000; + err = 0; + err |= !EXIImm(Chan, &cmd, 4, 1, 0); + err |= !EXISync(Chan); + err |= !EXIDma(Chan, buffer, size, 0, RxHandler); + return !err; +} + +BOOL HIOWriteAsync(u32 addr, void* buffer, s32 size, HIOCallback callback) { + int err; + u32 cmd; + + if (Chan == -1 || CheckConsoleType() == 0) { + return 0; + } + + ASSERTLINE(537, (addr % 4) == 0); + TxCallback = callback; + + if (EXILock(Chan, HIO_DEV, 0) == 0) { + return 0; + } + + if (EXISelect(Chan, HIO_DEV, 4) == 0) { + EXIUnlock(Chan); + return 0; + } + + cmd = ((addr << 8) & 0x01FFFC00) | 0xA0000000; + err = 0; + err |= !EXIImm(Chan, &cmd, 4, 1, 0); + err |= !EXISync(Chan); + err |= !EXIDma(Chan, buffer, size, 1, TxHandler); + return !err; +} + +BOOL HIOReadStatus(u32* status) { + int err; + u32 cmd; + + if (Chan == -1 || CheckConsoleType() == 0) { + return 0; + } + + if (EXILock(Chan, HIO_DEV, 0) == 0) { + return 0; + } + + if (EXISelect(Chan, HIO_DEV, 4) == 0) { + EXIUnlock(Chan); + return 0; + } + + cmd = 0x40000000; + err = 0; + err |= !EXIImm(Chan, &cmd, 2, 1, 0); + err |= !EXISync(Chan); + err |= !EXIImm(Chan, status, 4, 0, 0); + err |= !EXISync(Chan); + err |= !EXIDeselect(Chan); + EXIUnlock(Chan); + return !err; +} diff --git a/src/m_Do/m_Do_hostIO.cpp b/src/m_Do/m_Do_hostIO.cpp index 2bc81e66c..84e348773 100644 --- a/src/m_Do/m_Do_hostIO.cpp +++ b/src/m_Do/m_Do_hostIO.cpp @@ -10,13 +10,35 @@ mDoHIO_root_c mDoHIO_root; +#if DEBUG +void mDoHIO_root_c::genMessage(JORMContext* i_context) { + i_context->genNode("Node", &mSub, 0, 0); +} + +void mDoHIO_subRoot_c::genMessage(JORMContext* i_context) { + for (int i = 0; i < 80; i++) { + JORReflexible* node = mChildren[i].getPt(); + + if (node != NULL) { + i_context->genNode(mChildren[i].getName(), node, 0, 0); + } + } +} +#endif + /* 80017A4C-80017A50 .text update__13mDoHIO_root_cFv */ -void mDoHIO_root_c::update() {} +void mDoHIO_root_c::update() { +#if DEBUG + JORMContext* context = attachJORMContext(5); + context->invalidNode(this, 3); + releaseJORMContext(context); +#endif +} /* 80017A50-80017B20 .text createChild__16mDoHIO_subRoot_cFPCcP13JORReflexible */ -s8 mDoHIO_subRoot_c::createChild(const char* i_name, JORReflexible* i_reflexible) { +s8 mDoHIO_subRoot_c::createChild(const char* i_name, JORReflexible* i_node) { for (int i = 0; i < 64; i++) { - if (mChild[i].getPt() == i_reflexible) { + if (mChildren[i].getPt() == i_node) { // "Danger: Trying to register an already registered HostIO<%s>\n" OSReport_Error("危険:既に登録されているホストIOをふたたび登録しようとしています<%s>\n", i_name); return -1; @@ -24,9 +46,9 @@ s8 mDoHIO_subRoot_c::createChild(const char* i_name, JORReflexible* i_reflexible } for (int i = 0; i < 64; i++) { - if (mChild[i].getPt() == NULL) { - mChild[i].setName(i_name); - mChild[i].setPt(i_reflexible); + if (mChildren[i].getPt() == NULL) { + mChildren[i].setName(i_name); + mChildren[i].setPt(i_node); return i; } } @@ -39,16 +61,26 @@ s8 mDoHIO_subRoot_c::createChild(const char* i_name, JORReflexible* i_reflexible /* 80017B20-80017B88 .text deleteChild__16mDoHIO_subRoot_cFSc */ void mDoHIO_subRoot_c::deleteChild(s8 i_childID) { if (i_childID >= 0) { - if (mChild[i_childID].getPt() == NULL) { + if (mChildren[i_childID].getPt() == NULL) { // "Danger: Trying to delete HostIO that has already been deleted<%s>\n" - OSReport_Error("危険:すでに削除されているホストIOをさらに削除しようとしています<%s>\n", mChild[i_childID].getName()); + OSReport_Error("危険:すでに削除されているホストIOをさらに削除しようとしています<%s>\n", mChildren[i_childID].getName()); } else { - mChild[i_childID].setPt(NULL); + mChildren[i_childID].setPt(NULL); } } } #if VERSION == VERSION_DEMO +void mDoHIO_subRoot_c::updateChild(s8 i_no) { + i_no--; + + if (i_no >= 0) { + JORMContext* context = attachJORMContext(5); + context->invalidNode(mChildren[i_no].getPt(), 3); + releaseJORMContext(context); + } +} + mDoHIO_entry_c::mDoHIO_entry_c() { mNo = 0; mCount = 0; @@ -75,4 +107,12 @@ void mDoHIO_entry_c::removeHIO() { mDoHIO_deleteChild(mNo); } } + +void mDoHIO_updateChild(s8 i_no) { + mDoHIO_root.updateChild(i_no); +} + +void mDoHIO_root_c::updateChild(s8 i_no) { + mSub.updateChild(i_no); +} #endif diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index efa369c99..a87fe17b4 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -419,6 +419,17 @@ void main01() { ArchiveHeapCheck.setHeap(mDoExt_getArchiveHeap()); CommandHeapCheck.setHeap(mDoExt_getCommandHeap()); + #if DEBUG + JKRHeap* var_r28 = JKRGetSystemHeap(); + JKRHeap* sp10 = mDoExt_setCurrentHeap(var_r28); + JOR_INIT(); + JOR_SETROOTNODE("root", &mDoHIO_root, 4, 3); + mDoExt_setCurrentHeap(sp10); + + s32 local_34 = var_r28->getTotalFreeSize(); + OSReport("\x1b[36mHOSTIOヒープ残り %u Bytes\n\x1b[m", local_34); + #endif + JUTConsole* console = JFWSystem::getSystemConsole(); #if VERSION == VERSION_DEMO console->setOutput(JUTConsole::OUTPUT_OSR_AND_CONSOLE); @@ -494,6 +505,11 @@ void main01() { } while (true); } +#if DEBUG +template<> +JHIComPortManager* JHIComPortManager:: instance; +#endif + #if VERSION == VERSION_DEMO void parse_args(int argc, const char* argv[]) { for (int i = 0; i < argc; i++) {