#include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/support.h" #include "TRK_MINNOW_DOLPHIN/utils/common/MWTrace.h" #include "TRK_MINNOW_DOLPHIN/MetroTRK/Portable/msgbuf.h" #include "string.h" DSError TRKSuppAccessFile(u32 file_handle, u8* data, size_t* count, DSIOResult* io_result, BOOL need_reply, BOOL read) { DSError error; int replyBufferId; TRKBuffer* replyBuffer; u32 length; int bufferId; TRKBuffer* buffer; u32 i; u8 replyIOResult; u32 replyLength; BOOL exit; CommandReply reply; if (data == NULL || *count == 0) { return DS_ParameterError; } exit = FALSE; *io_result = DS_IONoError; i = 0; error = DS_NoError; while (!exit && i < *count && error == DS_NoError && *io_result == 0) { memset(&reply, 0, sizeof(CommandReply)); if (*count - i <= 0x800) { length = *count - i; } else { length = 0x800; } reply.commandID.b = read ? DSMSG_ReadFile : DSMSG_WriteFile; if (read) { reply._00 = 0x40; } else { reply._00 = length + 0x40; } reply.replyError.r = file_handle; *(u16*)&reply._0C = length; TRKGetFreeBuffer(&bufferId, &buffer); error = TRKAppendBuffer_ui8(buffer, (u8*)&reply, 0x40); if (!read && error == DS_NoError) { error = TRKAppendBuffer_ui8(buffer, data + i, length); } if (error == DS_NoError) { if (need_reply) { BOOL b = read && file_handle == 0; error = TRKRequestSend(buffer, &replyBufferId, read ? 5 : 5, 3, !b); if (error == DS_NoError) { replyBuffer = (TRKBuffer*)TRKGetBuffer(replyBufferId); } replyIOResult = *(u32*)(replyBuffer->data + 0x10); replyLength = *(u16*)(replyBuffer->data + 0x14); if (read && error == DS_NoError && replyLength <= length) { TRKSetBufferPosition(replyBuffer, 0x40); error = TRKReadBuffer_ui8(replyBuffer, data + i, replyLength); if (error == DS_MessageBufferReadError) { error = DS_NoError; } } if (replyLength != length) { length = replyLength; exit = TRUE; } *io_result = (DSIOResult)replyIOResult; TRKReleaseBuffer(replyBufferId); } else { error = TRKMessageSend(buffer); } } TRKReleaseBuffer(bufferId); i += length; } *count = i; return error; } DSError TRKRequestSend(TRKBuffer* msgBuf, int* bufferId, u32 p1, u32 p2, int p3) { int error = DS_NoError; TRKBuffer* buffer; u32 counter; int count; u8 msgCmd; int msgReplyError; BOOL badReply = TRUE; *bufferId = -1; for (count = p2 + 1; count != 0 && *bufferId == -1 && error == DS_NoError; count--) { error = TRKMessageSend(msgBuf); if (error == DS_NoError) { if (p3) { counter = 0; } while (TRUE) { do { *bufferId = TRKTestForPacket(); if (*bufferId != -1) break; } while (!p3 || ++counter < 79999980); if (*bufferId == -1) break; badReply = 0; buffer = TRKGetBuffer(*bufferId); TRKSetBufferPosition(buffer, 0); OutputData(&buffer->data[0], buffer->length); msgCmd = buffer->data[4]; if (msgCmd >= DSMSG_ReplyACK) break; TRKProcessInput(*bufferId); *bufferId = -1; } if (*bufferId != -1) { if (buffer->length < 0x40) { // OSReport("MetroTRK - bad reply size %ld\n", buffer->length); badReply = TRUE; } if (error == DS_NoError && !badReply) { msgReplyError = buffer->data[8]; } if (error == DS_NoError && !badReply) { if ((int)msgCmd != DSMSG_ReplyACK || msgReplyError != DSREPLY_NoError) { badReply = TRUE; } } if (error != DS_NoError || badReply) { TRKReleaseBuffer(*bufferId); *bufferId = -1; } } } } if (*bufferId == -1) { error = DS_Error800; } return error; } DSError HandleOpenFileSupportRequest(const char* path, u8 replyError, u32* param_3, DSIOResult* ioResult) { DSError error; int bufferId2; int bufferId1; TRKBuffer* tempBuffer; TRKBuffer* buffer; CommandReply reply; memset(&reply, 0, sizeof(CommandReply)); *param_3 = 0; reply.commandID.b = DSMSG_OpenFile; reply._00 = strlen(path) + 0x40 + 1; reply.replyError.b = replyError; *(u16*)&reply._0C = strlen(path) + 1; TRKGetFreeBuffer(&bufferId1, &buffer); error = TRKAppendBuffer_ui8(buffer, (u8*)&reply, 0x40); if (error == DS_NoError) { error = TRKAppendBuffer_ui8(buffer, (u8*)path, strlen(path) + 1); } if (error == DS_NoError) { *ioResult = DS_IONoError; error = TRKRequestSend(buffer, &bufferId2, 7, 3, 0); if (error == DS_NoError) { tempBuffer = TRKGetBuffer(bufferId2); } *ioResult = *(u32*)(tempBuffer->data + 0x10); *param_3 = *(u32*)(tempBuffer->data + 0x8); TRKReleaseBuffer(bufferId2); } TRKReleaseBuffer(bufferId1); return error; } DSError HandleCloseFileSupportRequest(int replyError, DSIOResult* ioResult) { DSError error; int replyBufferId; int bufferId; TRKBuffer* buffer1; TRKBuffer* buffer2; CommandReply reply; memset(&reply, 0, sizeof(CommandReply)); reply.commandID.b = DSMSG_CloseFile; reply._00 = 0x40; reply.replyError.r = replyError; error = TRKGetFreeBuffer(&bufferId, &buffer1); if (error == DS_NoError) { error = TRKAppendBuffer_ui8(buffer1, (u8*)&reply, sizeof(CommandReply)); } if (error == DS_NoError) { *ioResult = DS_IONoError; error = TRKRequestSend(buffer1, &replyBufferId, 3, 3, 0); if (error == DS_NoError) { buffer2 = TRKGetBuffer(replyBufferId); } if (error == DS_NoError) { *ioResult = *(u32*)(buffer2->data + 0x10); } TRKReleaseBuffer(replyBufferId); } TRKReleaseBuffer(bufferId); return error; } DSError HandlePositionFileSupportRequest(DSReplyError replyErr, u32* param_2, u8 param_3, DSIOResult* ioResult) { DSError error; int bufferId2; int bufferId1; TRKBuffer* buffer1; TRKBuffer* buffer2; CommandReply reply; memset(&reply, 0, sizeof(CommandReply)); reply.commandID.b = DSMSG_PositionFile; reply._00 = 0x40; reply.replyError.r = replyErr; reply._0C = *param_2; reply._10[0] = param_3; error = TRKGetFreeBuffer(&bufferId1, &buffer1); if (error == DS_NoError) { error = TRKAppendBuffer_ui8(buffer1, (u8*)&reply, sizeof(CommandReply)); } if (error == DS_NoError) { *ioResult = DS_IONoError; *param_2 = -1; error = TRKRequestSend(buffer1, &bufferId2, 3, 3, 0); if (error == DS_NoError) { buffer2 = TRKGetBuffer(bufferId2); if (buffer2 != NULL) { *ioResult = *(u32*)(buffer2->data + 0x10); *param_2 = *(u32*)(buffer2->data + 0x18); } } TRKReleaseBuffer(bufferId2); } TRKReleaseBuffer(bufferId1); return error; }