mirror of
https://github.com/isledecomp/isle.git
synced 2026-01-21 15:21:15 +00:00
* 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)
343 lines
9.5 KiB
C++
343 lines
9.5 KiB
C++
#include "mxioinfo.h"
|
|
#include "ddraw.h"
|
|
|
|
// OFFSET: LEGO1 0x100cc800
|
|
MXIOINFO::MXIOINFO()
|
|
{
|
|
memset(&m_info, 0, sizeof(MMIOINFO));
|
|
}
|
|
|
|
// OFFSET: LEGO1 0x100cc820
|
|
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)
|
|
{
|
|
_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)
|
|
{
|
|
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)
|
|
{
|
|
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
|
|
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;
|
|
} |