isle-portable/LEGO1/mxioinfo.cpp

461 lines
11 KiB
C++
Raw Normal View History

#include "mxioinfo.h"
2023-10-24 19:38:27 -04:00
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
#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));
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100cc800
MXIOINFO::MXIOINFO()
{
2023-10-24 19:38:27 -04:00
memset(&m_info, 0, sizeof(m_info));
}
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100cc820
MXIOINFO::~MXIOINFO()
{
2023-10-24 19:38:27 -04:00
Close(0);
}
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100cc830
2023-10-24 19:38:27 -04:00
MxU16 MXIOINFO::Open(const char* p_filename, MxULong p_flags)
{
OFSTRUCT unused;
2023-10-24 19:38:27 -04:00
MxU16 result = 0;
m_info.lBufOffset = 0;
m_info.lDiskOffset = 0;
2023-11-22 02:54:08 -05:00
// DECOMP: Cast of p_flags to u16 forces the `movzx` instruction
m_info.hmmio = (HMMIO) OpenFile(p_filename, &unused, (MxU16) p_flags);
2023-10-24 19:38:27 -04:00
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
2023-11-22 02:54:08 -05:00
MxLong len = m_info.cchBuffer ? m_info.cchBuffer : 8192;
2023-10-24 19:38:27 -04:00
HPSTR buf = new char[len];
if (!buf) {
result = MMIOERR_OUTOFMEMORY;
m_info.cchBuffer = 0;
m_info.dwFlags &= ~MMIO_ALLOCBUF;
m_info.pchBuffer = 0;
}
else {
m_info.pchBuffer = buf;
m_info.cchBuffer = len;
}
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;
}
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100cc8e0
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
MxU16 MXIOINFO::Close(MxLong p_unused)
{
2023-10-24 19:38:27 -04:00
MxU16 result = 0;
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
2023-10-24 19:38:27 -04:00
if (m_info.hmmio) {
result = Flush(0);
_lclose((HFILE) m_info.hmmio);
m_info.hmmio = 0;
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
2023-10-24 19:38:27 -04:00
if (m_info.dwFlags & MMIO_ALLOCBUF)
delete[] m_info.pchBuffer;
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
2023-10-24 19:38:27 -04:00
m_info.pchEndWrite = 0;
m_info.pchEndRead = 0;
m_info.pchBuffer = 0;
m_info.dwFlags = 0;
}
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
2023-10-24 19:38:27 -04:00
return result;
}
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100cc930
2023-10-24 19:38:27 -04:00
MxLong MXIOINFO::Read(void* p_buf, MxLong p_len)
{
MxLong bytesRead = 0;
2023-10-24 19:38:27 -04:00
if (m_info.pchBuffer) {
MxLong bytesLeft = m_info.pchEndRead - m_info.pchNext;
2023-10-24 19:38:27 -04:00
while (p_len > 0) {
if (bytesLeft > 0) {
if (p_len < bytesLeft)
bytesLeft = p_len;
2023-10-24 19:38:27 -04:00
memcpy(p_buf, m_info.pchNext, bytesLeft);
p_len -= bytesLeft;
2023-10-24 19:38:27 -04:00
m_info.pchNext += bytesLeft;
bytesRead += bytesLeft;
2023-10-24 19:38:27 -04:00
}
if (p_len <= 0 || Advance(0))
break;
bytesLeft = m_info.pchEndRead - m_info.pchNext;
if (bytesLeft <= 0)
2023-10-24 19:38:27 -04:00
break;
}
}
else if (m_info.hmmio && p_len > 0) {
bytesRead = _hread((HFILE) m_info.hmmio, p_buf, p_len);
2023-10-24 19:38:27 -04:00
if (bytesRead == -1) {
bytesRead = 0;
2023-10-24 19:38:27 -04:00
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
else {
m_info.lDiskOffset += bytesRead;
2023-10-24 19:38:27 -04:00
}
}
return bytesRead;
}
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100cca00
2023-11-22 02:54:08 -05:00
MxLong MXIOINFO::Seek(MxLong p_offset, MxLong p_origin)
{
2023-10-24 19:38:27 -04:00
MxLong result = -1;
// If buffered I/O
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_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_info.lBufOffset + (m_info.pchNext - m_info.pchBuffer);
p_origin = SEEK_SET;
}
}
else if (p_origin == SEEK_END) {
// not possible with buffered I/O
return -1;
}
// else p_origin == SEEK_SET.
// 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_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_info.hmmio && !Flush(0)) {
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, p_offset, p_origin);
if (m_info.lDiskOffset == -1) {
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
else {
// align offset to buffer size
MxLong newOffset = p_offset - (p_offset % m_info.cchBuffer);
m_info.lBufOffset = newOffset;
2023-10-24 19:38:27 -04:00
// do we need to seek again?
// (i.e. are we already aligned to buffer size?)
if (p_offset != newOffset) {
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, newOffset, SEEK_SET);
2023-10-24 19:38:27 -04:00
if (m_info.lDiskOffset == -1) {
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
}
if (m_info.lBufOffset == m_info.lDiskOffset) {
// is the file open for writing only?
if ((m_info.dwFlags & MMIO_RWMODE) && ((m_info.dwFlags & MMIO_RWMODE) != MMIO_READWRITE)) {
m_info.pchNext = m_info.pchBuffer - m_info.lBufOffset + p_offset;
result = p_offset;
}
else {
// We can read from the file. Fill the buffer.
MxLong bytesRead = _hread((HFILE) m_info.hmmio, m_info.pchBuffer, m_info.cchBuffer);
2023-10-24 19:38:27 -04:00
if (bytesRead == -1) {
2023-10-24 19:38:27 -04:00
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
else {
m_info.lDiskOffset += bytesRead;
2023-10-24 19:38:27 -04:00
m_info.pchNext = p_offset - m_info.lBufOffset + m_info.pchBuffer;
m_info.pchEndRead = m_info.pchBuffer + bytesRead;
2023-10-24 19:38:27 -04:00
if (m_info.pchNext < m_info.pchEndRead) {
result = p_offset;
}
}
}
}
}
}
}
}
else {
// No buffer so just seek the file directly (if we have a valid handle)
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_info.lDiskOffset;
}
else {
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, p_offset, p_origin);
result = m_info.lDiskOffset;
if (result == -1) {
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
}
}
}
return result;
}
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100ccbc0
2023-10-24 19:38:27 -04:00
MxU16 MXIOINFO::SetBuffer(char* p_buf, MxLong p_len, MxLong p_unused)
{
2023-10-24 19:38:27 -04:00
MxU16 result = Flush(0);
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
2023-10-24 19:38:27 -04:00
if (m_info.dwFlags & MMIO_ALLOCBUF) {
m_info.dwFlags &= ~MMIO_ALLOCBUF;
delete[] m_info.pchBuffer;
}
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
2023-10-24 19:38:27 -04:00
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;
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
2023-10-24 19:38:27 -04:00
return result;
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
}
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100ccc10
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
MxU16 MXIOINFO::Flush(MxU16 p_unused)
{
2023-10-24 19:38:27 -04:00
MxU16 result = 0;
// if buffer is dirty
if (m_info.dwFlags & MMIO_DIRTY) {
// if we have allocated an IO buffer
if (m_info.pchBuffer) {
// if we have a file open for writing
if (m_info.hmmio && (m_info.dwFlags & MMIO_RWMODE)) {
2023-11-22 02:54:08 -05:00
// DECOMP: pulling this value out into a variable forces it into EBX
2023-10-24 19:38:27 -04:00
MxLong cchBuffer = m_info.cchBuffer;
if (cchBuffer > 0) {
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_info.lBufOffset != m_info.lDiskOffset) {
result = MMIOERR_CANNOTSEEK;
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
else {
MxLong bytesWritten = _hwrite((HFILE) m_info.hmmio, m_info.pchBuffer, cchBuffer);
2023-10-24 19:38:27 -04:00
if (bytesWritten != -1 && bytesWritten == cchBuffer) {
m_info.lDiskOffset += bytesWritten;
2023-10-24 19:38:27 -04:00
m_info.pchNext = m_info.pchBuffer;
m_info.dwFlags &= ~MMIO_DIRTY;
}
else {
result = MMIOERR_CANNOTWRITE;
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
}
}
}
else {
result = MMIOERR_CANNOTWRITE;
}
}
else {
result = MMIOERR_UNBUFFERED;
}
}
return result;
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
}
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100ccd00
lego1: implement MXIOINFO (#54) * Implementation of MXIOINFO. Not a 100% match, but we are very close. I don't wanna wrangle with this one any more, so I figured I would open it up for review in case anyone else has ideas. **Known problems:** - The Open function uses a `movzx` instruction on the value of parameter `fdwOpen` before pushing to OpenFile from the kernel. You can force this to appear by casting to `unsigned short`, but this disturbs the instructions for the rest of the file. To get the "best" overall match I decided to leave this out. - Flush, Advance, and Descend differ only in the order of operands on a `cmp` instruction. - This entire file is honestly pretty ugly. The main reason is all the nested ifs; we are constrained by returning a result value from each function, but only at the very end instead of bailing out with a `return`. By far the worst offender is the do/while loop in the Descend function. **Design considerations:** - We are casting the file handle from MMIOINFO to `HFILE` everywhere it is used, so I decided to just change the type. While doing that, I figured I might as well just pull out the members from the struct so we don't have `m_info` all over the place. - Without using a struct member, we have the issue of the obvious `memset` used to zero out the values in the constructor. I changed this to work on the object itself, which would not be valid in most cases, but seems fine here since we have no virtual methods. There is a lot of repeated code here, namely the call to `_llseek` to reset `m_lDiskOffset` based on the current file position. You could move this to an inline function, but maybe that's not appropriate. There are probably strides to be made on code clarity and comments (if needed or wanted) here. I'm open to any suggestions. * remove casts on read, add size assert * Use more Mx* types and param style convention * 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
2023-07-16 21:37:21 -04:00
MxU16 MXIOINFO::Advance(MxU16 p_option)
{
2023-10-24 19:38:27 -04:00
MxU16 result = 0;
MxULong rwmode = m_info.dwFlags & MMIO_RWMODE;
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_info.dwFlags & MMIO_DIRTY) &&
((p_option & MMIO_WRITE) || (rwmode == MMIO_READWRITE)) && cch > 0) {
if (m_info.lBufOffset != m_info.lDiskOffset) {
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, m_info.lBufOffset, SEEK_SET);
}
if (m_info.lBufOffset != m_info.lDiskOffset) {
result = MMIOERR_CANNOTSEEK;
}
else {
MxLong bytesWritten = _hwrite((HFILE) m_info.hmmio, m_info.pchBuffer, cch);
2023-10-24 19:38:27 -04:00
if (bytesWritten != -1 && bytesWritten == cch) {
m_info.lDiskOffset += bytesWritten;
2023-10-24 19:38:27 -04:00
m_info.pchNext = m_info.pchBuffer;
m_info.pchEndRead = m_info.pchBuffer;
m_info.dwFlags &= ~MMIO_DIRTY;
}
else {
result = MMIOERR_CANNOTWRITE;
}
}
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
m_info.lBufOffset += cch;
if ((!rwmode || rwmode == MMIO_READWRITE) && cch > 0) {
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_info.lBufOffset != m_info.lDiskOffset) {
result = MMIOERR_CANNOTSEEK;
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
else {
MxLong bytesRead = _hread((HFILE) m_info.hmmio, m_info.pchBuffer, cch);
2023-10-24 19:38:27 -04:00
if (bytesRead == -1) {
2023-10-24 19:38:27 -04:00
result = MMIOERR_CANNOTREAD;
m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR);
}
else {
m_info.lDiskOffset += bytesRead;
2023-10-24 19:38:27 -04:00
m_info.pchNext = m_info.pchBuffer;
m_info.pchEndRead = m_info.pchBuffer + bytesRead;
2023-10-24 19:38:27 -04:00
}
}
}
}
else {
result = MMIOERR_UNBUFFERED;
}
return result;
}
(Proposal) Adjustments to "decomp" language (#308) * Adjustments to "decomp" language * Fix a comment * Fix accidental clang-formatting * Fix order * Fix order * Remove junk * Fix OFFSET * Adjustments based on new suggestions * Annotate globals * Globals in ISLE * More globals * Merge from parser2 branch * Allow prepending space for exact marker match * To eliminate noise, require the 0x prefix on offset for marker match * fix test from previous * Count tab stops for indented functions to reduce MISSED_END_OF_FUNCTION noise * FUNCTION to SYNTHETIC where needed * Missed marker conversion on SetAtomId * pylint cleanup, remove unused code * Fix unexpected function end, add more unit tests * Be more strict about synthetic name syntax * Revert "Missed marker conversion on SetAtomId" This reverts commit d87d665127fae7dd6e5bd48d9af14a0a829bf9e2. * Revert "FUNCTION to SYNTHETIC where needed" This reverts commit 8c815418d261ba8c5f67a9a2cae349fe4ac92db8. * Implicit lookup by name for functions * Fix VTABLE SYNTHETIC and other decomp markers * Get vtable class name * Vtable marker should identify struct * No colon for SIZE comment * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update README.md * Update CONTRIBUTING.md * Update README.md * Update CONTRIBUTING.md * Fix destructor/annotation * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md --------- Co-authored-by: disinvite <disinvite@users.noreply.github.com>
2023-12-06 07:10:45 -05:00
// FUNCTION: LEGO1 0x100cce60
2023-10-24 19:38:27 -04:00
MxU16 MXIOINFO::Descend(MMCKINFO* p_chunkInfo, const MMCKINFO* p_parentInfo, MxU16 p_descend)
{
2023-10-24 19:38:27 -04:00
MxU16 result = 0;
if (!p_chunkInfo)
return MMIOERR_BASE; // ?
if (!p_descend) {
p_chunkInfo->dwFlags = 0;
if (Read(p_chunkInfo, 8) != 8) {
result = MMIOERR_CANNOTREAD;
}
else {
if (m_info.pchBuffer) {
p_chunkInfo->dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
}
else {
p_chunkInfo->dwDataOffset = m_info.lDiskOffset;
}
2023-11-22 02:54:08 -05:00
if ((p_chunkInfo->ckid == FOURCC_RIFF || p_chunkInfo->ckid == FOURCC_LIST) &&
Read(&p_chunkInfo->fccType, 4) != 4) {
result = MMIOERR_CANNOTREAD;
2023-10-24 19:38:27 -04:00
}
}
}
else {
MxULong ofs = MAXLONG;
if (p_parentInfo)
ofs = p_parentInfo->cksize + p_parentInfo->dwDataOffset;
BOOL running = TRUE;
BOOL readOk = FALSE;
2023-10-24 19:38:27 -04:00
MMCKINFO tmp;
tmp.dwFlags = 0;
2023-11-22 02:54:08 -05:00
while (running) {
2023-10-24 19:38:27 -04:00
if (Read(&tmp, 8) != 8) {
// If the first read fails, report read error. Else EOF.
result = readOk ? MMIOERR_CHUNKNOTFOUND : MMIOERR_CANNOTREAD;
2023-10-24 19:38:27 -04:00
running = FALSE;
}
else {
readOk = TRUE;
2023-10-24 19:38:27 -04:00
if (m_info.pchBuffer) {
tmp.dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
}
else {
tmp.dwDataOffset = m_info.lDiskOffset;
}
if (ofs < tmp.dwDataOffset) {
result = MMIOERR_CHUNKNOTFOUND;
running = FALSE;
}
2023-11-22 02:54:08 -05:00
else if ((p_descend == MMIO_FINDLIST && tmp.ckid == FOURCC_LIST) || (p_descend == MMIO_FINDRIFF && tmp.ckid == FOURCC_RIFF)) {
if (Read(&tmp.fccType, 4) != 4) {
result = MMIOERR_CANNOTREAD;
2023-10-24 19:38:27 -04:00
running = FALSE;
}
2023-11-22 02:54:08 -05:00
else if (p_chunkInfo->fccType == tmp.fccType) {
2023-10-24 19:38:27 -04:00
running = FALSE;
}
}
2023-11-22 02:54:08 -05:00
else if (p_chunkInfo->ckid == tmp.ckid) {
running = FALSE;
}
else if (Seek((tmp.cksize & 1) + tmp.cksize, SEEK_CUR) == -1) {
result = MMIOERR_CANNOTSEEK;
running = FALSE;
}
2023-10-24 19:38:27 -04:00
}
2023-11-22 02:54:08 -05:00
}
2023-10-24 19:38:27 -04:00
if (!result)
memcpy(p_chunkInfo, &tmp, sizeof(MMCKINFO));
}
return result;
}