Fixing up MXIOINFO to prepare for merge.

* Following feedback from @stravant and @itsmattkc, reverted back to using `MMIOINFO` struct as the class member instead of adding its values directly. (We actually gained a little on accuracy with this change.)
* The memset to zero out the values in the constructor now acts on `m_info` instead of `this`. Strictly speaking we don't need the size assert any more but I decided to keep it in case we change the members later for some reason.
* Casting the `hmmio` member to `HFILE` (int) or `HMMIO` (WORD) typedefs where needed.
* Squelch a signed/unsigned type comparison warning
This commit is contained in:
disinvite 2023-07-16 18:19:22 -04:00
parent 9ad8eb6430
commit d49946c534
2 changed files with 118 additions and 139 deletions

View File

@ -1,14 +1,15 @@
#include "mxioinfo.h"
#include "decomp.h"
// This class should be 72 bytes in size, same as the MMIOINFO struct.
// The current implementation has MMIOINFO as the only member of the class,
// but this assert will enforce the size if we decide to change that.
DECOMP_SIZE_ASSERT(MXIOINFO, sizeof(MMIOINFO));
// OFFSET: LEGO1 0x100cc800
MXIOINFO::MXIOINFO()
{
// This is not good practice, but shouldn't damage anything
// because MXIOINFO has no vtable.
memset(this, 0, sizeof(*this));
memset(&m_info, 0, sizeof(m_info));
}
// OFFSET: LEGO1 0x100cc820
@ -23,33 +24,33 @@ MxU16 MXIOINFO::Open(const char *p_filename, MxULong p_flags)
OFSTRUCT _unused;
MxU16 result = 0;
m_lBufOffset = 0;
m_lDiskOffset = 0;
m_info.lBufOffset = 0;
m_info.lDiskOffset = 0;
// Cast of p_flags to u16 forces the `movzx` instruction
m_hmmio = OpenFile(p_filename, &_unused, (MxU16)p_flags);
m_info.hmmio = (HMMIO)OpenFile(p_filename, &_unused, (MxU16)p_flags);
if (m_hmmio != HFILE_ERROR) {
m_dwFlags = p_flags;
if ((HFILE)m_info.hmmio != HFILE_ERROR) {
m_info.dwFlags = p_flags;
if (p_flags & MMIO_ALLOCBUF) {
// Default buffer length of 8k if none specified
int len = m_cchBuffer ? m_cchBuffer : 8192;
int len = m_info.cchBuffer ? m_info.cchBuffer : 8192;
HPSTR buf = new char[len];
if (!buf) {
result = MMIOERR_OUTOFMEMORY;
m_cchBuffer = 0;
m_dwFlags &= ~MMIO_ALLOCBUF;
m_pchBuffer = 0;
m_info.cchBuffer = 0;
m_info.dwFlags &= ~MMIO_ALLOCBUF;
m_info.pchBuffer = 0;
} else {
m_pchBuffer = buf;
m_cchBuffer = len;
m_info.pchBuffer = buf;
m_info.cchBuffer = len;
}
m_pchEndRead = m_pchBuffer;
m_pchNext = m_pchBuffer;
m_pchEndWrite = m_pchBuffer + m_cchBuffer;
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;
@ -63,18 +64,18 @@ MxU16 MXIOINFO::Close(MxLong p_unused)
{
MxU16 result = 0;
if (m_hmmio) {
if (m_info.hmmio) {
result = Flush(0);
_lclose(m_hmmio);
m_hmmio = NULL;
_lclose((HFILE)m_info.hmmio);
m_info.hmmio = 0;
if (m_dwFlags & MMIO_ALLOCBUF)
delete[] m_pchBuffer;
if (m_info.dwFlags & MMIO_ALLOCBUF)
delete[] m_info.pchBuffer;
m_pchEndWrite = 0;
m_pchEndRead = 0;
m_pchBuffer = 0;
m_dwFlags = 0;
m_info.pchEndWrite = 0;
m_info.pchEndRead = 0;
m_info.pchBuffer = 0;
m_info.dwFlags = 0;
}
return result;
@ -85,37 +86,37 @@ MxLong MXIOINFO::Read(void *p_buf, MxLong p_len)
{
MxLong bytes_read = 0;
if (m_pchBuffer) {
if (m_info.pchBuffer) {
int bytes_left = m_pchEndRead - m_pchNext;
int bytes_left = m_info.pchEndRead - m_info.pchNext;
while (p_len > 0) {
if (bytes_left > 0) {
if (p_len < bytes_left)
bytes_left = p_len;
memcpy(p_buf, m_pchNext, bytes_left);
memcpy(p_buf, m_info.pchNext, bytes_left);
p_len -= bytes_left;
m_pchNext += bytes_left;
m_info.pchNext += bytes_left;
bytes_read += bytes_left;
}
if (p_len <= 0 || Advance(0))
break;
bytes_left = m_pchEndRead - m_pchNext;
bytes_left = m_info.pchEndRead - m_info.pchNext;
if (bytes_left <= 0)
break;
}
} else if (m_hmmio && p_len > 0) {
bytes_read = _hread(m_hmmio, p_buf, p_len);
} else if (m_info.hmmio && p_len > 0) {
bytes_read = _hread((HFILE)m_info.hmmio, p_buf, p_len);
if (bytes_read == -1) {
bytes_read = 0;
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
} else {
m_lDiskOffset += bytes_read;
m_info.lDiskOffset += bytes_read;
}
}
@ -128,15 +129,15 @@ MxLong MXIOINFO::Seek(MxLong p_offset, int p_origin)
MxLong result = -1;
// If buffered I/O
if (m_pchBuffer) {
if (m_info.pchBuffer) {
if (p_origin == SEEK_CUR) {
if (!p_offset) {
// don't seek at all and just return where we are.
return m_lBufOffset + (m_pchNext - m_pchBuffer);
return m_info.lBufOffset + (m_info.pchNext - m_info.pchBuffer);
} else {
// With SEEK_CUR, p_offset is a relative offset.
// Get the absolute position instead and use SEEK_SET.
p_offset += m_lBufOffset + (m_pchNext - m_pchBuffer);
p_offset += m_info.lBufOffset + (m_info.pchNext - m_info.pchBuffer);
p_origin = SEEK_SET;
}
} else if (p_origin == SEEK_END) {
@ -148,52 +149,52 @@ MxLong MXIOINFO::Seek(MxLong p_offset, int p_origin)
// is p_offset between the start and end of the buffer?
// i.e. can we do the seek without reading more from disk?
if (p_offset >= m_lBufOffset && p_offset < m_lBufOffset + m_cchBuffer) {
m_pchNext = m_pchBuffer + (p_offset - m_lBufOffset);
if (p_offset >= m_info.lBufOffset && p_offset < m_info.lBufOffset + m_info.cchBuffer) {
m_info.pchNext = m_info.pchBuffer + (p_offset - m_info.lBufOffset);
result = p_offset;
} else {
// we have to read another chunk from disk.
if (m_hmmio && !Flush(0)) {
m_lDiskOffset = _llseek(m_hmmio, p_offset, p_origin);
if (m_info.hmmio && !Flush(0)) {
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, p_offset, p_origin);
if (m_lDiskOffset == -1) {
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
if (m_info.lDiskOffset == -1) {
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
} else {
// align offset to buffer size
int new_offset = p_offset - (p_offset % m_cchBuffer);
m_lBufOffset = new_offset;
int new_offset = p_offset - (p_offset % m_info.cchBuffer);
m_info.lBufOffset = new_offset;
// do we need to seek again?
// (i.e. are we already aligned to buffer size?)
if (p_offset != new_offset) {
m_lDiskOffset = _llseek(m_hmmio, new_offset, SEEK_SET);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, new_offset, SEEK_SET);
if (m_lDiskOffset == -1) {
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
if (m_info.lDiskOffset == -1) {
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
}
}
if (m_lBufOffset == m_lDiskOffset) {
if (m_info.lBufOffset == m_info.lDiskOffset) {
// is the file open for writing only?
if ((m_dwFlags & MMIO_RWMODE) &&
((m_dwFlags & MMIO_RWMODE) != MMIO_READWRITE)) {
if ((m_info.dwFlags & MMIO_RWMODE) &&
((m_info.dwFlags & MMIO_RWMODE) != MMIO_READWRITE)) {
m_pchNext = m_pchBuffer - m_lBufOffset + p_offset;
m_info.pchNext = m_info.pchBuffer - m_info.lBufOffset + p_offset;
result = p_offset;
} else {
// We can read from the file. Fill the buffer.
int bytes_read = _hread(m_hmmio, m_pchBuffer, m_cchBuffer);
int bytes_read = _hread((HFILE)m_info.hmmio, m_info.pchBuffer, m_info.cchBuffer);
if (bytes_read == -1) {
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
} else {
m_lDiskOffset += bytes_read;
m_pchNext = p_offset - m_lBufOffset + m_pchBuffer;
m_pchEndRead = m_pchBuffer + bytes_read;
m_info.lDiskOffset += bytes_read;
m_info.pchNext = p_offset - m_info.lBufOffset + m_info.pchBuffer;
m_info.pchEndRead = m_info.pchBuffer + bytes_read;
if (m_pchNext < m_pchEndRead) {
if (m_info.pchNext < m_info.pchEndRead) {
result = p_offset;
}
}
@ -204,17 +205,17 @@ MxLong MXIOINFO::Seek(MxLong p_offset, int p_origin)
}
} else {
// No buffer so just seek the file directly (if we have a valid handle)
if (m_hmmio) {
if (m_info.hmmio) {
// i.e. if we just want to get the current file position
if (p_origin == SEEK_CUR && p_offset == 0) {
return m_lDiskOffset;
return m_info.lDiskOffset;
} else {
m_lDiskOffset = _llseek(m_hmmio, p_offset, p_origin);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, p_offset, p_origin);
result = m_lDiskOffset;
result = m_info.lDiskOffset;
if (result == -1) {
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
}
}
}
@ -228,15 +229,15 @@ MxU16 MXIOINFO::SetBuffer(char *p_buf, MxLong p_len, MxLong p_unused)
{
MxU16 result = Flush(0);
if (m_dwFlags & MMIO_ALLOCBUF) {
m_dwFlags &= ~MMIO_ALLOCBUF;
delete[] m_pchBuffer;
if (m_info.dwFlags & MMIO_ALLOCBUF) {
m_info.dwFlags &= ~MMIO_ALLOCBUF;
delete[] m_info.pchBuffer;
}
m_pchBuffer = p_buf;
m_cchBuffer = p_len;
m_pchEndWrite = m_pchBuffer + m_cchBuffer;
m_pchEndRead = m_pchBuffer;
m_info.pchBuffer = p_buf;
m_info.cchBuffer = p_len;
m_info.pchEndWrite = m_info.pchBuffer + m_info.cchBuffer;
m_info.pchEndRead = m_info.pchBuffer;
return result;
}
@ -247,32 +248,32 @@ MxU16 MXIOINFO::Flush(MxU16 p_unused)
MxU16 result = 0;
// if buffer is dirty
if (m_dwFlags & MMIO_DIRTY) {
if (m_info.dwFlags & MMIO_DIRTY) {
// if we have allocated an IO buffer
if (m_pchBuffer) {
if (m_info.pchBuffer) {
// if we have a file open for writing
if (m_hmmio && (m_dwFlags & MMIO_RWMODE)) {
if (m_info.hmmio && (m_info.dwFlags & MMIO_RWMODE)) {
// (pulling this value out into a variable forces it into EBX)
MxLong cchBuffer = m_cchBuffer;
MxLong cchBuffer = m_info.cchBuffer;
if (cchBuffer > 0) {
if (m_lBufOffset != m_lDiskOffset) {
m_lDiskOffset = _llseek(m_hmmio, m_lBufOffset, SEEK_SET);
if (m_info.lBufOffset != m_info.lDiskOffset) {
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, m_info.lBufOffset, SEEK_SET);
}
// Was the previous seek (if required) successful?
if (m_lBufOffset != m_lDiskOffset) {
if (m_info.lBufOffset != m_info.lDiskOffset) {
result = MMIOERR_CANNOTSEEK;
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
} else {
MxLong bytes_written = _hwrite(m_hmmio, m_pchBuffer, cchBuffer);
MxLong bytes_written = _hwrite((HFILE)m_info.hmmio, m_info.pchBuffer, cchBuffer);
if (bytes_written != -1 && bytes_written == cchBuffer) {
m_lDiskOffset += bytes_written;
m_pchNext = m_pchBuffer;
m_dwFlags &= ~MMIO_DIRTY;
m_info.lDiskOffset += bytes_written;
m_info.pchNext = m_info.pchBuffer;
m_info.dwFlags &= ~MMIO_DIRTY;
} else {
result = MMIOERR_CANNOTWRITE;
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
}
}
}
@ -291,62 +292,62 @@ MxU16 MXIOINFO::Flush(MxU16 p_unused)
MxU16 MXIOINFO::Advance(MxU16 p_option)
{
MxU16 result = 0;
MxULong rwmode = m_dwFlags & MMIO_RWMODE;
MxULong rwmode = m_info.dwFlags & MMIO_RWMODE;
if (m_pchBuffer) {
MxLong cch = m_cchBuffer;
if (m_info.pchBuffer) {
MxLong cch = m_info.cchBuffer;
// If we can and should write to the file,
// if we are being asked to write to the file,
// and if there is a buffer *to* write:
if ((rwmode == MMIO_WRITE || rwmode == MMIO_READWRITE) &&
(m_dwFlags & MMIO_DIRTY) &&
(m_info.dwFlags & MMIO_DIRTY) &&
((p_option & MMIO_WRITE) || (rwmode == MMIO_READWRITE)) &&
cch > 0) {
if (m_lBufOffset != m_lDiskOffset) {
m_lDiskOffset = _llseek(m_hmmio, m_lBufOffset, SEEK_SET);
if (m_info.lBufOffset != m_info.lDiskOffset) {
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, m_info.lBufOffset, SEEK_SET);
}
if (m_lBufOffset != m_lDiskOffset) {
if (m_info.lBufOffset != m_info.lDiskOffset) {
result = MMIOERR_CANNOTSEEK;
} else {
MxLong bytes_written = _hwrite(m_hmmio, m_pchBuffer, cch);
MxLong bytes_written = _hwrite((HFILE)m_info.hmmio, m_info.pchBuffer, cch);
if (bytes_written != -1 && bytes_written == cch) {
m_lDiskOffset += bytes_written;
m_pchNext = m_pchBuffer;
m_pchEndRead = m_pchBuffer;
m_dwFlags &= ~MMIO_DIRTY;
m_info.lDiskOffset += bytes_written;
m_info.pchNext = m_info.pchBuffer;
m_info.pchEndRead = m_info.pchBuffer;
m_info.dwFlags &= ~MMIO_DIRTY;
} else {
result = MMIOERR_CANNOTWRITE;
}
}
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
}
m_lBufOffset += cch;
m_info.lBufOffset += cch;
if ((!rwmode || rwmode == MMIO_READWRITE) && cch > 0) {
if (m_lBufOffset != m_lDiskOffset) {
m_lDiskOffset = _llseek(m_hmmio, m_lBufOffset, SEEK_SET);
if (m_info.lBufOffset != m_info.lDiskOffset) {
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, m_info.lBufOffset, SEEK_SET);
}
// if previous seek failed
if (m_lBufOffset != m_lDiskOffset) {
if (m_info.lBufOffset != m_info.lDiskOffset) {
result = MMIOERR_CANNOTSEEK;
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
} else {
int bytes_read = _hread(m_hmmio, m_pchBuffer, cch);
int bytes_read = _hread((HFILE)m_info.hmmio, m_info.pchBuffer, cch);
if (bytes_read == -1) {
result = MMIOERR_CANNOTREAD;
m_lDiskOffset = _llseek(m_hmmio, 0, SEEK_CUR);
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
} else {
m_lDiskOffset += bytes_read;
m_pchNext = m_pchBuffer;
m_pchEndRead = m_pchBuffer + bytes_read;
m_info.lDiskOffset += bytes_read;
m_info.pchNext = m_info.pchBuffer;
m_info.pchEndRead = m_info.pchBuffer + bytes_read;
}
}
}
@ -370,10 +371,10 @@ MxU16 MXIOINFO::Descend(MMCKINFO *p_chunkInfo, const MMCKINFO *p_parentInfo, MxU
if (Read(p_chunkInfo, 8) != 8) {
result = MMIOERR_CANNOTREAD;
} else {
if (m_pchBuffer) {
p_chunkInfo->dwDataOffset = m_pchNext - m_pchBuffer + m_lBufOffset;
if (m_info.pchBuffer) {
p_chunkInfo->dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
} else {
p_chunkInfo->dwDataOffset = m_lDiskOffset;
p_chunkInfo->dwDataOffset = m_info.lDiskOffset;
}
if (p_chunkInfo->ckid == FOURCC_RIFF || p_chunkInfo->ckid == FOURCC_LIST) {
@ -383,7 +384,7 @@ MxU16 MXIOINFO::Descend(MMCKINFO *p_chunkInfo, const MMCKINFO *p_parentInfo, MxU
}
}
} else {
MxLong ofs = MAXLONG;
MxULong ofs = MAXLONG;
if (p_parentInfo)
ofs = p_parentInfo->cksize + p_parentInfo->dwDataOffset;
@ -401,10 +402,10 @@ MxU16 MXIOINFO::Descend(MMCKINFO *p_chunkInfo, const MMCKINFO *p_parentInfo, MxU
running = FALSE;
} else {
read_ok = TRUE;
if (m_pchBuffer) {
tmp.dwDataOffset = m_pchNext - m_pchBuffer + m_lBufOffset;
if (m_info.pchBuffer) {
tmp.dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
} else {
tmp.dwDataOffset = m_lDiskOffset;
tmp.dwDataOffset = m_info.lDiskOffset;
}
if (ofs < tmp.dwDataOffset) {

View File

@ -21,31 +21,9 @@ class MXIOINFO
MxU16 Advance(MxU16);
MxU16 Descend(MMCKINFO *, const MMCKINFO *, MxU16);
// The following is the MMIOINFO struct but with h_mmio set to type HFILE.
/* general fields */
DWORD m_dwFlags; /* 0 general status flags */
FOURCC m_fccIOProc; /* 4 pointer to I/O procedure */
LPMMIOPROC m_pIOProc; /* 8 pointer to I/O procedure */
UINT m_wErrorRet; /* c place for error to be returned */
HTASK m_htask; /* 10 alternate local task */
/* fields maintained by MMIO functions during buffered I/O */
LONG m_cchBuffer; /* 14 size of I/O buffer (or 0L) */
HPSTR m_pchBuffer; /* 18 start of I/O buffer (or NULL) */
HPSTR m_pchNext; /* 1c pointer to next byte to read/write */
HPSTR m_pchEndRead; /* 20 pointer to last valid byte to read */
HPSTR m_pchEndWrite; /* 24 pointer to last byte to write */
LONG m_lBufOffset; /* 28 disk offset of start of buffer */
/* fields maintained by I/O procedure */
LONG m_lDiskOffset; /* 2c disk offset of next read or write */
DWORD m_adwInfo[3]; /* 30 data specific to type of MMIOPROC */
/* other fields maintained by MMIO */
DWORD m_dwReserved1; /* 3c reserved for MMIO use */
DWORD m_dwReserved2; /* 40 reserved for MMIO use */
HFILE m_hmmio; /* 44 handle to open file */
// NOTE: In MXIOINFO, the `hmmio` member of MMIOINFO is used like
// an HFILE (int) instead of an HMMIO (WORD).
MMIOINFO m_info;
};
#endif // MXIOINFO_H