MXIOINFO Progress

* MXIOINFO: 100%
* ~MXIOINFO: 100%
* Close: 100%
* Open: 100%
* SetBuffer: 80% (matching except register allocation)
* Something: 96% (matching except == comparison args swapped)
* Read: 59% (having trouble with the loop)
This commit is contained in:
Mark Langen 2023-07-01 21:54:02 -07:00
parent 8dfacd18d8
commit 7d6fb5432c
2 changed files with 311 additions and 13 deletions

View File

@ -1,4 +1,5 @@
#include "mxioinfo.h"
#include "ddraw.h"
// OFFSET: LEGO1 0x100cc800
MXIOINFO::MXIOINFO()
@ -12,38 +13,331 @@ MXIOINFO::~MXIOINFO()
Close(0);
}
// OFFSET: LEGO1 0x100cc8e0
unsigned short MXIOINFO::Close(long arg)
{
short result = 0;
if (m_info.hmmio != NULL)
{
result = Flush(0);
_lclose((HFILE)m_info.hmmio);
m_info.hmmio = NULL;
if (m_info.dwFlags & MMIO_ALLOCBUF)
free(m_info.pchBuffer);
m_info.pchEndWrite = NULL;
m_info.pchEndRead = NULL;
m_info.pchBuffer = NULL;
m_info.dwFlags = 0;
}
return result;
}
// OFFSET: LEGO1 0x100cc830
unsigned short MXIOINFO::Open(const char *filename, DWORD fdwOpen)
{
return 0;
}
// OFFSET: LEGO1 0x100cc8e0
void MXIOINFO::Close(long arg)
{
_OFSTRUCT lpReOpenBuff;
unsigned short result = 0;
m_info.lBufOffset = 0;
m_info.lDiskOffset = 0;
m_info.hmmio = (HMMIO)OpenFile(filename, &lpReOpenBuff, (unsigned short)fdwOpen);
if (m_info.hmmio != (HMMIO)HFILE_ERROR)
{
m_info.dwFlags = fdwOpen;
if (m_info.dwFlags & MMIO_ALLOCBUF)
{
long currentLength = m_info.cchBuffer != 0 ? m_info.cchBuffer : 0x2000;
char* buffer = (char*)malloc(currentLength);
if (buffer == NULL)
{
m_info.cchBuffer = 0;
m_info.dwFlags &= ~MMIO_ALLOCBUF;
m_info.pchBuffer = NULL;
result = MMIOERR_OUTOFMEMORY;
}
else
{
m_info.cchBuffer = currentLength;
m_info.pchBuffer = buffer;
}
m_info.pchEndRead = m_info.pchBuffer;
m_info.pchNext = m_info.pchBuffer;
m_info.pchEndWrite = m_info.pchBuffer + m_info.cchBuffer;
}
}
else
{
result = MMIOERR_CANNOTOPEN;
}
return result;
}
// Not close to a match yet.
// OFFSET: LEGO1 0x100cc930
unsigned long MXIOINFO::Read(HPSTR pch, LONG cch)
{
return 0;
long result = 0;
if (m_info.pchBuffer != NULL)
{
LONG toRead = m_info.pchEndRead - m_info.pchNext;
unsigned long remaining = cch;
do
{
if (toRead > 0) {
if (toRead > remaining) {
toRead = remaining;
}
remaining -= toRead;
memcpy(pch, m_info.pchNext, toRead);
m_info.pchNext += toRead;
}
} while (remaining && !Something(0) && m_info.pchEndRead - m_info.pchNext >= 1);
}
else
{
if (m_info.hmmio != NULL && cch > 0) {
result = _hread((HFILE)m_info.hmmio, pch, cch);
if (result == -1) {
result = 0;
m_info.lDiskOffset = GetCurrentOffset();
}
else
{
m_info.lDiskOffset += result;
}
}
}
return result;
}
// First attemp, not particularly close, see some sensible logic of what the
// function is trying to do.
// OFFSET: LEGO1 0x100cca00
LONG MXIOINFO::Seek(LONG lOffset, int iOrigin)
{
return 0;
LONG result = -1;
if (m_info.pchBuffer != NULL)
{
// Convert to SEEK_SET
if (iOrigin == SEEK_CUR) {
if (lOffset == 0) {
// Nothing to do
return (LONG)(m_info.pchNext + m_info.lBufOffset - m_info.pchBuffer);
} else {
iOrigin = 0;
lOffset = (LONG)(m_info.pchNext + lOffset + m_info.lBufOffset - m_info.pchBuffer);
}
} else if (iOrigin == SEEK_END) {
// Not implemented
return -1;
}
// Seek distance is already within the buffer
if ((m_info.lBufOffset <= lOffset) && (lOffset < m_info.cchBuffer + m_info.lBufOffset)) {
m_info.pchNext = m_info.pchBuffer + lOffset - m_info.lBufOffset;
return lOffset;
}
// Do SEEK_CUR on the underlying file handle
if (m_info.hmmio != NULL) {
short result = Flush(0);
if (result == 0) {
LONG newOffset = _llseek((HFILE)m_info.hmmio, lOffset, iOrigin);
m_info.lDiskOffset = newOffset;
if (newOffset == -1) {
m_info.lDiskOffset = GetCurrentOffset();
return -1;
}
LONG wholeBlockOffset = lOffset - (int)(lOffset % m_info.cchBuffer);
m_info.lBufOffset = wholeBlockOffset;
if (lOffset != wholeBlockOffset) {
LONG newOffset2 = _llseek((HFILE)m_info.hmmio, wholeBlockOffset, 0);
m_info.lDiskOffset = newOffset2;
if (newOffset2 == -1) {
m_info.lDiskOffset = GetCurrentOffset();
}
}
if (m_info.lDiskOffset == m_info.lBufOffset) {
DWORD rw = m_info.dwFlags & MMIO_RWMODE;
if (rw != MMIO_READ && rw != MMIO_READWRITE) {
m_info.pchNext = m_info.pchBuffer + lOffset - m_info.lBufOffset;
return lOffset;
}
LONG bytesRead = _hread((HFILE)m_info.hmmio, m_info.pchBuffer, m_info.cchBuffer);
if (bytesRead == -1) {
m_info.lDiskOffset = GetCurrentOffset();
return -1;
}
m_info.lDiskOffset += bytesRead;
m_info.pchNext = m_info.pchBuffer + lOffset - m_info.lBufOffset;
m_info.pchEndRead = m_info.pchBuffer + bytesRead;
if (m_info.pchNext < m_info.pchEndRead) {
return lOffset;
}
}
}
}
}
else
{
if (m_info.hmmio != NULL) {
if ((iOrigin == SEEK_CUR) && (lOffset == 0)) {
return m_info.lDiskOffset;
}
result = _llseek((HFILE)m_info.hmmio, lOffset, iOrigin);
m_info.lDiskOffset = result;
if (result == HFILE_ERROR) {
m_info.lDiskOffset = GetCurrentOffset();
}
}
}
return result;
}
// Matching except for swap of EAX and ECX
// OFFSET: LEGO1 0x100ccbc0
void MXIOINFO::SetBuffer(LPSTR pchBuffer, LONG cchBuffer, LONG unk)
unsigned short MXIOINFO::SetBuffer(LPSTR pchBuffer, LONG cchBuffer, UINT fuBuffer)
{
unsigned short ret = Flush(0);
if (m_info.dwFlags & MMIO_ALLOCBUF)
{
m_info.dwFlags &= ~MMIO_ALLOCBUF;
free(m_info.pchBuffer);
}
m_info.pchBuffer = pchBuffer;
m_info.cchBuffer = cchBuffer;
m_info.pchEndRead = pchBuffer;
m_info.pchEndWrite = pchBuffer + cchBuffer;
return ret;
}
// OFFSET: LEGO1 0x100cce60
unsigned short MXIOINFO::Descend(LPMMCKINFO pmmcki, const MMCKINFO *pmmckiParent, UINT fuDescend)
{
return 0;
}
// Not a close match, but the behavior looks reasonable.
// OFFSET: LEGO1 0x100ccc10
unsigned short MXIOINFO::Flush(int arg)
{
unsigned short result = 0;
if (m_info.dwFlags & MMIO_DIRTY)
{
if (m_info.pchBuffer == NULL)
{
result = MMIOERR_UNBUFFERED;
}
else
{
if (m_info.hmmio == NULL || (m_info.dwFlags & MMIO_RWMODE) == 0)
{
return MMIOERR_CANNOTWRITE;
}
if (m_info.cchBuffer > 0)
{
if (m_info.lDiskOffset != m_info.lBufOffset)
{
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, m_info.lBufOffset, 0);
}
if (m_info.lBufOffset == m_info.lDiskOffset)
{
long written = _hwrite((HFILE)m_info.hmmio, m_info.pchBuffer, m_info.cchBuffer);
if (written != -1 && m_info.cchBuffer == written)
{
m_info.lDiskOffset += written;
m_info.dwFlags &= ~MMIO_DIRTY;
m_info.pchNext = m_info.pchBuffer;
return 0;
}
m_info.lDiskOffset = GetCurrentOffset();
return MMIOERR_CANNOTWRITE;
}
m_info.lDiskOffset = GetCurrentOffset();
return MMIOERR_CANNOTSEEK;
}
}
}
return result;
}
// 97% Match, just two locations have the order of an == comparison swapped.
// I suspect this isn't how the code was originally written, because I have to
// include an empty if branch to get the code almost matching, though it is a
// place where you logically could have an empty block.
// OFFSET: LEGO1 0x100ccd00
unsigned short MXIOINFO::Something(UINT flags)
{
short result = 0;
DWORD rwState = m_info.dwFlags & MMIO_RWMODE;
if (m_info.pchBuffer != NULL)
{
LONG cchBuffer = m_info.cchBuffer;
if (((rwState == MMIO_WRITE) || (rwState == MMIO_READWRITE)) && (m_info.dwFlags & MMIO_DIRTY))
{
if (((flags & MMIO_WRITE) || (rwState == MMIO_READWRITE)) && (cchBuffer > 0))
{
if (m_info.lDiskOffset != m_info.lBufOffset) {
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, m_info.lBufOffset, 0);
}
if (m_info.lDiskOffset != m_info.lBufOffset)
{
result = MMIOERR_CANNOTSEEK;
m_info.lDiskOffset = GetCurrentOffset();
}
else
{
LONG bytesWritten = _hwrite((HFILE)m_info.hmmio, m_info.pchBuffer, cchBuffer);
if ((bytesWritten != -1) && (cchBuffer == bytesWritten)) {
m_info.lDiskOffset += bytesWritten;
m_info.dwFlags = m_info.dwFlags & ~MMIO_DIRTY;
m_info.pchNext = m_info.pchBuffer;
m_info.pchEndRead = m_info.pchBuffer;
}
else
{
result = MMIOERR_CANNOTWRITE;
m_info.lDiskOffset = GetCurrentOffset();
}
}
}
}
m_info.lBufOffset = m_info.lBufOffset + cchBuffer;
if (((rwState != MMIO_READ) && (rwState != MMIO_READWRITE)) || cchBuffer <= 0) {
// Nothing to do
}
else
{
if (m_info.lDiskOffset != m_info.lBufOffset) {
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, m_info.lBufOffset, 0);
}
if (m_info.lDiskOffset != m_info.lBufOffset) {
result = MMIOERR_CANNOTSEEK;
m_info.lDiskOffset = GetCurrentOffset();
} else {
LONG bytesRead = _hread((HFILE)m_info.hmmio, m_info.pchBuffer, cchBuffer);
if (bytesRead == -1) {
result = MMIOERR_CANNOTREAD;
m_info.lDiskOffset = GetCurrentOffset();
} else {
m_info.lDiskOffset += bytesRead;
m_info.pchNext = m_info.pchBuffer;
m_info.pchEndRead = m_info.pchBuffer + bytesRead;
return result;
}
}
}
}
else
{
result = MMIOERR_UNBUFFERED;
}
return result;
}

View File

@ -12,11 +12,15 @@ class MXIOINFO
__declspec(dllexport) ~MXIOINFO();
unsigned short Open(const char *filename, DWORD fdwOpen);
void Close(long arg);
unsigned short Close(long arg);
LONG Seek(LONG lOffset, int iOrigin);
unsigned long Read(HPSTR pch, LONG cch);
void SetBuffer(LPSTR pchBuffer, LONG cchBuffer, LONG unk);
unsigned short SetBuffer(LPSTR pchBuffer, LONG cchBuffer, UINT fuBuffer);
unsigned short Descend(LPMMCKINFO pmmcki, const MMCKINFO *pmmckiParent, UINT fuDescend);
unsigned short Flush(int arg);
unsigned short Something(UINT flags);
inline LONG GetCurrentOffset() { return _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR); }
MMIOINFO m_info;
};