From f707af34dbc707d4cfc769a8ce59e65689a8b46a Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 12 Jul 2023 14:12:03 -0700 Subject: [PATCH 1/8] move `override` macro to `compat.h` --- LEGO1/compat.h | 9 ++++++++- LEGO1/legostream.h | 3 ++- LEGO1/mxcore.h | 5 +++-- LEGO1/mxthread.h | 3 ++- LEGO1/mxtypes.h | 4 ---- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/LEGO1/compat.h b/LEGO1/compat.h index 496fa4db..7d76dfd0 100644 --- a/LEGO1/compat.h +++ b/LEGO1/compat.h @@ -11,4 +11,11 @@ #define COMPAT_CONST #endif -#endif // ISLECOMPAT_H \ No newline at end of file +// We use `override` so newer compilers can tell us our vtables are valid, +// however this keyword was added in C++11, so we define it as empty for +// compatibility with older compilers. +#if defined(_MSC_VER) && _MSC_VER <= 1200 // 1200 corresponds to VC6.0 but "override" was probably added even later +#define override +#endif + +#endif // ISLECOMPAT_H diff --git a/LEGO1/legostream.h b/LEGO1/legostream.h index a505cd54..ca110f01 100644 --- a/LEGO1/legostream.h +++ b/LEGO1/legostream.h @@ -1,6 +1,7 @@ #ifndef LEGOSTREAM_H #define LEGOSTREAM_H +#include "compat.h" #include "decomp.h" #include "mxtypes.h" @@ -70,4 +71,4 @@ class LegoMemoryStream : public LegoStream MxU32 m_offset; }; -#endif // LEGOSTREAM_H \ No newline at end of file +#endif // LEGOSTREAM_H diff --git a/LEGO1/mxcore.h b/LEGO1/mxcore.h index 5e6586ba..9fb3e689 100644 --- a/LEGO1/mxcore.h +++ b/LEGO1/mxcore.h @@ -3,6 +3,7 @@ #include +#include "compat.h" #include "mxtypes.h" class MxParam; @@ -14,8 +15,8 @@ class MxCore public: __declspec(dllexport) MxCore(); __declspec(dllexport) virtual ~MxCore(); // vtable+00 - __declspec(dllexport) virtual MxLong Notify(MxParam &p); // vtable+04 - virtual MxLong Tickle(); // vtable+08 + __declspec(dllexport) virtual MxResult Notify(MxParam &p); // vtable+04 + virtual MxResult Tickle(); // vtable+08 // OFFSET: LEGO1 0x100144c0 inline virtual const char *ClassName() const // vtable+0c diff --git a/LEGO1/mxthread.h b/LEGO1/mxthread.h index 6ac96b59..4537dc14 100644 --- a/LEGO1/mxthread.h +++ b/LEGO1/mxthread.h @@ -1,6 +1,7 @@ #ifndef MXTHREAD_H #define MXTHREAD_H +#include "compat.h" #include "mxtypes.h" #include "mxsemaphore.h" @@ -54,4 +55,4 @@ class MxTickleThread : public MxThread MxS32 m_frequencyMS; }; -#endif // MXTHREAD_H \ No newline at end of file +#endif // MXTHREAD_H diff --git a/LEGO1/mxtypes.h b/LEGO1/mxtypes.h index 8a7d5026..d17ac09a 100644 --- a/LEGO1/mxtypes.h +++ b/LEGO1/mxtypes.h @@ -39,8 +39,4 @@ typedef MxU8 MxBool; #define FALSE 0 #endif -#if defined(_MSC_VER) && _MSC_VER <= 1200 // 1200 corresponds to VC6.0 but "override" was probably added even later -#define override -#endif - #endif // MXTYPE_H From f8b1995a8350a3b80530b362119fcb05425b16e8 Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Sun, 16 Jul 2023 01:51:24 -0400 Subject: [PATCH 2/8] LEGO1: MxPalette (#56) * MxPalette - add missing member variables, Detach function * mb * MxPalette: give bob the builder his constructor * push progress, gn * avoid hexadecimal Co-authored-by: Anonymous Maarten * fix MxPalette::GetDefaultPalette Co-authored-by: Anonymous Maarten * aaaaaaaaaaaaaa * Revert "fix MxPalette::GetDefaultPalette" This reverts commit 63f2215737d3bcd286f67dcf1a04fdf8a234d41b. * Implement MxPalette::Clone (doesn't match) * fix MxPalette structure and match ctor/dtor * Matching progress for MxPalette::GetDefaultPalette * Implement ApplySystemEntriesToPalette except the memcpy calls * implement SetSkyColor (doesn't match) * Use MxTypes instead of generics * prefer decimal values than hex for m_entries * Update mxpalette.cpp * Push MxPalette progress - read comments in code. * improved MxPalette::operator==, will be 100% when MSVC feels like making it so * improved MxPalette::SetSkyColor, will be 100% when MSVC feels like making it so * improved MxPalette::Clone, will be 100% when MSVC feels like making it so * Fixes - reordered the functions in order of where they are in the hex because recmp.py sometimes kept saying it couldn't find the symbol (??) - clone returns a pointer, not a ref - worked a bit on setpalette/applysysentriestopalette * Match GetDefaultPalette a bit more * fix: MxPalette::GetDefaultPalette is now 100% matching * fix: MxPalette::ApplySystemEntriesToPalette is now 100% matching * tidy: rename `DC` var in GetDefaultPalette to `hdc` * fix: MxPalette::SetPalette is now functionally matching Not assembly matching yet because of MSVC weirdness. At some point it will probably start matching, because the structure seems to be accurate. * fix: MxPalette rgbquad ctor functionally matches Not quite ASM matching yet because of weird register allocation mismatches. * fix: I forgot to commit mxpalette.h... * tidy: use Mx* primitives instead of builtins * refactor: remove MxPalette::FromBitmapPalette * fix: call ApplySystemEntriesToPalette from MxPalette(const RGBQUAD *) * rename MxPalette::SetPalette to MxPalette::SetEntries * fix: I once again forgot to commit mxpalette.h... * feat: add/match MxPalette::Reset [0x100BF490] * fix: add MVideoManager() to mxomni header * refactor: change unk50 in MxVideoManager to LPDIRECTDRAW * feat: add/match MxPalette::CreateNativePalette [0x100BF000] * fix: MxPalette::SetSkyColor is 100% matching * Annotate MxPalette members' offsets * Annotate the global default aplette * use hex size * remove unnecessary variable offset listing * Update LEGO1/mxpalette.cpp --------- Co-authored-by: Anonymous Maarten Co-authored-by: Christian Semmler Co-authored-by: ktkaufman03 Co-authored-by: MattKC <34096995+itsmattkc@users.noreply.github.com> --- LEGO1/mxomni.h | 1 + LEGO1/mxpalette.cpp | 476 ++++++++++++++++++++++++++++++++++++++- LEGO1/mxpalette.h | 19 +- LEGO1/mxvideomanager.cpp | 2 +- LEGO1/mxvideomanager.h | 4 +- 5 files changed, 491 insertions(+), 11 deletions(-) diff --git a/LEGO1/mxomni.h b/LEGO1/mxomni.h index f3f1ee9a..b09d11ad 100644 --- a/LEGO1/mxomni.h +++ b/LEGO1/mxomni.h @@ -77,5 +77,6 @@ __declspec(dllexport) MxVariableTable * VariableTable(); __declspec(dllexport) MxMusicManager * MusicManager(); __declspec(dllexport) MxEventManager * EventManager(); __declspec(dllexport) MxNotificationManager * NotificationManager(); +MxVideoManager * MVideoManager(); #endif // MXOMNI_H diff --git a/LEGO1/mxpalette.cpp b/LEGO1/mxpalette.cpp index 546dddf9..7fb02f4f 100644 --- a/LEGO1/mxpalette.cpp +++ b/LEGO1/mxpalette.cpp @@ -1,4 +1,349 @@ #include "mxpalette.h" +#include "mxomni.h" + +// GLOBAL: LEGO1 0x10102188 0x400 +PALETTEENTRY g_defaultPaletteEntries[256] = +{ + { 0u, 0u, 0u, 0u }, + { 128u, 0u, 0u, 0u }, + { 0u, 128u, 0u, 0u }, + { 128u, 128u, 0u, 0u }, + { 0u, 0u, 128u, 0u }, + { 128u, 0u, 128u, 0u }, + { 0u, 128u, 128u, 0u }, + { 128u, 128u, 128u, 0u }, + { 192u, 220u, 192u, 0u }, + { 166u, 202u, 240u, 0u }, + { 255u, 255u, 255u, 0u }, + { 250u, 250u, 250u, 0u }, + { 239u, 239u, 239u, 0u }, + { 228u, 228u, 228u, 0u }, + { 217u, 217u, 217u, 0u }, + { 206u, 206u, 206u, 0u }, + { 195u, 195u, 195u, 0u }, + { 185u, 185u, 185u, 0u }, + { 174u, 174u, 174u, 0u }, + { 163u, 163u, 163u, 0u }, + { 152u, 152u, 152u, 0u }, + { 141u, 141u, 141u, 0u }, + { 130u, 130u, 130u, 0u }, + { 123u, 123u, 123u, 0u }, + { 115u, 115u, 115u, 0u }, + { 108u, 108u, 108u, 0u }, + { 101u, 101u, 101u, 0u }, + { 93u, 93u, 93u, 0u }, + { 86u, 86u, 86u, 0u }, + { 79u, 79u, 79u, 0u }, + { 71u, 71u, 71u, 0u }, + { 64u, 64u, 64u, 0u }, + { 54u, 54u, 54u, 0u }, + { 43u, 43u, 43u, 0u }, + { 33u, 33u, 33u, 0u }, + { 22u, 22u, 22u, 0u }, + { 12u, 12u, 12u, 0u }, + { 8u, 8u, 8u, 0u }, + { 4u, 4u, 4u, 0u }, + { 0u, 0u, 0u, 0u }, + { 225u, 218u, 217u, 0u }, + { 195u, 182u, 179u, 0u }, + { 165u, 145u, 141u, 0u }, + { 134u, 108u, 102u, 0u }, + { 104u, 72u, 64u, 0u }, + { 74u, 35u, 26u, 0u }, + { 59u, 28u, 21u, 0u }, + { 44u, 21u, 16u, 0u }, + { 30u, 14u, 10u, 0u }, + { 15u, 7u, 5u, 0u }, + { 250u, 231u, 232u, 0u }, + { 240u, 185u, 189u, 0u }, + { 233u, 154u, 160u, 0u }, + { 226u, 124u, 131u, 0u }, + { 219u, 93u, 102u, 0u }, + { 213u, 62u, 73u, 0u }, + { 203u, 18u, 32u, 0u }, + { 172u, 15u, 27u, 0u }, + { 159u, 14u, 25u, 0u }, + { 146u, 13u, 23u, 0u }, + { 133u, 12u, 21u, 0u }, + { 120u, 11u, 19u, 0u }, + { 107u, 10u, 17u, 0u }, + { 94u, 8u, 15u, 0u }, + { 81u, 7u, 13u, 0u }, + { 68u, 6u, 11u, 0u }, + { 55u, 5u, 9u, 0u }, + { 42u, 4u, 7u, 0u }, + { 29u, 3u, 5u, 0u }, + { 10u, 1u, 2u, 0u }, + { 227u, 236u, 242u, 0u }, + { 178u, 203u, 220u, 0u }, + { 145u, 181u, 205u, 0u }, + { 112u, 159u, 191u, 0u }, + { 79u, 137u, 176u, 0u }, + { 30u, 104u, 154u, 0u }, + { 0u, 84u, 140u, 0u }, + { 0u, 79u, 132u, 0u }, + { 0u, 72u, 119u, 0u }, + { 0u, 66u, 110u, 0u }, + { 0u, 61u, 101u, 0u }, + { 0u, 55u, 92u, 0u }, + { 0u, 47u, 78u, 0u }, + { 0u, 39u, 65u, 0u }, + { 0u, 34u, 56u, 0u }, + { 0u, 28u, 47u, 0u }, + { 0u, 23u, 38u, 0u }, + { 0u, 18u, 29u, 0u }, + { 0u, 12u, 20u, 0u }, + { 0u, 4u, 7u, 0u }, + { 230u, 242u, 234u, 0u }, + { 180u, 215u, 193u, 0u }, + { 147u, 198u, 166u, 0u }, + { 113u, 180u, 138u, 0u }, + { 80u, 162u, 111u, 0u }, + { 30u, 136u, 70u, 0u }, + { 0u, 120u, 45u, 0u }, + { 0u, 114u, 43u, 0u }, + { 0u, 102u, 38u, 0u }, + { 0u, 95u, 35u, 0u }, + { 0u, 83u, 31u, 0u }, + { 0u, 72u, 27u, 0u }, + { 0u, 63u, 24u, 0u }, + { 0u, 56u, 21u, 0u }, + { 0u, 48u, 18u, 0u }, + { 0u, 36u, 14u, 0u }, + { 0u, 25u, 9u, 0u }, + { 0u, 17u, 6u, 0u }, + { 0u, 9u, 3u, 0u }, + { 0u, 1u, 1u, 0u }, + { 254u, 244u, 220u, 0u }, + { 255u, 239u, 181u, 0u }, + { 255u, 231u, 156u, 0u }, + { 255u, 222u, 132u, 0u }, + { 255u, 222u, 115u, 0u }, + { 255u, 214u, 99u, 0u }, + { 255u, 206u, 66u, 0u }, + { 255u, 198u, 41u, 0u }, + { 255u, 185u, 0u, 0u }, + { 255u, 189u, 8u, 0u }, + { 247u, 181u, 0u, 0u }, + { 222u, 156u, 0u, 0u }, + { 189u, 140u, 0u, 0u }, + { 173u, 123u, 0u, 0u }, + { 148u, 107u, 0u, 0u }, + { 132u, 90u, 0u, 0u }, + { 107u, 74u, 0u, 0u }, + { 74u, 49u, 0u, 0u }, + { 57u, 41u, 0u, 0u }, + { 33u, 24u, 0u, 0u }, + { 117u, 52u, 87u, 0u }, + { 176u, 158u, 50u, 0u }, + { 122u, 165u, 29u, 0u }, + { 242u, 142u, 8u, 0u }, + { 164u, 43u, 36u, 0u }, + { 113u, 67u, 20u, 0u }, + { 255u, 0u, 255u, 0u }, + { 255u, 0u, 255u, 0u }, + { 255u, 0u, 255u, 0u }, + { 255u, 0u, 255u, 0u }, + { 255u, 0u, 255u, 0u }, + { 57u, 163u, 217u, 0u }, + { 255u, 255u, 255u, 0u }, + { 254u, 255u, 247u, 0u }, + { 253u, 253u, 239u, 0u }, + { 248u, 247u, 247u, 0u }, + { 248u, 247u, 231u, 0u }, + { 240u, 240u, 240u, 0u }, + { 239u, 239u, 218u, 0u }, + { 227u, 232u, 236u, 0u }, + { 224u, 221u, 209u, 0u }, + { 215u, 222u, 215u, 0u }, + { 213u, 214u, 215u, 0u }, + { 214u, 214u, 203u, 0u }, + { 255u, 219u, 57u, 0u }, + { 206u, 206u, 206u, 0u }, + { 206u, 206u, 198u, 0u }, + { 255u, 214u, 18u, 0u }, + { 207u, 203u, 186u, 0u }, + { 197u, 199u, 199u, 0u }, + { 255u, 206u, 0u, 0u }, + { 207u, 198u, 159u, 0u }, + { 247u, 204u, 0u, 0u }, + { 189u, 198u, 189u, 0u }, + { 189u, 189u, 189u, 0u }, + { 238u, 199u, 0u, 0u }, + { 189u, 189u, 181u, 0u }, + { 238u, 190u, 24u, 0u }, + { 181u, 189u, 184u, 0u }, + { 161u, 186u, 224u, 0u }, + { 181u, 181u, 181u, 0u }, + { 231u, 189u, 0u, 0u }, + { 173u, 182u, 173u, 0u }, + { 222u, 181u, 0u, 0u }, + { 173u, 173u, 173u, 0u }, + { 213u, 182u, 0u, 0u }, + { 172u, 173u, 160u, 0u }, + { 214u, 173u, 0u, 0u }, + { 165u, 165u, 165u, 0u }, + { 206u, 173u, 0u, 0u }, + { 160u, 168u, 151u, 0u }, + { 206u, 164u, 0u, 0u }, + { 198u, 165u, 0u, 0u }, + { 157u, 156u, 156u, 0u }, + { 134u, 156u, 200u, 0u }, + { 153u, 156u, 144u, 0u }, + { 142u, 156u, 161u, 0u }, + { 189u, 156u, 0u, 0u }, + { 148u, 148u, 148u, 0u }, + { 146u, 148u, 138u, 0u }, + { 133u, 143u, 161u, 0u }, + { 189u, 143u, 0u, 0u }, + { 140u, 140u, 140u, 0u }, + { 177u, 147u, 0u, 0u }, + { 131u, 140u, 136u, 0u }, + { 146u, 130u, 126u, 0u }, + { 170u, 137u, 0u, 0u }, + { 132u, 132u, 130u, 0u }, + { 123u, 125u, 125u, 0u }, + { 123u, 123u, 133u, 0u }, + { 153u, 126u, 0u, 0u }, + { 114u, 116u, 118u, 0u }, + { 110u, 112u, 108u, 0u }, + { 97u, 109u, 136u, 0u }, + { 127u, 108u, 6u, 0u }, + { 0u, 173u, 0u, 0u }, + { 100u, 99u, 101u, 0u }, + { 176u, 71u, 41u, 0u }, + { 36u, 142u, 33u, 0u }, + { 98u, 91u, 75u, 0u }, + { 80u, 88u, 104u, 0u }, + { 252u, 0u, 0u, 0u }, + { 78u, 71u, 73u, 0u }, + { 73u, 71u, 78u, 0u }, + { 62u, 63u, 61u, 0u }, + { 0u, 66u, 211u, 0u }, + { 99u, 51u, 14u, 0u }, + { 198u, 0u, 0u, 0u }, + { 189u, 0u, 0u, 0u }, + { 0u, 57u, 206u, 0u }, + { 181u, 0u, 0u, 0u }, + { 0u, 56u, 185u, 0u }, + { 173u, 0u, 0u, 0u }, + { 165u, 0u, 0u, 0u }, + { 49u, 49u, 49u, 0u }, + { 0u, 49u, 165u, 0u }, + { 156u, 0u, 0u, 0u }, + { 42u, 45u, 60u, 0u }, + { 148u, 0u, 0u, 0u }, + { 140u, 0u, 0u, 0u }, + { 41u, 41u, 41u, 0u }, + { 0u, 41u, 144u, 0u }, + { 132u, 0u, 0u, 0u }, + { 123u, 0u, 0u, 0u }, + { 7u, 35u, 114u, 0u }, + { 34u, 36u, 32u, 0u }, + { 115u, 0u, 0u, 0u }, + { 107u, 0u, 0u, 0u }, + { 90u, 0u, 0u, 0u }, + { 23u, 24u, 27u, 0u }, + { 74u, 0u, 0u, 0u }, + { 15u, 15u, 16u, 0u }, + { 49u, 0u, 0u, 0u }, + { 16u, 12u, 4u, 0u }, + { 7u, 8u, 8u, 0u }, + { 0u, 0u, 8u, 0u }, + { 255u, 251u, 240u, 0u }, + { 160u, 160u, 164u, 0u }, + { 128u, 128u, 128u, 0u }, + { 255u, 0u, 0u, 0u }, + { 0u, 255u, 0u, 0u }, + { 255u, 255u, 0u, 0u }, + { 0u, 0u, 255u, 0u }, + { 255u, 0u, 255u, 0u }, + { 0u, 255u, 255u, 0u }, + { 255u, 255u, 255u, 0u } +}; + + +// OFFSET: LEGO1 0x100bee30 +MxPalette::MxPalette() +{ + this->m_overrideSkyColor = FALSE; + this->m_palette = NULL; + GetDefaultPalette(this->m_entries); + this->m_skyColor = this->m_entries[141]; +} + +// OFFSET: LEGO1 0x100BEED0 +MxPalette::MxPalette(const RGBQUAD *p_colors) +{ + this->m_overrideSkyColor = FALSE; + this->m_palette = NULL; + ApplySystemEntriesToPalette(this->m_entries); + + for ( MxS32 i = 10; i < 246; i++ ) + { + this->m_entries[i].peRed = p_colors[i].rgbRed; + this->m_entries[i].peGreen = p_colors[i].rgbGreen; + this->m_entries[i].peBlue = p_colors[i].rgbBlue; + this->m_entries[i].peFlags = 0; + } + + this->m_skyColor = this->m_entries[141]; +} + +// OFFSET: LEGO1 100bef90 +MxPalette::~MxPalette() +{ + if (m_palette) { + m_palette->Release(); + } +} + +// OFFSET: LEGO1 0x100bf390 +void MxPalette::ApplySystemEntriesToPalette(LPPALETTEENTRY p_entries) +{ + HDC hdc; + + hdc = GetDC(0); + if ( (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) != 0 && GetDeviceCaps(hdc, SIZEPALETTE) == 256 ) + { + GetSystemPaletteEntries(hdc, 0, 10, p_entries); + GetSystemPaletteEntries(hdc, 246, 10, &p_entries[246]); + } + else + { + memcpy(p_entries, g_defaultPaletteEntries, sizeof(PALETTEENTRY) * 10); + memcpy(&p_entries[246], &g_defaultPaletteEntries[246], sizeof(PALETTEENTRY) * 10); + } + ReleaseDC(0, hdc); +} + +// OFFSET: LEGO1 0x100bf0b0 +MxPalette* MxPalette::Clone() +{ + MxPalette *result = new MxPalette; + this->GetEntries(result->m_entries); + result->m_overrideSkyColor = this->m_overrideSkyColor; + return result; +} + +// OFFSET: LEGO1 0x100bf420 +void MxPalette::GetDefaultPalette(LPPALETTEENTRY p_entries) +{ + HDC hdc; + + hdc = GetDC(0); + if ( (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) != 0 && GetDeviceCaps(hdc, SIZEPALETTE) == 256 ) + { + GetSystemPaletteEntries(hdc, 0, 256, p_entries); + memcpy(&p_entries[10], &g_defaultPaletteEntries[10], sizeof(PALETTEENTRY) * 236); + } + else + { + memcpy(p_entries, g_defaultPaletteEntries, sizeof(PALETTEENTRY) * 256); + } + + ReleaseDC(0, hdc); +} // OFFSET: LEGO1 0x100bf150 MxResult MxPalette::GetEntries(LPPALETTEENTRY p_entries) @@ -8,14 +353,137 @@ MxResult MxPalette::GetEntries(LPPALETTEENTRY p_entries) } // OFFSET: LEGO1 0x100bf340 -MxBool MxPalette::operator==(MxPalette &) +MxBool MxPalette::operator==(MxPalette &other) { - // TODO - return FALSE; + for (MxS32 i = 0; i < 256; i++) + { + if (this->m_entries[i].peRed != other.m_entries[i].peRed) + return FALSE; + if (this->m_entries[i].peGreen != other.m_entries[i].peGreen) + return FALSE; + if (this->m_entries[i].peBlue != other.m_entries[i].peBlue) + return FALSE; + } + return TRUE; } // OFFSET: LEGO1 0x100bf330 void MxPalette::Detach() { - // TODO + this->m_palette = NULL; +} + +// OFFSET: LEGO1 0x100bf170 +MxResult MxPalette::SetEntries(LPPALETTEENTRY p_entries) +{ + MxS32 i; + MxResult status = 0; + + if ( this->m_palette ) + { + for ( i = 0; i < 10; i++ ) + this->m_entries[i].peFlags = 0x80; + for ( i = 10; i < 136; i++ ) + { + this->m_entries[i].peFlags = 68; + this->m_entries[i].peRed = p_entries[i].peRed; + this->m_entries[i].peGreen = p_entries[i].peGreen; + this->m_entries[i].peBlue = p_entries[i].peBlue; + } + for ( i = 136; i < 140; i++ ) + { + this->m_entries[i].peFlags = 132; + this->m_entries[i].peRed = p_entries[i].peRed; + this->m_entries[i].peGreen = p_entries[i].peGreen; + this->m_entries[i].peBlue = p_entries[i].peBlue; + } + if ( !this->m_overrideSkyColor ) + { + this->m_entries[140].peFlags = 0x44; + this->m_entries[140].peRed = p_entries[140].peRed; + this->m_entries[140].peGreen = p_entries[140].peGreen; + this->m_entries[140].peBlue = p_entries[140].peBlue; + this->m_entries[141].peFlags = 0x84; + this->m_entries[141].peRed = p_entries[141].peRed; + this->m_entries[141].peGreen = p_entries[141].peGreen; + this->m_entries[141].peBlue = p_entries[141].peBlue; + } + + for ( i = 142; i < 246; i++ ) + { + this->m_entries[i].peFlags = 132; + this->m_entries[i].peRed = p_entries[i].peRed; + this->m_entries[i].peGreen = p_entries[i].peGreen; + this->m_entries[i].peBlue = p_entries[i].peBlue; + } + + for ( i = 246; i < 256; i++ ) + this->m_entries[i].peFlags = 0x80; + + if ( this->m_palette->SetEntries(0, 0, 256, this->m_entries) ) + status = -1; + } + + return status; +} + +// OFFSET: LEGO1 0x100bf2d0 +MxResult MxPalette::SetSkyColor(LPPALETTEENTRY p_sky_color) +{ + MxResult status = 0; + if ( this->m_palette != NULL ) + { + this->m_entries[141].peRed = p_sky_color->peRed; + this->m_entries[141].peGreen = p_sky_color->peGreen; + this->m_entries[141].peBlue = p_sky_color->peBlue; + this->m_skyColor = this->m_entries[141]; + if ( this->m_palette->SetEntries(0, 141, 1, &this->m_skyColor) ) + { + status = -1; + } + } + return status; +} + +// OFFSET: LEGO1 0x100BF490 +void MxPalette::Reset(MxBool p_ignoreSkyColor) +{ + if ( this->m_palette != NULL ) + { + GetDefaultPalette(this->m_entries); + if ( !p_ignoreSkyColor ) + { + this->m_entries[140] = this->m_entries[141] = this->m_skyColor; + } + SetEntries(this->m_entries); + this->m_palette->SetEntries(0, 0, 256, this->m_entries); + } +} + +// OFFSET: LEGO1 0x100BF000 +LPDIRECTDRAWPALETTE MxPalette::CreateNativePalette() +{ + MxS32 i; + if ( this->m_palette == NULL ) + { + for (i = 0; i < 10; i++) + this->m_entries[i].peFlags = 0x80; + for (i = 10; i < 136; i++) + this->m_entries[i].peFlags = 0x44; + for (i = 136; i < 140; i++) + this->m_entries[i].peFlags = 0x84; + this->m_entries[140].peFlags = 0x84; + this->m_entries[141].peFlags = 0x44; + for (i = 142; i < 246; i++) + this->m_entries[i].peFlags = 0x84; + for (i = 246; i < 256; i++) + this->m_entries[i].peFlags = 0x80; + + if (MVideoManager() && MVideoManager()->GetDirectDraw()) + { + MVideoManager()->GetDirectDraw()->CreatePalette(4, this->m_entries, &this->m_palette, NULL); + } + } + + return this->m_palette; } diff --git a/LEGO1/mxpalette.h b/LEGO1/mxpalette.h index 7f4a4299..b024330a 100644 --- a/LEGO1/mxpalette.h +++ b/LEGO1/mxpalette.h @@ -14,12 +14,23 @@ class MxPalette : public MxCore __declspec(dllexport) MxBool operator==(MxPalette &); __declspec(dllexport) void Detach(); - MxResult GetEntries(LPPALETTEENTRY p_entries); + MxPalette(); + MxPalette(const RGBQUAD *); + virtual ~MxPalette(); + void ApplySystemEntriesToPalette(LPPALETTEENTRY p_entries); + MxPalette* Clone(); + void GetDefaultPalette(LPPALETTEENTRY p_entries); + MxResult GetEntries(LPPALETTEENTRY p_entries); + MxResult SetEntries(LPPALETTEENTRY p_palette); + MxResult SetSkyColor(LPPALETTEENTRY p_sky_color); + void Reset(MxBool p_ignoreSkyColor); + LPDIRECTDRAWPALETTE CreateNativePalette(); private: - LPDIRECTDRAWPALETTE m_pDirectDrawPalette; - PALETTEENTRY m_entries[256]; - // there's a bit more here + LPDIRECTDRAWPALETTE m_palette; + PALETTEENTRY m_entries[256]; // 0xc + MxBool m_overrideSkyColor; // 0x40c + PALETTEENTRY m_skyColor; // 0x40d }; #endif // MXPALETTE_H diff --git a/LEGO1/mxvideomanager.cpp b/LEGO1/mxvideomanager.cpp index 543f4136..af4995ae 100644 --- a/LEGO1/mxvideomanager.cpp +++ b/LEGO1/mxvideomanager.cpp @@ -23,7 +23,7 @@ MxVideoManager::MxVideoManager() // OFFSET: LEGO1 0x100be320 int MxVideoManager::Init() { - this->m_unk50 = 0; + this->m_pDirectDraw = NULL; this->m_unk54 = NULL; this->m_unk58 = NULL; this->m_unk5c = 0; diff --git a/LEGO1/mxvideomanager.h b/LEGO1/mxvideomanager.h index f70bf06e..2061ec6b 100644 --- a/LEGO1/mxvideomanager.h +++ b/LEGO1/mxvideomanager.h @@ -21,10 +21,10 @@ class MxVideoManager : public MxUnknown100dc6b0 int Init(); inline MxVideoParam& GetVideoParam() { return this->m_videoParam; } - + inline LPDIRECTDRAW GetDirectDraw() { return this->m_pDirectDraw; } private: MxVideoParam m_videoParam; - int m_unk50; + LPDIRECTDRAW m_pDirectDraw; LPDIRECTDRAWSURFACE m_unk54; void* m_unk58; int m_unk5c; From f247e10b7e73c700e9a4e71fed1fa5cfe28ea486 Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Sat, 15 Jul 2023 23:13:34 -0700 Subject: [PATCH 3/8] reccmp.py improvements (#82) * Rather than using as a replacement for all offsets in a function, label the offsets as , , etc. Doing this will avoid false-positive 100% matches resulting from the same function being called in two times where a different on should have been called or vice versa. And the same for globals. I already encountered one case of this in the wild. * When a 100% match initially fails, try to make the functions match by swapping register allocations. This makes it possible to get a 100% match where the generated machine code differs only in register allocation. * Only apply the above when it is possible to reach a 100% match in that way. Otherwise show the developer the unadultrated diff to avoid complicating decompilation. * In the result listing, show the functions which are "effective matches" in this way as "100%*" instead of "100%". --- tools/reccmp/reccmp.py | 124 ++++++++++++++++++++++++++++++++----- tools/reccmp/template.html | 4 +- 2 files changed, 113 insertions(+), 15 deletions(-) diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index 226be15d..69779872 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -10,6 +10,7 @@ import os import sys import colorama +import re parser = argparse.ArgumentParser(allow_abbrev=False, description='Recompilation Compare: compare an original EXE with a recompiled EXE + PDB.') @@ -248,9 +249,21 @@ def get_recompiled_address(self, filename, line): md = Cs(CS_ARCH_X86, CS_MODE_32) -def sanitize(file, mnemonic, op_str): - offsetplaceholder = '' +class OffsetPlaceholderGenerator: + def __init__(self): + self.counter = 0 + self.replacements = {} + def get(self, addr): + if addr in self.replacements: + return self.replacements[addr] + else: + self.counter += 1 + replacement = '' % self.counter + self.replacements[addr] = replacement + return replacement + +def sanitize(file, placeholderGenerator, mnemonic, op_str): op_str_is_number = False try: int(op_str, 16) @@ -262,7 +275,7 @@ def sanitize(file, mnemonic, op_str): # Filter out "calls" because the offsets we're not currently trying to # match offsets. As long as there's a call in the right place, it's # probably accurate. - op_str = offsetplaceholder + op_str = placeholderGenerator.get(int(op_str, 16)) else: def filter_out_ptr(ptype, op_str): try: @@ -273,7 +286,7 @@ def filter_out_ptr(ptype, op_str): # This will throw ValueError if not hex inttest = int(op_str[start:end], 16) - return op_str[0:start] + offsetplaceholder + op_str[end:] + return op_str[0:start] + placeholderGenerator.get(inttest) + op_str[end:] except ValueError: return op_str @@ -288,7 +301,7 @@ def filter_out_ptr(ptype, op_str): try: inttest = int(word, 16) if inttest >= file.imagebase + file.textvirt: - words[i] = offsetplaceholder + words[i] = placeholderGenerator.get(inttest) except ValueError: pass op_str = ' '.join(words) @@ -298,18 +311,76 @@ def filter_out_ptr(ptype, op_str): def parse_asm(file, addr, size): asm = [] data = file.read(addr, size) + placeholderGenerator = OffsetPlaceholderGenerator() for i in md.disasm(data, 0): # Use heuristics to disregard some differences that aren't representative # of the accuracy of a function (e.g. global offsets) - mnemonic, op_str = sanitize(file, i.mnemonic, i.op_str) + mnemonic, op_str = sanitize(file, placeholderGenerator, i.mnemonic, i.op_str) if op_str is None: asm.append(mnemonic) else: asm.append("%s %s" % (mnemonic, op_str)) return asm +REGISTER_LIST = set([ + 'eax', 'ebx', 'ecx', 'edx', 'edi', 'esi', 'ebp', 'esp', + 'ax', 'bx', 'cx', 'dx', 'di', 'si', 'bp', 'sp', +]) +WORDS = re.compile(r'\w+') + +def get_registers(line: str): + to_replace = [] + # use words regex to find all matching positions: + for match in WORDS.finditer(line): + reg = match.group(0) + if reg in REGISTER_LIST: + to_replace.append((reg, match.start())) + return to_replace + +def replace_register(lines: list[str], start_line: int, reg: str, replacement: str): + for i in range(start_line, len(lines)): + lines[i] = lines[i].replace(reg, replacement) + +# Is it possible to make new_asm the same as original_asm by swapping registers? +def can_resolve_register_differences(original_asm, new_asm): + # Swapping ain't gonna help if the lengths are different + if len(original_asm) != len(new_asm): + return False + + # Make copies so we don't modify the original + original_asm = original_asm.copy() + new_asm = new_asm.copy() + + # Look for the mismatching lines + for i in range(len(original_asm)): + new_line = new_asm[i] + original_line = original_asm[i] + if new_line != original_line: + # Find all the registers to replace + to_replace = get_registers(original_line) + + for j in range(len(to_replace)): + (reg, reg_index) = to_replace[j] + replacing_reg = new_line[reg_index:reg_index + len(reg)] + if replacing_reg in REGISTER_LIST: + if replacing_reg != reg: + # Do a three-way swap replacing in all the subsequent lines + temp_reg = "&" * len(reg) + replace_register(new_asm, i, replacing_reg, temp_reg) + replace_register(new_asm, i, reg, replacing_reg) + replace_register(new_asm, i, temp_reg, reg) + else: + # No replacement to do, different code, bail out + return False + # Check if the lines are now the same + for i in range(len(original_asm)): + if new_asm[i] != original_asm[i]: + return False + return True + function_count = 0 total_accuracy = 0 +total_effective_accuracy = 0 htmlinsert = [] # Generate basename of original file, used in locating OFFSET lines @@ -356,24 +427,41 @@ def parse_asm(file, addr, size): if not recinfo: continue + # The effective_ratio is the ratio when ignoring differing register + # allocation vs the ratio is the true ratio. + ratio = 0.0 + effective_ratio = 0.0 if recinfo.size: origasm = parse_asm(origfile, addr + recinfo.start, recinfo.size) recompasm = parse_asm(recompfile, recinfo.addr + recinfo.start, recinfo.size) diff = difflib.SequenceMatcher(None, origasm, recompasm) ratio = diff.ratio() + effective_ratio = ratio + + if ratio != 1.0: + # Check whether we can resolve register swaps which are actually + # perfect matches modulo compiler entropy. + if can_resolve_register_differences(origasm, recompasm): + effective_ratio = 1.0 else: ratio = 0 - percenttext = "%.2f%%" % (ratio * 100) + percenttext = "%.2f%%" % (effective_ratio * 100) if not plain: - if ratio == 1.0: + if effective_ratio == 1.0: percenttext = colorama.Fore.GREEN + percenttext + colorama.Style.RESET_ALL - elif ratio > 0.8: + elif effective_ratio > 0.8: percenttext = colorama.Fore.YELLOW + percenttext + colorama.Style.RESET_ALL else: percenttext = colorama.Fore.RED + percenttext + colorama.Style.RESET_ALL + if effective_ratio == 1.0 and ratio != 1.0: + if plain: + percenttext += "*" + else: + percenttext += colorama.Fore.RED + "*" + colorama.Style.RESET_ALL + if not verbose: if args.print_rec_addr: addrs = '%s / %s' % (hex(addr), hex(recinfo.addr)) @@ -383,14 +471,21 @@ def parse_asm(file, addr, size): function_count += 1 total_accuracy += ratio + total_effective_accuracy += effective_ratio if recinfo.size: udiff = difflib.unified_diff(origasm, recompasm, n=10) # If verbose, print the diff for that funciton to the output if verbose: - if ratio == 1.0: - print("%s: %s 100%% match.\n\nOK!" % (hex(addr), recinfo.name)) + if effective_ratio == 1.0: + ok_text = "OK!" if plain else (colorama.Fore.GREEN + "✨ OK! ✨" + colorama.Style.RESET_ALL) + if ratio == 1.0: + print("%s: %s 100%% match.\n\n%s\n\n" % + (hex(addr), recinfo.name, ok_text)) + else: + print("%s: %s Effective 100%% match. (Differs in register allocation only)\n\n%s (still differs in register allocation)\n\n" % + (hex(addr), recinfo.name, ok_text)) else: for line in udiff: if line.startswith("++") or line.startswith("@@") or line.startswith("--"): @@ -416,7 +511,7 @@ def parse_asm(file, addr, size): # If html, record the diffs to an HTML file if html: escaped = '\\n'.join(udiff).replace('"', '\\"').replace('\n', '\\n').replace('<', '<').replace('>', '>') - htmlinsert.append('{address: "%s", name: "%s", matching: %s, diff: "%s"}' % (hex(addr), recinfo.name, str(ratio), escaped)) + htmlinsert.append('{address: "%s", name: "%s", matching: %s, diff: "%s"}' % (hex(addr), recinfo.name, str(effective_ratio), escaped)) except UnicodeDecodeError: break @@ -496,7 +591,8 @@ def gen_svg(svg, name, icon, implemented_funcs, total_funcs, raw_accuracy): function_count = int(args.total) if function_count > 0: - print('\nTotal accuracy %.2f%% across %i functions' % (total_accuracy / function_count * 100, function_count)) + print('\nTotal effective accuracy %.2f%% across %i functions (%.2f%% actual accuracy)' % + (total_effective_accuracy / function_count * 100, function_count, total_accuracy / function_count * 100)) if svg: - gen_svg(svg, os.path.basename(original), args.svg_icon, implemented_funcs, function_count, total_accuracy) + gen_svg(svg, os.path.basename(original), args.svg_icon, implemented_funcs, function_count, total_effective_accuracy) diff --git a/tools/reccmp/template.html b/tools/reccmp/template.html index 9b03e4ec..f3087688 100644 --- a/tools/reccmp/template.html +++ b/tools/reccmp/template.html @@ -221,7 +221,9 @@ addrCel.innerHTML = addrCel.dataset.value = element.address; nameCel.innerHTML = nameCel.dataset.value = element.name; - matchCel.innerHTML = (element.matching * 100).toFixed(2) + '%'; + + var effectiveNote = (element.matching == 1 && element.diff != '') ? '*' : ''; + matchCel.innerHTML = (element.matching * 100).toFixed(2) + '%' + effectiveNote; matchCel.dataset.value = element.matching; row.classList.add('funcrow'); From 2ffe227d82916ae37b4916cbd8a714f4ef627f78 Mon Sep 17 00:00:00 2001 From: MattKC <34096995+itsmattkc@users.noreply.github.com> Date: Sat, 15 Jul 2023 23:18:21 -0700 Subject: [PATCH 4/8] Add SmartHeap (#83) * add smartheap * cmake: bump even further * this seemed to be necessary but now it isn't? ok * cmake: force include smrtheap.hpp Co-authored-by: Anonymous Maarten * cmake: force include smrtheap.hpp 2 Co-authored-by: Anonymous Maarten * remove compiler defs - unnecessary if force-including anyway * cmake: use interface for cleaner code --------- Co-authored-by: Anonymous Maarten --- .github/workflows/build.yml | 2 +- 3rdparty/smartheap/SHLW32MT.LIB | Bin 0 -> 106886 bytes 3rdparty/smartheap/SHMALLOC.H | 63 +++ 3rdparty/smartheap/SHMFC4M.LIB | Bin 0 -> 3206 bytes 3rdparty/smartheap/SMRTHEAP.H | 656 ++++++++++++++++++++++++++++++++ 3rdparty/smartheap/SMRTHEAP.HPP | 159 ++++++++ CMakeLists.txt | 17 +- 7 files changed, 895 insertions(+), 2 deletions(-) create mode 100644 3rdparty/smartheap/SHLW32MT.LIB create mode 100644 3rdparty/smartheap/SHMALLOC.H create mode 100644 3rdparty/smartheap/SHMFC4M.LIB create mode 100644 3rdparty/smartheap/SMRTHEAP.H create mode 100644 3rdparty/smartheap/SMRTHEAP.HPP diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index af1dac3b..c846a9f9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,7 +46,7 @@ jobs: uses: jwlawson/actions-setup-cmake@v1.13 with: # Use minimum supported version - cmake-version: '3.0.x' + cmake-version: '3.13.x' - name: Build shell: cmd diff --git a/3rdparty/smartheap/SHLW32MT.LIB b/3rdparty/smartheap/SHLW32MT.LIB new file mode 100644 index 0000000000000000000000000000000000000000..732aedf81e8fa402cb197f1a72a1966e3705d432 GIT binary patch literal 106886 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 aOWw*zl9QwVgJhh~`Y|eNCZ)L5W%4KBGcqOs literal 0 HcmV?d00001 diff --git a/3rdparty/smartheap/SMRTHEAP.H b/3rdparty/smartheap/SMRTHEAP.H new file mode 100644 index 00000000..aab58b84 --- /dev/null +++ b/3rdparty/smartheap/SMRTHEAP.H @@ -0,0 +1,656 @@ +/* smrtheap.h -- SmartHeap (tm) public C header file + * Professional Memory Management Library + * + * Copyright (C) 1991-1997 by Arthur D. Applegate. All Rights Reserved. + * All Rights Reserved. + * + * No part of this source code may be copied, modified or reproduced + * in any form without retaining the above copyright notice. + * This source code, or source code derived from it, may not be redistributed + * without express written permission of the author. + * + */ + +#if !defined(_SMARTHEAP_H) +#define _SMARTHEAP_H + +#include +#include + +#if !defined(macintosh) && !defined(THINK_C) && !defined(__MWERKS__) \ + && !defined(SHANSI) && UINT_MAX == 0xFFFFu \ + && (defined(_Windows) || defined(_WINDOWS) || defined(__WINDOWS__)) + #define MEM_WIN16 +#endif + +#if (UINT_MAX == 0xFFFFu) && (defined(MEM_WIN16) \ + || defined(MSDOS) || defined(__MSDOS__) || defined(__DOS__)) + /* 16-bit X86 */ + #if defined(SYS_DLL) + #if defined(_MSC_VER) && _MSC_VER <= 600 + #define MEM_ENTRY _export _loadds far pascal + #else + #define MEM_ENTRY _export far pascal + #endif + #else + #define MEM_ENTRY far pascal + #endif + #ifdef __WATCOMC__ + #define MEM_ENTRY_ANSI __far + #else + #define MEM_ENTRY_ANSI far cdecl + #endif + #define MEM_FAR far + #if defined(MEM_WIN16) + #define MEM_ENTRY2 _export far pascal + #elif defined(DOS16M) || defined(DOSX286) + #define MEM_ENTRY2 _export _loadds far pascal + #endif + +#else /* not 16-bit X86 */ + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) \ + || defined(__WIN32__) || defined(__NT__) + #define MEM_WIN32 + #if defined(_MSC_VER) + #if defined(_SHI_Pool) && defined(SYS_DLL) + #define MEM_ENTRY1 __declspec(dllexport) + #define MEM_ENTRY4 __declspec(dllexport) extern + #elif !defined(_SHI_Pool) && (defined(MEM_DEBUG) || defined(MEM_DLL)) + #define MEM_ENTRY1 __declspec(dllimport) + #if defined(_M_IX86) || defined(_X86_) + #define MemDefaultPool shi_MemDefaultPool + #define MEM_ENTRY4 __declspec(dllimport) + #endif + #endif + #endif + #if !defined(_MSC_VER) || defined(_M_IX86) || defined(_X86_) + #define MEM_ENTRY __stdcall + #else + #define MEM_ENTRY __cdecl /* for NT/RISC */ + #endif + #ifndef __WATCOMC__ + #define MEM_ENTRY_ANSI __cdecl + #endif + +#elif defined(__OS2__) + #if defined(__BORLANDC__) || defined(__WATCOMC__) + #if defined(SYS_DLL) + #define MEM_ENTRY __export __syscall + #else + #define MEM_ENTRY __syscall + #endif /* SYS_DLL */ + #ifdef __BORLANDC__ + #define MEM_ENTRY_ANSI __stdcall + #endif + #elif defined(__IBMC__) || defined(__IBMCPP__) + #if defined(SYS_DLL) && 0 + #define MEM_ENTRY _Export _System + #else + #define MEM_ENTRY _System + #endif + #define MEM_ENTRY_ANSI _Optlink + #define MEM_ENTRY3 MEM_ENTRY + #define MEM_CALLBACK MEM_ENTRY3 + #define MEM_ENTRY2 + #endif +#endif /* __OS2__ */ + +#if defined(__WATCOMC__) && defined(__SW_3S) + /* Watcom stack calling convention */ +#ifndef __OS2__ +#ifdef __WINDOWS_386__ + #pragma aux syscall "*_" parm routine [eax ebx ecx edx fs gs] modify [eax]; +#else + #pragma aux syscall "*_" parm routine [eax ebx ecx edx] modify [eax]; +#endif +#ifndef MEM_ENTRY + #define MEM_ENTRY __syscall +#endif /* MEM_ENTRY */ +#endif +#endif /* Watcom stack calling convention */ + +#endif /* end of system-specific declarations */ + +#ifndef MEM_ENTRY + #define MEM_ENTRY +#endif +#ifndef MEM_ENTRY1 + #define MEM_ENTRY1 +#endif +#ifndef MEM_ENTRY2 + #define MEM_ENTRY2 MEM_ENTRY +#endif +#ifndef MEM_ENTRY3 + #define MEM_ENTRY3 +#endif +#ifndef MEM_ENTRY4 + #define MEM_ENTRY4 extern +#endif +#ifndef MEM_CALLBACK +#define MEM_CALLBACK MEM_ENTRY2 +#endif +#ifndef MEM_ENTRY_ANSI + #define MEM_ENTRY_ANSI +#endif +#ifndef MEM_FAR + #define MEM_FAR +#endif + +#ifdef applec +/* Macintosh: Apple MPW C/C++ passes char/short parms as longs (4 bytes), + * whereas Symantec C/C++ for MPW passes these as words (2 bytes); + * therefore, canonicalize all integer parms as 'int' for this platform. + */ + #define MEM_USHORT unsigned + #define MEM_UCHAR unsigned +#else + #define MEM_USHORT unsigned short + #define MEM_UCHAR unsigned char +#endif /* applec */ + +#ifdef MEM_DEBUG +#include "heapagnt.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*** Types ***/ + +#ifndef MEM_BOOL_DEFINED +#define MEM_BOOL_DEFINED +typedef int MEM_BOOL; +#endif + +/* Version Masks */ +typedef unsigned MEM_VERSION; +#define MEM_MAJOR_VERSION(v) (((v) & 0xF000u) >> 12) +#define MEM_MINOR_VERSION(v) (((v) & 0x0F00u) >> 8) +#define MEM_UPDATE_VERSION(v) ((v) & 0x00FFu) + +/* Note: these types are struct's rather than integral types to facilitate + * compile-time type-checking. MEM_POOL and MEM_HANDLE should be regarded + * as black boxes, and treated just like handles. + * You should not have any type casts to or from MEM_POOL or MEM_HANDLE; + * nor should you dereference variables of type MEM_POOL or MEM_HANDLE + * (unless you are using SmartHeap to replace NewHandle on the Mac, and + * you have existing code that dereferences handles). + */ +#ifndef MEM_POOL_DEFINED +#define MEM_POOL_DEFINED +#ifdef _SHI_Pool + typedef struct _SHI_Pool MEM_FAR *MEM_POOL; + typedef struct _SHI_MovHandle MEM_FAR *MEM_HANDLE; +#else + #ifdef THINK_C + typedef void *MEM_POOL; + typedef void **MEM_HANDLE; + #else + typedef struct _SHI_Pool { int reserved; } MEM_FAR *MEM_POOL; + typedef struct _SHI_MovHandle { int reserved; } MEM_FAR *MEM_HANDLE; + #endif +#endif +#endif /* MEM_POOL_DEFINED */ + + +#if !defined(MEM_DEBUG) || !(defined(MEM_WIN16) || defined(MEM_WIN32)) +#define SHI_MAJOR_VERSION 3 +#define SHI_MINOR_VERSION 3 +#define SHI_UPDATE_LEVEL 0 +#endif /* !WINDOWS */ + +#ifndef MEM_DEBUG + +/* Error codes: errorCode field of MEM_ERROR_INFO */ +#ifndef MEM_ERROR_CODE_DEFINED +#define MEM_ERROR_CODE_DEFINED +typedef enum +{ + MEM_NO_ERROR=0, + MEM_INTERNAL_ERROR, + MEM_OUT_OF_MEMORY, + MEM_BLOCK_TOO_BIG, + MEM_ALLOC_ZERO, + MEM_RESIZE_FAILED, + MEM_LOCK_ERROR, + MEM_EXCEEDED_CEILING, + MEM_TOO_MANY_PAGES, + MEM_TOO_MANY_TASKS, + MEM_BAD_MEM_POOL, + MEM_BAD_BLOCK, + MEM_BAD_FREE_BLOCK, + MEM_BAD_HANDLE, + MEM_BAD_POINTER, + MEM_WRONG_TASK, + MEM_NOT_FIXED_SIZE, + MEM_BAD_FLAGS, + MEM_ERROR_CODE_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_ERROR_CODE; +#endif /* MEM_ERROR_CODE_DEFINED */ + + +/* ### we should have packing pragma around these structure decls in case + * ### user is compiling with non-default packing directive (only needed + * ### if user is packing more strictly than native int size *and* if + * ### native int size is != native long and ptr sizes) + */ + +/* Error info, passed to error-handling callback routine */ +#ifndef MEM_ERROR_INFO_DEFINED +#define MEM_ERROR_INFO_DEFINED +typedef struct _MEM_ERROR_INFO +{ + MEM_ERROR_CODE errorCode; /* error code identifying type of error */ + MEM_POOL pool; /* pool in which error occurred, if known */ +} MEM_ERROR_INFO; + +/* Error handling callback function */ +typedef MEM_BOOL (MEM_ENTRY2 * MEM_ENTRY3 MEM_ERROR_FN) + (MEM_ERROR_INFO MEM_FAR *); + +#endif /* MEM_ERROR_INFO_DEFINED */ + +#endif /* MEM_DEBUG */ + + +#ifndef MEM_BLOCK_TYPE_DEFINED +#define MEM_BLOCK_TYPE_DEFINED +/* Block Type: field of MEM_POOL_ENTRY, field of MEM_POOL_INFO, + * parameter to MemPoolPreAllocate + */ +typedef enum +{ + MEM_FS_BLOCK = 0x0001u, + MEM_VAR_MOVEABLE_BLOCK = 0x0002u, + MEM_VAR_FIXED_BLOCK = 0x0004u, + MEM_EXTERNAL_BLOCK = 0x0008u, + MEM_BLOCK_TYPE_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_BLOCK_TYPE; +#endif /* MEM_BLOCK_TYPE_DEFINED */ + +#ifndef MEM_POOL_ENTRY_DEFINED +#define MEM_POOL_ENTRY_DEFINED +/* Pool Entry: parameter to MemPoolWalk */ +typedef struct +{ + void MEM_FAR *entry; + MEM_POOL pool; + MEM_BLOCK_TYPE type; + MEM_BOOL isInUse; + unsigned long size; + MEM_HANDLE handle; + unsigned lockCount; + void MEM_FAR *reserved_ptr; +} MEM_POOL_ENTRY; +#endif /* MEM_POOL_ENTRY_DEFINED */ + +#ifndef MEM_POOL_STATUS_DEFINED +#define MEM_POOL_STATUS_DEFINED +/* Pool Status: returned by MemPoolWalk, MemPoolFirst, MemPoolNext */ +typedef enum +{ + MEM_POOL_OK = 1, + MEM_POOL_CORRUPT = -1, + MEM_POOL_CORRUPT_FATAL = -2, + MEM_POOL_END = 0, + MEM_POOL_STATUS_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_POOL_STATUS; +#endif /* MEM_POOL_STATUS_DEFINED */ + +#ifndef MEM_POINTER_STATUS_DEFINED +#define MEM_POINTER_STATUS_DEFINED +/* Pointer Status: returned by MemCheckPtr */ +typedef enum +{ + MEM_POINTER_OK = 1, + MEM_POINTER_WILD = 0, + MEM_POINTER_FREE = -1, + MEM_POINTER_STATUS_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_POINTER_STATUS; +#endif /* MEM_POINTER_STATUS_DEFINED */ + +/* Pool Info: parameter to MemPoolInfo, MemPoolFirst, MemPoolNext */ +typedef struct +{ + MEM_POOL pool; + MEM_BLOCK_TYPE type; /* disjunctive combination of block type flags */ + unsigned short blockSizeFS; + unsigned short smallBlockSize; + unsigned pageSize; + unsigned long floor; + unsigned long ceiling; + unsigned flags; + MEM_ERROR_FN errorFn; +} MEM_POOL_INFO; + +/* Flags passed to MemAlloc, MemAllocPtr, MemReAlloc, MemReAllocPtr */ +#define MEM_FIXED 0x0000u /* fixed handle-based block */ +#define MEM_ZEROINIT 0x0001u /* == TRUE for SH 1.5 compatibility */ +#define MEM_MOVEABLE 0x0002u /* moveable handle-based block */ +#define MEM_RESIZEABLE 0x0004u /* reserve space above block */ +#define MEM_RESIZE_IN_PLACE 0x0008u /* do not move block (realloc) */ +#define MEM_NOGROW 0x0010u /* do not grow heap to satisfy request */ +#define MEM_NOEXTERNAL 0x0020u /* reserved for internal use */ +#define MEM_NOCOMPACT 0x0040u /* do not compact to satisfy request */ +#define MEM_NO_SERIALIZE 0x0080u /* do not serialize this request */ +#define MEM_HANDLEBASED 0x4000u /* for internal use */ +#define MEM_RESERVED 0x8000u /* for internal use */ + +#define MEM_UNLOCK_FAILED USHRT_MAX + +/* Flags passed to MemPoolInit, MemPoolInitFS */ +#ifndef MEM_POOL_SHARED +#define MEM_POOL_SHARED 0x0001u /* == TRUE for SH 1.5 compatibility */ +#define MEM_POOL_SERIALIZE 0x0002u /* pool used in more than one thread */ +#define MEM_POOL_VIRTUAL_LOCK 0x0004u /* pool is locked in physical memory */ +#define MEM_POOL_ZEROINIT 0x0008u /* malloc/new from pool zero-inits */ +#define MEM_POOL_REGION 0x0010u /* store pool in user-supplied region*/ +#define MEM_POOL_DEFAULT 0x8000u /* pool with default characteristics */ +#endif /* MEM_POOL_SHARED */ + +MEM_ENTRY4 MEM_POOL MemDefaultPool; + +/* Default memory pool for C malloc, C++ new (for backwards compatibility) */ +#define MEM_DEFAULT_POOL MemDefaultPool + +/* define and initialize these variables at file scope to change defaults */ +extern unsigned short MemDefaultPoolBlockSizeFS; +extern unsigned MemDefaultPoolPageSize; +extern unsigned MemDefaultPoolFlags; + +/* define SmartHeap_malloc at file scope if you + * are intentionally _NOT_ linking in the SmartHeap malloc definition + * ditto for SmartHeap operator new, and fmalloc et al. + */ +extern int SmartHeap_malloc; +extern int SmartHeap_far_malloc; +extern int SmartHeap_new; + +#define MEM_ERROR_RET ULONG_MAX + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !defined(_SMARTHEAP_H) */ + + +/*** Function Prototypes ***/ + +#ifndef _SMARTHEAP_PROT +#define _SMARTHEAP_PROT + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _shAPI + #if defined(MEM_DEBUG) && !defined(SHI_NO_MEM_DEBUG) + #define _shAPI(ret, name) MEM_ENTRY1 ret MEM_ENTRY _dbg ## name + #else + #define _shAPI(ret, name) MEM_ENTRY1 ret MEM_ENTRY name + #endif +#endif + +#ifndef _dbgARGS + #if defined(MEM_DEBUG) && !defined(SHI_NO_MEM_DEBUG) + #define _dbgARGS1 const char MEM_FAR *, int + #define _dbgARGS , _dbgARGS1 + #else + #define _dbgARGS1 void + #define _dbgARGS + #endif +#endif + + +/**** HOW TO READ SmartHeap PROTOTYPES **** + * prototypes below have the follow syntax in order to support both debug + * and non-debug APIs with single-source: + * + * _shiAPI(, )([] _dbgARGS); + * + * the above translates to a C prototype as follows: + * + * ([]); + */ + +/* Library Version */ +MEM_ENTRY1 MEM_VERSION MEM_ENTRY MemVersion(void); + +/* Library Registration */ +_shAPI(MEM_BOOL, MemRegisterTask)(_dbgARGS1); +_shAPI(MEM_BOOL, MemUnregisterTask)(_dbgARGS1); + +/* Memory Pool Functions */ +_shAPI(MEM_POOL, MemPoolInit)(unsigned _dbgARGS); +_shAPI(MEM_POOL, MemPoolInitFS)(MEM_USHORT, unsigned long, + unsigned _dbgARGS); +_shAPI(MEM_POOL, MemPoolInitRegion)(void MEM_FAR *, + unsigned long size, unsigned _dbgARGS); +_shAPI(MEM_POOL, MemPoolInitNamedShared)(const char MEM_FAR *, + unsigned long size,unsigned _dbgARGS); +_shAPI(MEM_POOL, MemPoolInitNamedSharedEx)(void MEM_FAR *addr, + unsigned pidCount, unsigned long MEM_FAR *pids, void MEM_FAR *security, + const char MEM_FAR *name, unsigned long size, unsigned flags _dbgARGS); +_shAPI(MEM_POOL, MemPoolAttachShared)(MEM_POOL, const char MEM_FAR * _dbgARGS); +_shAPI(MEM_BOOL, MemPoolFree)(MEM_POOL _dbgARGS); +MEM_POOL MEM_ENTRY MemInitDefaultPool(void); +MEM_BOOL MEM_ENTRY MemFreeDefaultPool(void); +_shAPI(unsigned, MemPoolSetPageSize)(MEM_POOL, unsigned _dbgARGS); +_shAPI(MEM_BOOL, MemPoolSetBlockSizeFS)(MEM_POOL, MEM_USHORT _dbgARGS); +_shAPI(MEM_BOOL, MemPoolSetSmallBlockSize)(MEM_POOL, MEM_USHORT _dbgARGS); +_shAPI(unsigned long, MemPoolSetFloor)(MEM_POOL, unsigned long _dbgARGS); +_shAPI(unsigned long, MemPoolSetCeiling)(MEM_POOL, unsigned long _dbgARGS); +_shAPI(unsigned long, MemPoolPreAllocate)(MEM_POOL, unsigned long, + MEM_BLOCK_TYPE _dbgARGS); +_shAPI(unsigned long, MemPoolPreAllocateHandles)(MEM_POOL, + unsigned long _dbgARGS); +_shAPI(unsigned long, MemPoolShrink)(MEM_POOL _dbgARGS); +_shAPI(unsigned long, MemPoolSize)(MEM_POOL _dbgARGS); +_shAPI(unsigned long, MemPoolCount)(MEM_POOL _dbgARGS); +_shAPI(MEM_BOOL, MemPoolInfo)(MEM_POOL, void MEM_FAR *, + MEM_POOL_INFO MEM_FAR* _dbgARGS); +_shAPI(MEM_POOL_STATUS, MemPoolFirst)(MEM_POOL_INFO MEM_FAR *, + MEM_BOOL _dbgARGS); +_shAPI(MEM_POOL_STATUS,MemPoolNext)(MEM_POOL_INFO MEM_FAR*,MEM_BOOL _dbgARGS); +_shAPI(MEM_POOL_STATUS,MemPoolWalk)(MEM_POOL,MEM_POOL_ENTRY MEM_FAR*_dbgARGS); +_shAPI(MEM_BOOL, MemPoolCheck)(MEM_POOL _dbgARGS); +_shAPI(MEM_BOOL, MemPoolLock)(MEM_POOL _dbgARGS); +_shAPI(MEM_BOOL, MemPoolUnlock)(MEM_POOL _dbgARGS); + +/* Handle-based API for moveable memory within heap. */ +_shAPI(MEM_HANDLE, MemAlloc)(MEM_POOL, unsigned, unsigned long _dbgARGS); +_shAPI(MEM_HANDLE, MemReAlloc)(MEM_HANDLE,unsigned long,unsigned _dbgARGS); +_shAPI(MEM_BOOL, MemFree)(MEM_HANDLE _dbgARGS); +_shAPI(void MEM_FAR *, MemLock)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned, MemUnlock)(MEM_HANDLE _dbgARGS); +_shAPI(void MEM_FAR *, MemFix)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned, MemUnfix)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned, MemLockCount)(MEM_HANDLE _dbgARGS); +#ifndef MemFlags +#define MemFlags(mem) MemLockCount(mem) +#endif +_shAPI(MEM_BOOL, MemIsMoveable)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned long, MemSize)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned long, MemSizeRequested)(MEM_HANDLE _dbgARGS); +_shAPI(MEM_HANDLE, MemHandle)(void MEM_FAR * _dbgARGS); +#ifndef MEM_REFERENCE + #ifdef MEM_DEBUG + MEM_ENTRY1 void MEM_FAR * MEM_ENTRY _dbgMemReference(MEM_HANDLE, + const char MEM_FAR *, int); + #define MEM_REFERENCE(handle) \ + _dbgMemReference(handle, __FILE__, __LINE__) + #else + #define MEM_REFERENCE(handle) (*(void MEM_FAR * MEM_FAR *)handle) + #endif +#endif + +/* General Heap Allocator (returns direct pointer to memory) */ +_shAPI(void MEM_FAR*,MemAllocPtr)(MEM_POOL,unsigned long,unsigned _dbgARGS); +_shAPI(void MEM_FAR *, MemReAllocPtr)(void MEM_FAR *, unsigned long, + unsigned _dbgARGS); +_shAPI(MEM_BOOL, MemFreePtr)(void MEM_FAR * _dbgARGS); +_shAPI(unsigned long, MemSizePtr)(void MEM_FAR * _dbgARGS); +_shAPI(MEM_POINTER_STATUS, MemCheckPtr)(MEM_POOL, void MEM_FAR * _dbgARGS); + +/* Fixed-Size Allocator */ +_shAPI(void MEM_FAR *, MemAllocFS)(MEM_POOL _dbgARGS); +_shAPI(MEM_BOOL, MemFreeFS)(void MEM_FAR * _dbgARGS); + +/* Error Handling Functions */ +MEM_ENTRY1 MEM_ERROR_FN MEM_ENTRY MemSetErrorHandler(MEM_ERROR_FN); +MEM_ENTRY1 MEM_BOOL MEM_ENTRY MemDefaultErrorHandler(MEM_ERROR_INFO MEM_FAR*); +MEM_ENTRY1 void MEM_ENTRY MemErrorUnwind(void); + +#ifdef MEM_WIN32 +/* patching control */ + +#ifndef MEM_PATCHING_DEFINED +#define MEM_PATCHING_DEFINED +typedef enum +{ + MEM_PATCH_ALL = 0, + MEM_SKIP_PATCHING_THIS_DLL = 1, + MEM_DISABLE_SYSTEM_HEAP_PATCHING = 2, + MEM_DISABLE_ALL_PATCHING = 4|2|1, + MEM_PATCHING_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_PATCHING; +#endif /* MEM_PATCHING_DEFINED */ + +#ifdef _MSC_VER +__declspec(dllexport) +#endif +MEM_PATCHING MEM_ENTRY MemSetPatching(const char ***skipDLLs); + +#endif /* MEM_WIN32 */ + +/* internal routines */ +MEM_ENTRY1 MEM_BOOL MEM_ENTRY _shi_enterCriticalSection(void); +MEM_ENTRY1 void MEM_ENTRY _shi_leaveCriticalSection(void); +MEM_BOOL shi_call_new_handler_msc(size_t, MEM_BOOL); + + +/* Wrapper macros for debugging API */ +#ifndef _SHI_dbgMacros +#ifdef MEM_DEBUG +#define MemRegisterTask() _dbgMemRegisterTask(__FILE__, __LINE__) +#define MemUnregisterTask() _dbgMemUnregisterTask(__FILE__, __LINE__) +#define MemPoolInit(flags) _dbgMemPoolInit(flags, __FILE__, __LINE__) +#define MemPoolInitFS(bs, bc, f) _dbgMemPoolInitFS(bs,bc,f,__FILE__,__LINE__) +#define MemPoolInitRegion(addr, sz, f) \ + _dbgMemPoolInitRegion(addr, sz, f, __FILE__, __LINE__) +#define MemPoolInitNamedShared(nm, sz, f) \ + _dbgMemPoolInitNamedShared(nm, sz, f, __FILE__, __LINE__) +#define MemPoolInitNamedSharedEx(a, c, p, sec, nm, sz, f) \ + _dbgMemPoolInitNamedSharedEx(a, c, p, sec, nm, sz, f, __FILE__, __LINE__) +#define MemPoolAttachShared(p, n) \ + _dbgMemPoolAttachShared(p, n, __FILE__, __LINE__) +#define MemPoolFree(pool) _dbgMemPoolFree(pool, __FILE__, __LINE__) +#define MemPoolSetPageSize(p, s) _dbgMemPoolSetPageSize(p,s,__FILE__,__LINE__) +#define MemPoolSetBlockSizeFS(p, s) \ + _dbgMemPoolSetBlockSizeFS(p, s, __FILE__, __LINE__) +#define MemPoolSetSmallBlockSize(p, s) \ + _dbgMemPoolSetSmallBlockSize(p, s, __FILE__, __LINE__) +#define MemPoolSetFloor(p, f) _dbgMemPoolSetFloor(p, f, __FILE__, __LINE__) +#define MemPoolSetCeiling(p, c) _dbgMemPoolSetCeiling(p,c,__FILE__, __LINE__) +#define MemPoolPreAllocate(p,s,t) \ + _dbgMemPoolPreAllocate(p,s,t,__FILE__, __LINE__) +#define MemPoolPreAllocateHandles(p,h) \ + _dbgMemPoolPreAllocateHandles(p,h,__FILE__, __LINE__) +#define MemPoolShrink(p) _dbgMemPoolShrink(p, __FILE__, __LINE__) +#define MemPoolCheck(p) _dbgMemPoolCheck(p, __FILE__, __LINE__) +#define MemPoolWalk(p, e) _dbgMemPoolWalk(p, e, __FILE__, __LINE__) +#define MemPoolSize(p) _dbgMemPoolSize(p, __FILE__, __LINE__) +#define MemPoolCount(p) _dbgMemPoolCount(p, __FILE__, __LINE__) +#define MemPoolInfo(p,x,i) _dbgMemPoolInfo(p,x,i, __FILE__, __LINE__) +#define MemPoolFirst(i, b) _dbgMemPoolFirst(i, b, __FILE__, __LINE__) +#define MemPoolNext(i, b) _dbgMemPoolNext(i, b, __FILE__, __LINE__) +#define MemPoolLock(p) _dbgMemPoolLock(p, __FILE__, __LINE__) +#define MemPoolUnlock(p) _dbgMemPoolUnlock(p, __FILE__, __LINE__) +#define MemAlloc(p, f, s) _dbgMemAlloc(p, f, s, __FILE__, __LINE__) +#define MemReAlloc(h, s, f) _dbgMemReAlloc(h, s, f, __FILE__, __LINE__) +#define MemFree(h) _dbgMemFree(h, __FILE__, __LINE__) +#define MemLock(h) _dbgMemLock(h, __FILE__, __LINE__) +#define MemUnlock(h) _dbgMemUnlock(h, __FILE__, __LINE__) +#define MemFix(h) _dbgMemFix(h, __FILE__, __LINE__) +#define MemUnfix(h) _dbgMemUnfix(h, __FILE__, __LINE__) +#define MemSize(h) _dbgMemSize(h, __FILE__, __LINE__) +#define MemSizeRequested(h) _dbgMemSizeRequested(h, __FILE__, __LINE__) +#define MemLockCount(h) _dbgMemLockCount(h, __FILE__, __LINE__) +#define MemIsMoveable(h) _dbgMemIsMoveable(h, __FILE__, __LINE__) +#define MemHandle(p) _dbgMemHandle(p, __FILE__, __LINE__) +#define MemAllocPtr(p, s, f) _dbgMemAllocPtr(p, s, f, __FILE__, __LINE__) +#define MemReAllocPtr(p, s, f) _dbgMemReAllocPtr(p, s, f, __FILE__,__LINE__) +#define MemFreePtr(p) _dbgMemFreePtr(p, __FILE__, __LINE__) +#define MemSizePtr(p) _dbgMemSizePtr(p, __FILE__, __LINE__) +#define MemCheckPtr(p, x) _dbgMemCheckPtr(p, x, __FILE__, __LINE__) +#define MemAllocFS(p) _dbgMemAllocFS(p, __FILE__, __LINE__) +#define MemFreeFS(p) _dbgMemFreeFS(p, __FILE__, __LINE__) + +#else /* MEM_DEBUG */ + +/* MEM_DEBUG not defined: define dbgMemXXX as no-op macros + * each macro returns "success" value when MEM_DEBUG not defined + */ +#ifndef dbgMemBreakpoint +#define dbgMemBreakpoint() ((void)0) +#define dbgMemCheckAll() 1 +#define dbgMemCheckPtr(p, f, s) 1 +#define dbgMemDeferFreeing(b) 1 +#define dbgMemFormatCall(i, b, s) 0 +#define dbgMemFormatErrorInfo(i, b, s) 0 +#define dbgMemPoolDeferFreeing(p, b) 1 +#define dbgMemFreeDeferred() 1 +#define dbgMemPoolFreeDeferred(p) 1 +#define dbgMemPoolInfo(p, b) 1 +#define dbgMemPoolSetCheckFrequency(p, f) 1 +#define dbgMemPoolSetDeferQueueLen(p, b) 1 +#define dbgMemPoolSetName(p, n) 1 +#define dbgMemProtectPtr(p, f) 1 +#define dbgMemPtrInfo(p, b) 1 +#define dbgMemReallocMoves(b) 1 +#define dbgMemReportLeakage(p, c1, c2) 1 +#define dbgMemReportWrongTaskRef(b) 1 +#define dbgMemScheduleChecking(b, p, i) 1 +#define dbgMemSetCheckFrequency(f) 1 +#define dbgMemSetCheckpoint(c) 1 +#define dbgMemSetDefaultErrorOutput(x, f) 1 +#define dbgMemSetDeferQueueLen(l) 1 +#define dbgMemSetDeferSizeThreshold(s) 1 +#define dbgMemSetEntryHandler(f) 0 +#define dbgMemSetExitHandler(f) 0 +#define dbgMemSetFreeFill(c) 1 +#define dbgMemSetGuardFill(c) 1 +#define dbgMemSetGuardSize(s) 1 +#define dbgMemSetInUseFill(c) 1 +#define dbgMemSetCallstackChains(s) 1 +#define dbgMemSetStackChecking(s) 1 +#define dbgMemSetSafetyLevel(s) 1 +#define dbgMemSettingsInfo(b) 1 +#define dbgMemSuppressFreeFill(b) 1 +#define dbgMemTotalCount() 1 +#define dbgMemTotalSize() 1 +#define dbgMemWalkHeap(b) MEM_POOL_OK +#endif /* dbgMemBreakpoint */ + +#endif /* MEM_DEBUG */ +#endif /* _SHI_dbgMacros */ + +#if defined(__WATCOMC__) && defined(__SW_3S) +/* Watcom stack calling convention */ + #pragma aux MemDefaultPool "_*"; + #pragma aux MemDefaultPoolBlockSizeFS "_*"; + #pragma aux MemDefaultPoolPageSize "_*"; + #pragma aux MemDefaultPoolFlags "_*"; + #pragma aux SmartHeap_malloc "_*"; + #pragma aux SmartHeap_far_malloc "_*"; + #pragma aux SmartHeap_new "_*"; +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !defined(_SMARTHEAP_PROT) */ diff --git a/3rdparty/smartheap/SMRTHEAP.HPP b/3rdparty/smartheap/SMRTHEAP.HPP new file mode 100644 index 00000000..663b6c90 --- /dev/null +++ b/3rdparty/smartheap/SMRTHEAP.HPP @@ -0,0 +1,159 @@ +// smrtheap.hpp -- SmartHeap public C++ header file +// Professional Memory Management Library +// +// Copyright (C) 1991-1996 by Arthur D. Applegate +// All Rights Reserved. +// +// No part of this source code may be copied, modified or reproduced +// in any form without retaining the above copyright notice. +// This source code, or source code derived from it, may not be redistributed +// without express written permission of the author. +// +// COMMENTS: +// - Include this header file to call the SmartHeap-specific versions of +// operators new (i.e. with placement syntax), to: +// o allocate from a specific memory pool; +// o specify allocation flags, such as zero-initialization; +// o resize an allocation. +// +// - If you include this header file, you must compile and link shnew.cpp, or +// link with one of the SmartHeap static operator new libraries: +// sh[l|d]XXXX.lib +// +// - Can be used in both EXEs and DLLs. +// +// - For 16-bit x86 platforms, use only in large or compact memory model. +// +// - If you do not want to use SmartHeap's global operator new but you do +// want to use SmartHeap's other facilities in a C++ application, then +// include the smrtheap.h header file but do not include this header file, +// and do not link with shnew.cpp. The two ".Xpp" files are present +// ONLY for the purpose of defining operator new and operator delete. +// +// - Use the MemDefaultPool global variable to refer to a memory pool to pass +// to SmartHeap functions that accept a pool as a parameter, +// e.g. MemPoolCount, MemPoolSize, MemPoolWalk, etc. +// + +#if !defined(_SMARTHEAP_HPP) +#define _SMARTHEAP_HPP + +#if defined(_MSC_VER) \ + && (defined(M_I86LM) || defined(M_I86CM) || defined(M_I86HM)) \ + && !defined(MEM_HUGE) +#define MEM_HUGE 0x8000u +#endif + +#ifndef __BORLANDC__ +/* Borland C++ does not treat extern "C++" correctly */ +extern "C++" +{ +#endif /* __BORLANDC__ */ + +#if defined(_MSC_VER) && _MSC_VER >= 900 +#pragma warning(disable : 4507) +#endif + +#if defined(new) +#if defined(MEM_DEBUG) +#undef new +#endif +#endif + +#include + +#include "smrtheap.h" + +#if defined(new) +#if defined(MEM_DEBUG) +#undef new +#endif +#endif + +#if ((defined(__BORLANDC__) && (__BORLANDC__ >= 0x450)) \ + || (defined(__WATCOMC__) && __WATCOMC__ >= 1000) \ + || (defined(__IBMCPP__) && __IBMCPP__ >= 250)) +#define SHI_ARRAY_NEW 1 +#endif + +void MEM_FAR * MEM_ENTRY_ANSI shi_New(unsigned long sz, unsigned flags=0, MEM_POOL pool=0); + +// operator new variants: + + +// version of new that passes memory allocation flags +// (e.g. MEM_ZEROINIT to zero-initialize memory) +// call with syntax 'ptr = new (flags) ' +inline void MEM_FAR *operator new(size_t sz, unsigned flags) + { return shi_New(sz, flags); } + +// version of new that allocates from a specified memory pool with alloc flags +// call with the syntax 'ptr = new (pool, [flags=0]) ' +inline void MEM_FAR *operator new(size_t sz, MEM_POOL pool, unsigned flags=0) + { return shi_New(sz, flags, pool); } +#ifdef SHI_ARRAY_NEW +inline void MEM_FAR *operator new[](size_t sz, MEM_POOL pool, unsigned flags=0) + { return shi_New(sz, flags, pool); } +#endif + +// version of new that changes the size of a memory block previously allocated +// from an SmartHeap memory pool +// call with the syntax 'ptr = new (ptr, flags) ' +#if !defined(MEM_DEBUG) || !defined(__HIGHC__) +/* bug in MetaWare High C++ parser confuses this with new(file,line) */ +inline void MEM_FAR *operator new(size_t new_sz, void MEM_FAR *lpMem, + unsigned flags) + { return MemReAllocPtr(lpMem, new_sz, flags); } +#ifdef SHI_ARRAY_NEW +inline void MEM_FAR *operator new[](size_t new_sz, void MEM_FAR *lpMem, + unsigned flags) + { return MemReAllocPtr(lpMem, new_sz, flags); } +#endif // SHI_ARRAY_NEW +#endif + + +// new_handler prototypes: note that MSC/C++ prototype differs from the +// protosed ANSI standard prototype for set_new_handler +#ifdef __MWERKS__ +#define MEM_CPP_THROW throw() +#else +#define MEM_CPP_THROW +#endif // __MWERKS__ +#ifndef _CRTIMP +#define _CRTIMP +#endif // _CRTIMP +#ifdef _MSC_VER +_CRTIMP _PNH MEM_ENTRY_ANSI _set_new_handler(_PNH); +#if UINT_MAX == 0xFFFFu +_PNH MEM_ENTRY_ANSI _set_fnew_handler(_PNH); +_PNHH MEM_ENTRY_ANSI _set_hnew_handler(_PNHH); +#endif // UINT_MAX +#endif // _MSC_VER +typedef void (MEM_ENTRY_ANSI * pnh)(); +_CRTIMP pnh MEM_ENTRY_ANSI set_new_handler(pnh) MEM_CPP_THROW; + +#ifndef DBG_FORMAL +#define DBG_FORMAL +#define DBG_ACTUAL +#ifndef DEBUG_NEW +#define DEBUG_NEW new +#endif // DEBUG_NEW +#define DEBUG_NEW1(x_) new(x_) +#define DEBUG_NEW2(x_, y_) new(x_, y_) +#define DEBUG_NEW3(x_, y_, z_) new(x_, y_, z_) +#define DEBUG_DELETE delete +#endif + +#ifdef DEFINE_NEW_MACRO +#define new DEBUG_NEW +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 900 +#pragma warning(default : 4507) +#endif + +#ifndef __BORLANDC__ +} +#endif /* __BORLANDC__ */ + +#endif /* !defined(_SMARTHEAP_HPP) */ diff --git a/CMakeLists.txt b/CMakeLists.txt index 6067d1f9..eafee9ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,9 @@ -cmake_minimum_required(VERSION 3.0...3.5 FATAL_ERROR) +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) project(isle CXX) option(ISLE_BUILD_APP "Build ISLE.EXE application" ON) +option(ISLE_USE_SMARTHEAP "Build with SmartHeap" ${MSVC}) add_library(lego1 SHARED LEGO1/act1state.cpp @@ -177,6 +178,16 @@ add_library(lego1 SHARED LEGO1/viewmanager.cpp ) +if (ISLE_USE_SMARTHEAP) + add_library(SmartHeap::SmartHeap STATIC IMPORTED) + set_target_properties(SmartHeap::SmartHeap PROPERTIES + IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SHLW32MT.LIB" + INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/smartheap" + INTERFACE_COMPILE_OPTIONS "/FI${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SMRTHEAP.HPP") + + target_link_libraries(lego1 PRIVATE SmartHeap::SmartHeap) +endif() + # Link libraries target_link_libraries(lego1 PRIVATE ddraw dsound winmm) @@ -194,6 +205,10 @@ if (ISLE_BUILD_APP) # Include LEGO1 headers in ISLE target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1") + if (ISLE_USE_SMARTHEAP) + target_link_libraries(isle PRIVATE SmartHeap::SmartHeap) + endif() + # Link DSOUND, WINMM, and LEGO1 target_link_libraries(isle PRIVATE dsound winmm lego1) From 4a50a9ff56f9edf3f2848b3439fda64c3c609e43 Mon Sep 17 00:00:00 2001 From: pewpew Date: Sun, 16 Jul 2023 01:43:08 -0500 Subject: [PATCH 5/8] MxNotificationManager and MxParam initial work. (#78) * MxNotificationManager initial work. * Add .swp files to .gitignore. * Checkpoint before anything too crazy with param * Cleanup and add MxParam. * Checkpoint for everything except MxNotificationManager::Register. * Add int return type to MxCore::GetId instead of relying on implicit function nonsense. * Add stlcompat.h so this can still be built on modern compilers, fix affected type size asserts. * Switch to Mx types * Add BUILD_COMPAT option to CMake so the project can still be built with modern compilers. * Change vtable14 and vtable18 to Register and Unregister in MxTickleManager. * Remove last unsigned int reference to id type. * Remove MxList, use one inherited class per type. Improves accuracy again. * Address compiler compatibility code review. * Match MxNotificationManager::Register. * Re-enable MxNotificationManager DECOMP_SIZE_ASSERT. --- .gitignore | 1 + CMakeLists.txt | 1 + LEGO1/compat.h | 13 +++ LEGO1/mxcore.h | 7 +- LEGO1/mxnotificationmanager.cpp | 140 ++++++++++++++++++++++++++++++-- LEGO1/mxnotificationmanager.h | 52 +++++++++++- LEGO1/mxparam.cpp | 11 +++ LEGO1/mxparam.h | 33 ++++++++ LEGO1/mxticklemanager.h | 4 +- 9 files changed, 250 insertions(+), 12 deletions(-) create mode 100644 LEGO1/mxparam.cpp create mode 100644 LEGO1/mxparam.h diff --git a/.gitignore b/.gitignore index 14ad2717..402fb660 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ Release/ ISLE.EXE LEGO1.DLL build/ +*.swp diff --git a/CMakeLists.txt b/CMakeLists.txt index eafee9ff..fa4de1e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,7 @@ add_library(lego1 SHARED LEGO1/mxomnicreateparam.cpp LEGO1/mxomnicreateparambase.cpp LEGO1/mxpalette.cpp + LEGO1/mxparam.cpp LEGO1/mxpresenter.cpp LEGO1/mxscheduler.cpp LEGO1/mxsemaphore.cpp diff --git a/LEGO1/compat.h b/LEGO1/compat.h index 7d76dfd0..6248259b 100644 --- a/LEGO1/compat.h +++ b/LEGO1/compat.h @@ -11,6 +11,19 @@ #define COMPAT_CONST #endif +#define MSVC420_VERSION 1020 + +// STL compatibility. +#if defined(_MSC_VER) && _MSC_VER <= MSVC420_VERSION +#include +#else +#include +#include +using namespace std; +template +using List = list; +#endif + // We use `override` so newer compilers can tell us our vtables are valid, // however this keyword was added in C++11, so we define it as empty for // compatibility with older compilers. diff --git a/LEGO1/mxcore.h b/LEGO1/mxcore.h index 9fb3e689..8ca7c421 100644 --- a/LEGO1/mxcore.h +++ b/LEGO1/mxcore.h @@ -31,8 +31,13 @@ class MxCore return !strcmp(name, MxCore::ClassName()); } + inline MxU32 GetId() + { + return m_id; + } + private: - unsigned int m_id; + MxU32 m_id; }; diff --git a/LEGO1/mxnotificationmanager.cpp b/LEGO1/mxnotificationmanager.cpp index 472c87b5..593572bb 100644 --- a/LEGO1/mxnotificationmanager.cpp +++ b/LEGO1/mxnotificationmanager.cpp @@ -1,15 +1,143 @@ +#include "legoomni.h" +#include "mxautolocker.h" +#include "mxcore.h" #include "mxnotificationmanager.h" +#include "mxparam.h" +#include "mxtypes.h" -// OFFSET: LEGO1 0x100ac450 STUB +#include "compat.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxNotification, 0x8); +DECOMP_SIZE_ASSERT(MxNotificationManager, 0x40); + +// OFFSET: LEGO1 0x100ac220 +MxNotification::MxNotification(MxCore *p_target, MxParam *p_param) +{ + m_target = p_target; + m_param = p_param->Clone(); +} + +// OFFSET: LEGO1 0x100ac240 +MxNotification::~MxNotification() +{ + delete m_param; +} + +// OFFSET: LEGO1 0x100ac250 +MxNotificationManager::MxNotificationManager() : MxCore(), m_lock(), m_listenerIds() +{ + m_unk2c = 0; + m_queue = NULL; + m_active = TRUE; + m_sendList = NULL; +} + +// OFFSET: LEGO1 0x100ac450 MxNotificationManager::~MxNotificationManager() +{ + MxAutoLocker lock(&m_lock); + Tickle(); + delete m_queue; + m_queue = NULL; + + TickleManager()->Unregister(this); +} + +// OFFSET: LEGO1 0x100ac800 +MxResult MxNotificationManager::Tickle() +{ + m_sendList = new MxNotificationPtrList(); + if (m_sendList == NULL) { + return FAILURE; + } + else { + { + MxAutoLocker lock(&m_lock); + swap(m_queue, m_sendList); + } + + while (m_sendList->size() != 0) { + MxNotification *notif = m_sendList->front(); + m_sendList->pop_front(); + notif->GetTarget()->Notify(*notif->GetParam()); + delete notif; + } + + delete m_sendList; + m_sendList = NULL; + return SUCCESS; + } +} + +// OFFSET: LEGO1 0x100ac600 +MxResult MxNotificationManager::Create(MxS32 p_unk1, MxS32 p_unk2) +{ + MxResult result = SUCCESS; + m_queue = new MxNotificationPtrList(); + + if (m_queue == NULL) { + result = FAILURE; + } + else { + TickleManager()->Register(this, 10); + } + + return result; +} + +// OFFSET: LEGO1 0x100acd20 +void MxNotificationManager::Register(MxCore *p_listener) +{ + MxAutoLocker lock(&m_lock); + + MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId()); + if (it != m_listenerIds.end()) + return; + + m_listenerIds.push_back(p_listener->GetId()); +} + +// OFFSET: LEGO1 0x100acdf0 +void MxNotificationManager::Unregister(MxCore *p_listener) +{ + MxAutoLocker lock(&m_lock); + + MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId()); + + if (it != m_listenerIds.end()) { + m_listenerIds.erase(it); + FlushPending(p_listener); + } +} + +// OFFSET: LEGO1 0x100ac990 STUB +void MxNotificationManager::FlushPending(MxCore *p_listener) { // TODO } -// OFFSET: LEGO1 0x100ac800 STUB -MxLong MxNotificationManager::Tickle() +// OFFSET: LEGO1 0x100ac6c0 +MxResult MxNotificationManager::Send(MxCore *p_listener, MxParam *p_param) { - // TODO + MxAutoLocker lock(&m_lock); - return 0; -} \ No newline at end of file + if (m_active == FALSE) { + return FAILURE; + } + else { + MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId()); + if (it == m_listenerIds.end()) { + return FAILURE; + } + else { + MxNotification *notif = new MxNotification(p_listener, p_param); + if (notif != NULL) { + m_queue->push_back(notif); + return SUCCESS; + } + } + } + + return FAILURE; +} diff --git a/LEGO1/mxnotificationmanager.h b/LEGO1/mxnotificationmanager.h index 86cb4f00..e313510b 100644 --- a/LEGO1/mxnotificationmanager.h +++ b/LEGO1/mxnotificationmanager.h @@ -2,16 +2,62 @@ #define MXNOTIFICATIONMANAGER_H #include "mxcore.h" +#include "mxcriticalsection.h" +#include "mxtypes.h" + +#include "compat.h" + +class MxNotification +{ +public: + MxNotification(MxCore *p_target, MxParam *p_param); + ~MxNotification(); + + inline MxCore *GetTarget() + { + return m_target; + } + + inline MxParam *GetParam() + { + return m_param; + } + +private: + MxCore *m_target; // 0x0 + MxParam *m_param; // 0x4 +}; + +class MxIdList : public List +{}; + +class MxNotificationPtrList : public List +{}; // VTABLE 0x100dc078 class MxNotificationManager : public MxCore { +private: + MxNotificationPtrList *m_queue; // 0x8 + MxNotificationPtrList *m_sendList; // 0xc + MxCriticalSection m_lock; // 0x10 + MxS32 m_unk2c; // 0x2c + MxIdList m_listenerIds; // 0x30 + MxBool m_active; // 0x3c + public: - virtual ~MxNotificationManager(); // vtable+0x0 + MxNotificationManager(); + virtual ~MxNotificationManager(); // vtable+0x0 (scalar deleting destructor) - virtual MxLong Tickle(); // vtable+0x8 + virtual MxResult Tickle(); // vtable+0x8 + // TODO: Where does this method come from? + virtual MxResult Create(MxS32 p_unk1, MxS32 p_unk2); // vtable+0x14 + void Register(MxCore *p_listener); + void Unregister(MxCore *p_listener); + MxResult Send(MxCore *p_listener, MxParam *p_param); - // 0x10: MxCriticalSection +private: + void FlushPending(MxCore *p_listener); }; #endif // MXNOTIFICATIONMANAGER_H diff --git a/LEGO1/mxparam.cpp b/LEGO1/mxparam.cpp new file mode 100644 index 00000000..d7bb36b2 --- /dev/null +++ b/LEGO1/mxparam.cpp @@ -0,0 +1,11 @@ +#include "mxparam.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxParam, 0xc); + +// OFFSET: LEGO1 0x10010390 +MxParam* MxParam::Clone() +{ + return new MxParam(m_type, m_sender); +} diff --git a/LEGO1/mxparam.h b/LEGO1/mxparam.h new file mode 100644 index 00000000..c4150ff7 --- /dev/null +++ b/LEGO1/mxparam.h @@ -0,0 +1,33 @@ +#ifndef MXPARAM_H +#define MXPARAM_H + +#include "mxomnicreateparambase.h" +#include "mxtypes.h" + +class MxCore; + +// VTABLE 0x100d56e0 +class MxParam : public MxOmniCreateParamBase +{ +public: + inline MxParam(MxS32 p_type, MxCore *p_sender) : MxOmniCreateParamBase(), m_type(p_type), m_sender(p_sender){} + + virtual ~MxParam(){}; // vtable+0x0 (scalar deleting destructor) + virtual MxParam *Clone(); // vtable+0x4 + + inline MxS32 GetType() const + { + return m_type; + } + + inline MxCore *GetSender() const + { + return m_sender; + } + +private: + MxS32 m_type; // 0x4 + MxCore *m_sender; // 0x8 +}; + +#endif // MXPARAM_H diff --git a/LEGO1/mxticklemanager.h b/LEGO1/mxticklemanager.h index 60f2f14d..3d976d5a 100644 --- a/LEGO1/mxticklemanager.h +++ b/LEGO1/mxticklemanager.h @@ -12,8 +12,8 @@ class MxTickleManager : public MxCore virtual MxLong Tickle(); virtual const char *ClassName() const; virtual MxBool IsA(const char *name) const; - virtual void vtable14(); - virtual void vtable18(); + virtual void Register(MxCore *p_listener, int p_milliseconds); + virtual void Unregister(MxCore *p_listener); virtual void vtable1c(void *v, int p); virtual void vtable20(); }; From e3bf7b53b57de2629ccc96ef87bfe325453241de Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Sun, 16 Jul 2023 02:49:47 -0400 Subject: [PATCH 6/8] MxEntity (#84) * Start MxEntity * MxEntity: make MxAtomId a member --- LEGO1/mxentity.cpp | 15 ++++----------- LEGO1/mxentity.h | 10 +++++----- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/LEGO1/mxentity.cpp b/LEGO1/mxentity.cpp index 7459dd24..1b5ea84f 100644 --- a/LEGO1/mxentity.cpp +++ b/LEGO1/mxentity.cpp @@ -1,19 +1,12 @@ #include "mxentity.h" -// OFFSET: LEGO1 0x1001d190 STUB +// OFFSET: LEGO1 0x1001d190 MxEntity::MxEntity() { - // TODO + this->m_mxEntityId = -1; } -// OFFSET: LEGO1 0x1000c110 STUB +// OFFSET: LEGO1 0x1000c110 MxEntity::~MxEntity() { - // TODO -} - -// OFFSET: LEGO1 0x10001070 STUB -void MxEntity::Destroy() -{ - // TODO -} +} \ No newline at end of file diff --git a/LEGO1/mxentity.h b/LEGO1/mxentity.h index 7123abbf..a7e26e37 100644 --- a/LEGO1/mxentity.h +++ b/LEGO1/mxentity.h @@ -1,7 +1,9 @@ #ifndef MXENTITY_H #define MXENTITY_H +#include "mxatomid.h" #include "mxcore.h" +#include "mxtypes.h" // VTABLE 0x100d5390 class MxEntity : public MxCore @@ -22,11 +24,9 @@ class MxEntity : public MxCore { return !strcmp(name, MxEntity::ClassName()) || MxCore::IsA(name); } - - virtual void Destroy(); // vtable+0x1c - - // 0x8: MxResult - // 0xc MxAtomId +private: + MxS32 m_mxEntityId; // 0x8 + MxAtomId m_atom; // 0xc }; #endif // MXENTITY_H From a31626cffb7a393f37ec558505af0d505d20b627 Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Sun, 16 Jul 2023 02:51:11 -0400 Subject: [PATCH 7/8] MxDSAction/Chunk/MediaAction/Sound (#85) * Match MxDSChunk ctor/dtor * Push work on MxDSAction/MediaAction/Sound * MxDSMediaAction constructor is matching up to a mov location * Match MxDSSound constructor by adding the missing member just four bytes in between them in ghidra.. isn't that enough for ghidra to justify a member variable? * Match MxDSMediaAction constructor Today's lesson: ecx suggests '1' --- LEGO1/mxdsaction.cpp | 8 +++--- LEGO1/mxdsaction.h | 55 ++++++++++++++++++++------------------- LEGO1/mxdschunk.cpp | 14 +++++++--- LEGO1/mxdschunk.h | 12 ++++++++- LEGO1/mxdsmediaaction.cpp | 13 ++++++--- LEGO1/mxdsmediaaction.h | 12 ++++++++- LEGO1/mxdssound.cpp | 2 +- LEGO1/mxdssound.h | 4 +++ 8 files changed, 80 insertions(+), 40 deletions(-) diff --git a/LEGO1/mxdsaction.cpp b/LEGO1/mxdsaction.cpp index e5162f89..b5cf6e75 100644 --- a/LEGO1/mxdsaction.cpp +++ b/LEGO1/mxdsaction.cpp @@ -5,10 +5,12 @@ MxDSAction::MxDSAction() { // TODO this->SetType(MxDSType_Action); + this->m_omni = NULL; + this->m_someTimingField = -0x80000000; } -// OFFSET: LEGO1 0x100ada80 STUB +// OFFSET: LEGO1 0x100ada80 MxDSAction::~MxDSAction() { - // TODO -} + delete this->m_unk7c; +} \ No newline at end of file diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h index e26d28a6..155d7cc2 100644 --- a/LEGO1/mxdsaction.h +++ b/LEGO1/mxdsaction.h @@ -2,6 +2,7 @@ #define MXDSACTION_H #include "mxdsobject.h" +#include "mxomni.h" // VTABLE 0x100dc098 // SIZE 0x94 @@ -23,33 +24,33 @@ class MxDSAction : public MxDSObject { return !strcmp(name, MxDSAction::ClassName()) || MxDSObject::IsA(name); } - - int m_unk2c; - int m_unk30; - int m_unk34; - int m_unk38; - int m_unk3c; - int m_unk40; - int m_unk44; - int m_unk48; - int m_unk4c; - int m_unk50; - int m_unk54; - int m_unk58; - int m_unk5c; - int m_unk60; - int m_unk64; - int m_unk68; - int m_unk6c; - int m_unk70; - int m_unk74; - int m_unk78; - int m_unk7c; - int m_unk80; - int m_unk84; - int m_unk88; - int m_unk8c; - int m_unk90; +private: + MxLong m_unk2c; + MxLong m_unk30; + MxLong m_unk34; + MxLong* m_unk38; + MxLong m_unk3c; + MxLong m_unk40; + MxLong m_unk44; + MxLong m_unk48; + MxLong m_unk4c; + MxLong m_unk50; + MxLong m_unk54; + MxLong m_unk58; + MxLong m_unk5c; + MxLong m_unk60; + MxLong m_unk64; + MxLong m_unk68; + MxLong m_unk6c; + MxLong m_unk70; + MxLong m_unk74; + MxLong m_unk78; + MxLong* m_unk7c; + MxLong m_unk80; + MxLong m_unk84; + MxLong m_unk88; + MxOmni* m_omni; // 0x8c + MxS32 m_someTimingField; // 0x90 }; #endif // MXDSACTION_H diff --git a/LEGO1/mxdschunk.cpp b/LEGO1/mxdschunk.cpp index 7ec8531c..63c43ba2 100644 --- a/LEGO1/mxdschunk.cpp +++ b/LEGO1/mxdschunk.cpp @@ -1,13 +1,19 @@ #include "mxdschunk.h" -// OFFSET: LEGO1 0x100be050 STUB +// OFFSET: LEGO1 0x100be050 MxDSChunk::MxDSChunk() { - // TODO + this->m_length = 0; + this->m_pStuff = NULL; + this->m_buffer = -1; + this->m_long1FromHeader = 0; + this->m_long2FromHeader = 0; } -// OFFSET: LEGO1 0x100be170 STUB +// OFFSET: LEGO1 0x100be170 MxDSChunk::~MxDSChunk() { - // TODO + if ((this->m_length & 1) != 0) { + delete this->m_pStuff; + } } diff --git a/LEGO1/mxdschunk.h b/LEGO1/mxdschunk.h index 8758ffa3..f9b1d9d0 100644 --- a/LEGO1/mxdschunk.h +++ b/LEGO1/mxdschunk.h @@ -1,8 +1,11 @@ #ifndef MXDSCHUNK_H #define MXDSCHUNK_H -#include "mxcore.h" +#include "mxcore.h" +#include "mxtypes.h" + +// VTABLE 0x100dc7f8 class MxDSChunk : public MxCore { public: @@ -21,6 +24,13 @@ class MxDSChunk : public MxCore { return !strcmp(name, MxDSChunk::ClassName()) || MxCore::IsA(name); } +private: + MxS16 m_length; // 0x8 + MxLong m_buffer; // 0xc + MxLong m_long1FromHeader; // 0x10 + MxLong m_long2FromHeader; // 0x14 + void* m_pStuff; // 0x18 + void* m_pSomething; // 0x1c }; #endif // MXDSCHUNK_H diff --git a/LEGO1/mxdsmediaaction.cpp b/LEGO1/mxdsmediaaction.cpp index 5f9c1132..a8acde30 100644 --- a/LEGO1/mxdsmediaaction.cpp +++ b/LEGO1/mxdsmediaaction.cpp @@ -3,12 +3,19 @@ // OFFSET: LEGO1 0x100c8b40 MxDSMediaAction::MxDSMediaAction() { - // TODO + this->m_unk98 = 0; + this->m_unk9c = 0; + this->m_unka0 = 0; + this->m_unka4 = 0; + this->m_unka8 = 0; + this->m_unkac = 1; + this->m_unkb4 = 0xffffffff; + this->m_unkb0 = 0; this->SetType(MxDSType_MediaAction); } -// OFFSET: LEGO1 0x100c8cf0 STUB +// OFFSET: LEGO1 0x100c8cf0 MxDSMediaAction::~MxDSMediaAction() { - // TODO + delete this->m_unk98; } diff --git a/LEGO1/mxdsmediaaction.h b/LEGO1/mxdsmediaaction.h index 5beb12f5..5e6a6141 100644 --- a/LEGO1/mxdsmediaaction.h +++ b/LEGO1/mxdsmediaaction.h @@ -1,6 +1,7 @@ #ifndef MXDSMEDIAACTION_H #define MXDSMEDIAACTION_H +#include "decomp.h" #include "mxdsaction.h" // VTABLE 0x100dcd40 @@ -23,7 +24,16 @@ class MxDSMediaAction : public MxDSAction { return !strcmp(name, MxDSMediaAction::ClassName()) || MxDSAction::IsA(name); } - +private: + MxS32* m_unk94; + MxS32* m_unk98; + MxS32* m_unk9c; + MxS32* m_unka0; + MxS32* m_unka4; + MxS32* m_unka8; + MxS32 m_unkac; + MxS32* m_unkb0; + MxS32 m_unkb4; }; #endif // MXDSMEDIAACTION_H diff --git a/LEGO1/mxdssound.cpp b/LEGO1/mxdssound.cpp index 30894abc..d05f785d 100644 --- a/LEGO1/mxdssound.cpp +++ b/LEGO1/mxdssound.cpp @@ -3,7 +3,7 @@ // OFFSET: LEGO1 0x100c92c0 MxDSSound::MxDSSound() { - // TODO + this->m_lastField = 0x4f; this->SetType(MxDSType_Sound); } diff --git a/LEGO1/mxdssound.h b/LEGO1/mxdssound.h index 45a61d63..eca6c055 100644 --- a/LEGO1/mxdssound.h +++ b/LEGO1/mxdssound.h @@ -2,6 +2,7 @@ #define MXDSSOUND_H #include "mxdsmediaaction.h" +#include "mxtypes.h" // VTABLE 0x100dcdd0 // SIZE 0xc0 @@ -23,6 +24,9 @@ class MxDSSound : public MxDSMediaAction { return !strcmp(name, MxDSSound::ClassName()) || MxDSMediaAction::IsA(name); } +private: + MxS32 m_unkb8; + MxLong m_lastField; // 0xbc }; From 19dcfe1164e20cf5296bd4bad459fe837b41b2ca Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Sun, 16 Jul 2023 09:27:30 -0700 Subject: [PATCH 8/8] Fix SmartHeap files (#90) --- 3rdparty/smartheap/SHMALLOC.H | 126 ++-- 3rdparty/smartheap/SMRTHEAP.H | 1312 ++++++++++++++++----------------- 2 files changed, 719 insertions(+), 719 deletions(-) diff --git a/3rdparty/smartheap/SHMALLOC.H b/3rdparty/smartheap/SHMALLOC.H index fff43c88..709c19b8 100644 --- a/3rdparty/smartheap/SHMALLOC.H +++ b/3rdparty/smartheap/SHMALLOC.H @@ -1,63 +1,63 @@ -/* shmalloc.h -- SmartHeap ANSI Standard C memory API - * Professional Memory Management Library - * - * Copyright (C) 1991-1996 by Arthur D. Applegate. All Rights Reserved. - * All Rights Reserved. - * - * No part of this source code may be copied, modified or reproduced - * in any form without retaining the above copyright notice. - * This source code, or source code derived from it, may not be redistributed - * without express written permission of the author. - */ - -#if !(defined(_SHMALLOC_H)) -#define _SHMALLOC_H - -#include "smrtheap.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* ANSI Standard Memory Management API */ - -#if (!defined(MEM_DEBUG) && !defined(NO_MALLOC_MACRO)) || defined(MALLOC_MACRO) -#ifdef malloc -#undef malloc -#endif -#define malloc(s) MEM_malloc(s) -#ifdef calloc -#undef calloc -#endif -#define calloc(s,c) MEM_calloc(s,c) -#ifdef realloc -#undef realloc -#endif -#define realloc(p,s) MEM_realloc(p,s) -#ifdef free -#undef free -#endif -#define free(p) MEM_free(p) - -#endif /* NO_MALLOC_MACRO */ - -#ifndef MEM_malloc -void MEM_FAR * MEM_ENTRY_ANSI MEM_malloc(size_t size); -void MEM_FAR * MEM_ENTRY_ANSI MEM_calloc(size_t nobj, size_t size); -void MEM_FAR * MEM_ENTRY_ANSI MEM_realloc(void MEM_FAR *p, size_t size); -void MEM_ENTRY_ANSI MEM_free(void MEM_FAR *p); -#endif /* MEM_malloc */ - -#if defined(__WATCOMC__) && defined(__SW_3S) -/* Watcom stack calling convention */ - #pragma aux (syscall) MEM_malloc - #pragma aux (syscall) MEM_realloc - #pragma aux (syscall) MEM_calloc - #pragma aux (syscall) MEM_free -#endif /* __WATCOMC__ */ - -#ifdef __cplusplus -} -#endif - -#endif /* !defined(_SHMALLOC_H) */ +/* shmalloc.h -- SmartHeap ANSI Standard C memory API + * Professional Memory Management Library + * + * Copyright (C) 1991-1996 by Arthur D. Applegate. All Rights Reserved. + * All Rights Reserved. + * + * No part of this source code may be copied, modified or reproduced + * in any form without retaining the above copyright notice. + * This source code, or source code derived from it, may not be redistributed + * without express written permission of the author. + */ + +#if !(defined(_SHMALLOC_H)) +#define _SHMALLOC_H + +#include "smrtheap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ANSI Standard Memory Management API */ + +#if (!defined(MEM_DEBUG) && !defined(NO_MALLOC_MACRO)) || defined(MALLOC_MACRO) +#ifdef malloc +#undef malloc +#endif +#define malloc(s) MEM_malloc(s) +#ifdef calloc +#undef calloc +#endif +#define calloc(s,c) MEM_calloc(s,c) +#ifdef realloc +#undef realloc +#endif +#define realloc(p,s) MEM_realloc(p,s) +#ifdef free +#undef free +#endif +#define free(p) MEM_free(p) + +#endif /* NO_MALLOC_MACRO */ + +#ifndef MEM_malloc +void MEM_FAR * MEM_ENTRY_ANSI MEM_malloc(size_t size); +void MEM_FAR * MEM_ENTRY_ANSI MEM_calloc(size_t nobj, size_t size); +void MEM_FAR * MEM_ENTRY_ANSI MEM_realloc(void MEM_FAR *p, size_t size); +void MEM_ENTRY_ANSI MEM_free(void MEM_FAR *p); +#endif /* MEM_malloc */ + +#if defined(__WATCOMC__) && defined(__SW_3S) +/* Watcom stack calling convention */ + #pragma aux (syscall) MEM_malloc + #pragma aux (syscall) MEM_realloc + #pragma aux (syscall) MEM_calloc + #pragma aux (syscall) MEM_free +#endif /* __WATCOMC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(_SHMALLOC_H) */ diff --git a/3rdparty/smartheap/SMRTHEAP.H b/3rdparty/smartheap/SMRTHEAP.H index aab58b84..b4f17a74 100644 --- a/3rdparty/smartheap/SMRTHEAP.H +++ b/3rdparty/smartheap/SMRTHEAP.H @@ -1,656 +1,656 @@ -/* smrtheap.h -- SmartHeap (tm) public C header file - * Professional Memory Management Library - * - * Copyright (C) 1991-1997 by Arthur D. Applegate. All Rights Reserved. - * All Rights Reserved. - * - * No part of this source code may be copied, modified or reproduced - * in any form without retaining the above copyright notice. - * This source code, or source code derived from it, may not be redistributed - * without express written permission of the author. - * - */ - -#if !defined(_SMARTHEAP_H) -#define _SMARTHEAP_H - -#include -#include - -#if !defined(macintosh) && !defined(THINK_C) && !defined(__MWERKS__) \ - && !defined(SHANSI) && UINT_MAX == 0xFFFFu \ - && (defined(_Windows) || defined(_WINDOWS) || defined(__WINDOWS__)) - #define MEM_WIN16 -#endif - -#if (UINT_MAX == 0xFFFFu) && (defined(MEM_WIN16) \ - || defined(MSDOS) || defined(__MSDOS__) || defined(__DOS__)) - /* 16-bit X86 */ - #if defined(SYS_DLL) - #if defined(_MSC_VER) && _MSC_VER <= 600 - #define MEM_ENTRY _export _loadds far pascal - #else - #define MEM_ENTRY _export far pascal - #endif - #else - #define MEM_ENTRY far pascal - #endif - #ifdef __WATCOMC__ - #define MEM_ENTRY_ANSI __far - #else - #define MEM_ENTRY_ANSI far cdecl - #endif - #define MEM_FAR far - #if defined(MEM_WIN16) - #define MEM_ENTRY2 _export far pascal - #elif defined(DOS16M) || defined(DOSX286) - #define MEM_ENTRY2 _export _loadds far pascal - #endif - -#else /* not 16-bit X86 */ - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) \ - || defined(__WIN32__) || defined(__NT__) - #define MEM_WIN32 - #if defined(_MSC_VER) - #if defined(_SHI_Pool) && defined(SYS_DLL) - #define MEM_ENTRY1 __declspec(dllexport) - #define MEM_ENTRY4 __declspec(dllexport) extern - #elif !defined(_SHI_Pool) && (defined(MEM_DEBUG) || defined(MEM_DLL)) - #define MEM_ENTRY1 __declspec(dllimport) - #if defined(_M_IX86) || defined(_X86_) - #define MemDefaultPool shi_MemDefaultPool - #define MEM_ENTRY4 __declspec(dllimport) - #endif - #endif - #endif - #if !defined(_MSC_VER) || defined(_M_IX86) || defined(_X86_) - #define MEM_ENTRY __stdcall - #else - #define MEM_ENTRY __cdecl /* for NT/RISC */ - #endif - #ifndef __WATCOMC__ - #define MEM_ENTRY_ANSI __cdecl - #endif - -#elif defined(__OS2__) - #if defined(__BORLANDC__) || defined(__WATCOMC__) - #if defined(SYS_DLL) - #define MEM_ENTRY __export __syscall - #else - #define MEM_ENTRY __syscall - #endif /* SYS_DLL */ - #ifdef __BORLANDC__ - #define MEM_ENTRY_ANSI __stdcall - #endif - #elif defined(__IBMC__) || defined(__IBMCPP__) - #if defined(SYS_DLL) && 0 - #define MEM_ENTRY _Export _System - #else - #define MEM_ENTRY _System - #endif - #define MEM_ENTRY_ANSI _Optlink - #define MEM_ENTRY3 MEM_ENTRY - #define MEM_CALLBACK MEM_ENTRY3 - #define MEM_ENTRY2 - #endif -#endif /* __OS2__ */ - -#if defined(__WATCOMC__) && defined(__SW_3S) - /* Watcom stack calling convention */ -#ifndef __OS2__ -#ifdef __WINDOWS_386__ - #pragma aux syscall "*_" parm routine [eax ebx ecx edx fs gs] modify [eax]; -#else - #pragma aux syscall "*_" parm routine [eax ebx ecx edx] modify [eax]; -#endif -#ifndef MEM_ENTRY - #define MEM_ENTRY __syscall -#endif /* MEM_ENTRY */ -#endif -#endif /* Watcom stack calling convention */ - -#endif /* end of system-specific declarations */ - -#ifndef MEM_ENTRY - #define MEM_ENTRY -#endif -#ifndef MEM_ENTRY1 - #define MEM_ENTRY1 -#endif -#ifndef MEM_ENTRY2 - #define MEM_ENTRY2 MEM_ENTRY -#endif -#ifndef MEM_ENTRY3 - #define MEM_ENTRY3 -#endif -#ifndef MEM_ENTRY4 - #define MEM_ENTRY4 extern -#endif -#ifndef MEM_CALLBACK -#define MEM_CALLBACK MEM_ENTRY2 -#endif -#ifndef MEM_ENTRY_ANSI - #define MEM_ENTRY_ANSI -#endif -#ifndef MEM_FAR - #define MEM_FAR -#endif - -#ifdef applec -/* Macintosh: Apple MPW C/C++ passes char/short parms as longs (4 bytes), - * whereas Symantec C/C++ for MPW passes these as words (2 bytes); - * therefore, canonicalize all integer parms as 'int' for this platform. - */ - #define MEM_USHORT unsigned - #define MEM_UCHAR unsigned -#else - #define MEM_USHORT unsigned short - #define MEM_UCHAR unsigned char -#endif /* applec */ - -#ifdef MEM_DEBUG -#include "heapagnt.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/*** Types ***/ - -#ifndef MEM_BOOL_DEFINED -#define MEM_BOOL_DEFINED -typedef int MEM_BOOL; -#endif - -/* Version Masks */ -typedef unsigned MEM_VERSION; -#define MEM_MAJOR_VERSION(v) (((v) & 0xF000u) >> 12) -#define MEM_MINOR_VERSION(v) (((v) & 0x0F00u) >> 8) -#define MEM_UPDATE_VERSION(v) ((v) & 0x00FFu) - -/* Note: these types are struct's rather than integral types to facilitate - * compile-time type-checking. MEM_POOL and MEM_HANDLE should be regarded - * as black boxes, and treated just like handles. - * You should not have any type casts to or from MEM_POOL or MEM_HANDLE; - * nor should you dereference variables of type MEM_POOL or MEM_HANDLE - * (unless you are using SmartHeap to replace NewHandle on the Mac, and - * you have existing code that dereferences handles). - */ -#ifndef MEM_POOL_DEFINED -#define MEM_POOL_DEFINED -#ifdef _SHI_Pool - typedef struct _SHI_Pool MEM_FAR *MEM_POOL; - typedef struct _SHI_MovHandle MEM_FAR *MEM_HANDLE; -#else - #ifdef THINK_C - typedef void *MEM_POOL; - typedef void **MEM_HANDLE; - #else - typedef struct _SHI_Pool { int reserved; } MEM_FAR *MEM_POOL; - typedef struct _SHI_MovHandle { int reserved; } MEM_FAR *MEM_HANDLE; - #endif -#endif -#endif /* MEM_POOL_DEFINED */ - - -#if !defined(MEM_DEBUG) || !(defined(MEM_WIN16) || defined(MEM_WIN32)) -#define SHI_MAJOR_VERSION 3 -#define SHI_MINOR_VERSION 3 -#define SHI_UPDATE_LEVEL 0 -#endif /* !WINDOWS */ - -#ifndef MEM_DEBUG - -/* Error codes: errorCode field of MEM_ERROR_INFO */ -#ifndef MEM_ERROR_CODE_DEFINED -#define MEM_ERROR_CODE_DEFINED -typedef enum -{ - MEM_NO_ERROR=0, - MEM_INTERNAL_ERROR, - MEM_OUT_OF_MEMORY, - MEM_BLOCK_TOO_BIG, - MEM_ALLOC_ZERO, - MEM_RESIZE_FAILED, - MEM_LOCK_ERROR, - MEM_EXCEEDED_CEILING, - MEM_TOO_MANY_PAGES, - MEM_TOO_MANY_TASKS, - MEM_BAD_MEM_POOL, - MEM_BAD_BLOCK, - MEM_BAD_FREE_BLOCK, - MEM_BAD_HANDLE, - MEM_BAD_POINTER, - MEM_WRONG_TASK, - MEM_NOT_FIXED_SIZE, - MEM_BAD_FLAGS, - MEM_ERROR_CODE_INT_MAX = INT_MAX /* to ensure enum is full int in size */ -} MEM_ERROR_CODE; -#endif /* MEM_ERROR_CODE_DEFINED */ - - -/* ### we should have packing pragma around these structure decls in case - * ### user is compiling with non-default packing directive (only needed - * ### if user is packing more strictly than native int size *and* if - * ### native int size is != native long and ptr sizes) - */ - -/* Error info, passed to error-handling callback routine */ -#ifndef MEM_ERROR_INFO_DEFINED -#define MEM_ERROR_INFO_DEFINED -typedef struct _MEM_ERROR_INFO -{ - MEM_ERROR_CODE errorCode; /* error code identifying type of error */ - MEM_POOL pool; /* pool in which error occurred, if known */ -} MEM_ERROR_INFO; - -/* Error handling callback function */ -typedef MEM_BOOL (MEM_ENTRY2 * MEM_ENTRY3 MEM_ERROR_FN) - (MEM_ERROR_INFO MEM_FAR *); - -#endif /* MEM_ERROR_INFO_DEFINED */ - -#endif /* MEM_DEBUG */ - - -#ifndef MEM_BLOCK_TYPE_DEFINED -#define MEM_BLOCK_TYPE_DEFINED -/* Block Type: field of MEM_POOL_ENTRY, field of MEM_POOL_INFO, - * parameter to MemPoolPreAllocate - */ -typedef enum -{ - MEM_FS_BLOCK = 0x0001u, - MEM_VAR_MOVEABLE_BLOCK = 0x0002u, - MEM_VAR_FIXED_BLOCK = 0x0004u, - MEM_EXTERNAL_BLOCK = 0x0008u, - MEM_BLOCK_TYPE_INT_MAX = INT_MAX /* to ensure enum is full int in size */ -} MEM_BLOCK_TYPE; -#endif /* MEM_BLOCK_TYPE_DEFINED */ - -#ifndef MEM_POOL_ENTRY_DEFINED -#define MEM_POOL_ENTRY_DEFINED -/* Pool Entry: parameter to MemPoolWalk */ -typedef struct -{ - void MEM_FAR *entry; - MEM_POOL pool; - MEM_BLOCK_TYPE type; - MEM_BOOL isInUse; - unsigned long size; - MEM_HANDLE handle; - unsigned lockCount; - void MEM_FAR *reserved_ptr; -} MEM_POOL_ENTRY; -#endif /* MEM_POOL_ENTRY_DEFINED */ - -#ifndef MEM_POOL_STATUS_DEFINED -#define MEM_POOL_STATUS_DEFINED -/* Pool Status: returned by MemPoolWalk, MemPoolFirst, MemPoolNext */ -typedef enum -{ - MEM_POOL_OK = 1, - MEM_POOL_CORRUPT = -1, - MEM_POOL_CORRUPT_FATAL = -2, - MEM_POOL_END = 0, - MEM_POOL_STATUS_INT_MAX = INT_MAX /* to ensure enum is full int in size */ -} MEM_POOL_STATUS; -#endif /* MEM_POOL_STATUS_DEFINED */ - -#ifndef MEM_POINTER_STATUS_DEFINED -#define MEM_POINTER_STATUS_DEFINED -/* Pointer Status: returned by MemCheckPtr */ -typedef enum -{ - MEM_POINTER_OK = 1, - MEM_POINTER_WILD = 0, - MEM_POINTER_FREE = -1, - MEM_POINTER_STATUS_INT_MAX = INT_MAX /* to ensure enum is full int in size */ -} MEM_POINTER_STATUS; -#endif /* MEM_POINTER_STATUS_DEFINED */ - -/* Pool Info: parameter to MemPoolInfo, MemPoolFirst, MemPoolNext */ -typedef struct -{ - MEM_POOL pool; - MEM_BLOCK_TYPE type; /* disjunctive combination of block type flags */ - unsigned short blockSizeFS; - unsigned short smallBlockSize; - unsigned pageSize; - unsigned long floor; - unsigned long ceiling; - unsigned flags; - MEM_ERROR_FN errorFn; -} MEM_POOL_INFO; - -/* Flags passed to MemAlloc, MemAllocPtr, MemReAlloc, MemReAllocPtr */ -#define MEM_FIXED 0x0000u /* fixed handle-based block */ -#define MEM_ZEROINIT 0x0001u /* == TRUE for SH 1.5 compatibility */ -#define MEM_MOVEABLE 0x0002u /* moveable handle-based block */ -#define MEM_RESIZEABLE 0x0004u /* reserve space above block */ -#define MEM_RESIZE_IN_PLACE 0x0008u /* do not move block (realloc) */ -#define MEM_NOGROW 0x0010u /* do not grow heap to satisfy request */ -#define MEM_NOEXTERNAL 0x0020u /* reserved for internal use */ -#define MEM_NOCOMPACT 0x0040u /* do not compact to satisfy request */ -#define MEM_NO_SERIALIZE 0x0080u /* do not serialize this request */ -#define MEM_HANDLEBASED 0x4000u /* for internal use */ -#define MEM_RESERVED 0x8000u /* for internal use */ - -#define MEM_UNLOCK_FAILED USHRT_MAX - -/* Flags passed to MemPoolInit, MemPoolInitFS */ -#ifndef MEM_POOL_SHARED -#define MEM_POOL_SHARED 0x0001u /* == TRUE for SH 1.5 compatibility */ -#define MEM_POOL_SERIALIZE 0x0002u /* pool used in more than one thread */ -#define MEM_POOL_VIRTUAL_LOCK 0x0004u /* pool is locked in physical memory */ -#define MEM_POOL_ZEROINIT 0x0008u /* malloc/new from pool zero-inits */ -#define MEM_POOL_REGION 0x0010u /* store pool in user-supplied region*/ -#define MEM_POOL_DEFAULT 0x8000u /* pool with default characteristics */ -#endif /* MEM_POOL_SHARED */ - -MEM_ENTRY4 MEM_POOL MemDefaultPool; - -/* Default memory pool for C malloc, C++ new (for backwards compatibility) */ -#define MEM_DEFAULT_POOL MemDefaultPool - -/* define and initialize these variables at file scope to change defaults */ -extern unsigned short MemDefaultPoolBlockSizeFS; -extern unsigned MemDefaultPoolPageSize; -extern unsigned MemDefaultPoolFlags; - -/* define SmartHeap_malloc at file scope if you - * are intentionally _NOT_ linking in the SmartHeap malloc definition - * ditto for SmartHeap operator new, and fmalloc et al. - */ -extern int SmartHeap_malloc; -extern int SmartHeap_far_malloc; -extern int SmartHeap_new; - -#define MEM_ERROR_RET ULONG_MAX - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* !defined(_SMARTHEAP_H) */ - - -/*** Function Prototypes ***/ - -#ifndef _SMARTHEAP_PROT -#define _SMARTHEAP_PROT - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _shAPI - #if defined(MEM_DEBUG) && !defined(SHI_NO_MEM_DEBUG) - #define _shAPI(ret, name) MEM_ENTRY1 ret MEM_ENTRY _dbg ## name - #else - #define _shAPI(ret, name) MEM_ENTRY1 ret MEM_ENTRY name - #endif -#endif - -#ifndef _dbgARGS - #if defined(MEM_DEBUG) && !defined(SHI_NO_MEM_DEBUG) - #define _dbgARGS1 const char MEM_FAR *, int - #define _dbgARGS , _dbgARGS1 - #else - #define _dbgARGS1 void - #define _dbgARGS - #endif -#endif - - -/**** HOW TO READ SmartHeap PROTOTYPES **** - * prototypes below have the follow syntax in order to support both debug - * and non-debug APIs with single-source: - * - * _shiAPI(, )([] _dbgARGS); - * - * the above translates to a C prototype as follows: - * - * ([]); - */ - -/* Library Version */ -MEM_ENTRY1 MEM_VERSION MEM_ENTRY MemVersion(void); - -/* Library Registration */ -_shAPI(MEM_BOOL, MemRegisterTask)(_dbgARGS1); -_shAPI(MEM_BOOL, MemUnregisterTask)(_dbgARGS1); - -/* Memory Pool Functions */ -_shAPI(MEM_POOL, MemPoolInit)(unsigned _dbgARGS); -_shAPI(MEM_POOL, MemPoolInitFS)(MEM_USHORT, unsigned long, - unsigned _dbgARGS); -_shAPI(MEM_POOL, MemPoolInitRegion)(void MEM_FAR *, - unsigned long size, unsigned _dbgARGS); -_shAPI(MEM_POOL, MemPoolInitNamedShared)(const char MEM_FAR *, - unsigned long size,unsigned _dbgARGS); -_shAPI(MEM_POOL, MemPoolInitNamedSharedEx)(void MEM_FAR *addr, - unsigned pidCount, unsigned long MEM_FAR *pids, void MEM_FAR *security, - const char MEM_FAR *name, unsigned long size, unsigned flags _dbgARGS); -_shAPI(MEM_POOL, MemPoolAttachShared)(MEM_POOL, const char MEM_FAR * _dbgARGS); -_shAPI(MEM_BOOL, MemPoolFree)(MEM_POOL _dbgARGS); -MEM_POOL MEM_ENTRY MemInitDefaultPool(void); -MEM_BOOL MEM_ENTRY MemFreeDefaultPool(void); -_shAPI(unsigned, MemPoolSetPageSize)(MEM_POOL, unsigned _dbgARGS); -_shAPI(MEM_BOOL, MemPoolSetBlockSizeFS)(MEM_POOL, MEM_USHORT _dbgARGS); -_shAPI(MEM_BOOL, MemPoolSetSmallBlockSize)(MEM_POOL, MEM_USHORT _dbgARGS); -_shAPI(unsigned long, MemPoolSetFloor)(MEM_POOL, unsigned long _dbgARGS); -_shAPI(unsigned long, MemPoolSetCeiling)(MEM_POOL, unsigned long _dbgARGS); -_shAPI(unsigned long, MemPoolPreAllocate)(MEM_POOL, unsigned long, - MEM_BLOCK_TYPE _dbgARGS); -_shAPI(unsigned long, MemPoolPreAllocateHandles)(MEM_POOL, - unsigned long _dbgARGS); -_shAPI(unsigned long, MemPoolShrink)(MEM_POOL _dbgARGS); -_shAPI(unsigned long, MemPoolSize)(MEM_POOL _dbgARGS); -_shAPI(unsigned long, MemPoolCount)(MEM_POOL _dbgARGS); -_shAPI(MEM_BOOL, MemPoolInfo)(MEM_POOL, void MEM_FAR *, - MEM_POOL_INFO MEM_FAR* _dbgARGS); -_shAPI(MEM_POOL_STATUS, MemPoolFirst)(MEM_POOL_INFO MEM_FAR *, - MEM_BOOL _dbgARGS); -_shAPI(MEM_POOL_STATUS,MemPoolNext)(MEM_POOL_INFO MEM_FAR*,MEM_BOOL _dbgARGS); -_shAPI(MEM_POOL_STATUS,MemPoolWalk)(MEM_POOL,MEM_POOL_ENTRY MEM_FAR*_dbgARGS); -_shAPI(MEM_BOOL, MemPoolCheck)(MEM_POOL _dbgARGS); -_shAPI(MEM_BOOL, MemPoolLock)(MEM_POOL _dbgARGS); -_shAPI(MEM_BOOL, MemPoolUnlock)(MEM_POOL _dbgARGS); - -/* Handle-based API for moveable memory within heap. */ -_shAPI(MEM_HANDLE, MemAlloc)(MEM_POOL, unsigned, unsigned long _dbgARGS); -_shAPI(MEM_HANDLE, MemReAlloc)(MEM_HANDLE,unsigned long,unsigned _dbgARGS); -_shAPI(MEM_BOOL, MemFree)(MEM_HANDLE _dbgARGS); -_shAPI(void MEM_FAR *, MemLock)(MEM_HANDLE _dbgARGS); -_shAPI(unsigned, MemUnlock)(MEM_HANDLE _dbgARGS); -_shAPI(void MEM_FAR *, MemFix)(MEM_HANDLE _dbgARGS); -_shAPI(unsigned, MemUnfix)(MEM_HANDLE _dbgARGS); -_shAPI(unsigned, MemLockCount)(MEM_HANDLE _dbgARGS); -#ifndef MemFlags -#define MemFlags(mem) MemLockCount(mem) -#endif -_shAPI(MEM_BOOL, MemIsMoveable)(MEM_HANDLE _dbgARGS); -_shAPI(unsigned long, MemSize)(MEM_HANDLE _dbgARGS); -_shAPI(unsigned long, MemSizeRequested)(MEM_HANDLE _dbgARGS); -_shAPI(MEM_HANDLE, MemHandle)(void MEM_FAR * _dbgARGS); -#ifndef MEM_REFERENCE - #ifdef MEM_DEBUG - MEM_ENTRY1 void MEM_FAR * MEM_ENTRY _dbgMemReference(MEM_HANDLE, - const char MEM_FAR *, int); - #define MEM_REFERENCE(handle) \ - _dbgMemReference(handle, __FILE__, __LINE__) - #else - #define MEM_REFERENCE(handle) (*(void MEM_FAR * MEM_FAR *)handle) - #endif -#endif - -/* General Heap Allocator (returns direct pointer to memory) */ -_shAPI(void MEM_FAR*,MemAllocPtr)(MEM_POOL,unsigned long,unsigned _dbgARGS); -_shAPI(void MEM_FAR *, MemReAllocPtr)(void MEM_FAR *, unsigned long, - unsigned _dbgARGS); -_shAPI(MEM_BOOL, MemFreePtr)(void MEM_FAR * _dbgARGS); -_shAPI(unsigned long, MemSizePtr)(void MEM_FAR * _dbgARGS); -_shAPI(MEM_POINTER_STATUS, MemCheckPtr)(MEM_POOL, void MEM_FAR * _dbgARGS); - -/* Fixed-Size Allocator */ -_shAPI(void MEM_FAR *, MemAllocFS)(MEM_POOL _dbgARGS); -_shAPI(MEM_BOOL, MemFreeFS)(void MEM_FAR * _dbgARGS); - -/* Error Handling Functions */ -MEM_ENTRY1 MEM_ERROR_FN MEM_ENTRY MemSetErrorHandler(MEM_ERROR_FN); -MEM_ENTRY1 MEM_BOOL MEM_ENTRY MemDefaultErrorHandler(MEM_ERROR_INFO MEM_FAR*); -MEM_ENTRY1 void MEM_ENTRY MemErrorUnwind(void); - -#ifdef MEM_WIN32 -/* patching control */ - -#ifndef MEM_PATCHING_DEFINED -#define MEM_PATCHING_DEFINED -typedef enum -{ - MEM_PATCH_ALL = 0, - MEM_SKIP_PATCHING_THIS_DLL = 1, - MEM_DISABLE_SYSTEM_HEAP_PATCHING = 2, - MEM_DISABLE_ALL_PATCHING = 4|2|1, - MEM_PATCHING_INT_MAX = INT_MAX /* to ensure enum is full int in size */ -} MEM_PATCHING; -#endif /* MEM_PATCHING_DEFINED */ - -#ifdef _MSC_VER -__declspec(dllexport) -#endif -MEM_PATCHING MEM_ENTRY MemSetPatching(const char ***skipDLLs); - -#endif /* MEM_WIN32 */ - -/* internal routines */ -MEM_ENTRY1 MEM_BOOL MEM_ENTRY _shi_enterCriticalSection(void); -MEM_ENTRY1 void MEM_ENTRY _shi_leaveCriticalSection(void); -MEM_BOOL shi_call_new_handler_msc(size_t, MEM_BOOL); - - -/* Wrapper macros for debugging API */ -#ifndef _SHI_dbgMacros -#ifdef MEM_DEBUG -#define MemRegisterTask() _dbgMemRegisterTask(__FILE__, __LINE__) -#define MemUnregisterTask() _dbgMemUnregisterTask(__FILE__, __LINE__) -#define MemPoolInit(flags) _dbgMemPoolInit(flags, __FILE__, __LINE__) -#define MemPoolInitFS(bs, bc, f) _dbgMemPoolInitFS(bs,bc,f,__FILE__,__LINE__) -#define MemPoolInitRegion(addr, sz, f) \ - _dbgMemPoolInitRegion(addr, sz, f, __FILE__, __LINE__) -#define MemPoolInitNamedShared(nm, sz, f) \ - _dbgMemPoolInitNamedShared(nm, sz, f, __FILE__, __LINE__) -#define MemPoolInitNamedSharedEx(a, c, p, sec, nm, sz, f) \ - _dbgMemPoolInitNamedSharedEx(a, c, p, sec, nm, sz, f, __FILE__, __LINE__) -#define MemPoolAttachShared(p, n) \ - _dbgMemPoolAttachShared(p, n, __FILE__, __LINE__) -#define MemPoolFree(pool) _dbgMemPoolFree(pool, __FILE__, __LINE__) -#define MemPoolSetPageSize(p, s) _dbgMemPoolSetPageSize(p,s,__FILE__,__LINE__) -#define MemPoolSetBlockSizeFS(p, s) \ - _dbgMemPoolSetBlockSizeFS(p, s, __FILE__, __LINE__) -#define MemPoolSetSmallBlockSize(p, s) \ - _dbgMemPoolSetSmallBlockSize(p, s, __FILE__, __LINE__) -#define MemPoolSetFloor(p, f) _dbgMemPoolSetFloor(p, f, __FILE__, __LINE__) -#define MemPoolSetCeiling(p, c) _dbgMemPoolSetCeiling(p,c,__FILE__, __LINE__) -#define MemPoolPreAllocate(p,s,t) \ - _dbgMemPoolPreAllocate(p,s,t,__FILE__, __LINE__) -#define MemPoolPreAllocateHandles(p,h) \ - _dbgMemPoolPreAllocateHandles(p,h,__FILE__, __LINE__) -#define MemPoolShrink(p) _dbgMemPoolShrink(p, __FILE__, __LINE__) -#define MemPoolCheck(p) _dbgMemPoolCheck(p, __FILE__, __LINE__) -#define MemPoolWalk(p, e) _dbgMemPoolWalk(p, e, __FILE__, __LINE__) -#define MemPoolSize(p) _dbgMemPoolSize(p, __FILE__, __LINE__) -#define MemPoolCount(p) _dbgMemPoolCount(p, __FILE__, __LINE__) -#define MemPoolInfo(p,x,i) _dbgMemPoolInfo(p,x,i, __FILE__, __LINE__) -#define MemPoolFirst(i, b) _dbgMemPoolFirst(i, b, __FILE__, __LINE__) -#define MemPoolNext(i, b) _dbgMemPoolNext(i, b, __FILE__, __LINE__) -#define MemPoolLock(p) _dbgMemPoolLock(p, __FILE__, __LINE__) -#define MemPoolUnlock(p) _dbgMemPoolUnlock(p, __FILE__, __LINE__) -#define MemAlloc(p, f, s) _dbgMemAlloc(p, f, s, __FILE__, __LINE__) -#define MemReAlloc(h, s, f) _dbgMemReAlloc(h, s, f, __FILE__, __LINE__) -#define MemFree(h) _dbgMemFree(h, __FILE__, __LINE__) -#define MemLock(h) _dbgMemLock(h, __FILE__, __LINE__) -#define MemUnlock(h) _dbgMemUnlock(h, __FILE__, __LINE__) -#define MemFix(h) _dbgMemFix(h, __FILE__, __LINE__) -#define MemUnfix(h) _dbgMemUnfix(h, __FILE__, __LINE__) -#define MemSize(h) _dbgMemSize(h, __FILE__, __LINE__) -#define MemSizeRequested(h) _dbgMemSizeRequested(h, __FILE__, __LINE__) -#define MemLockCount(h) _dbgMemLockCount(h, __FILE__, __LINE__) -#define MemIsMoveable(h) _dbgMemIsMoveable(h, __FILE__, __LINE__) -#define MemHandle(p) _dbgMemHandle(p, __FILE__, __LINE__) -#define MemAllocPtr(p, s, f) _dbgMemAllocPtr(p, s, f, __FILE__, __LINE__) -#define MemReAllocPtr(p, s, f) _dbgMemReAllocPtr(p, s, f, __FILE__,__LINE__) -#define MemFreePtr(p) _dbgMemFreePtr(p, __FILE__, __LINE__) -#define MemSizePtr(p) _dbgMemSizePtr(p, __FILE__, __LINE__) -#define MemCheckPtr(p, x) _dbgMemCheckPtr(p, x, __FILE__, __LINE__) -#define MemAllocFS(p) _dbgMemAllocFS(p, __FILE__, __LINE__) -#define MemFreeFS(p) _dbgMemFreeFS(p, __FILE__, __LINE__) - -#else /* MEM_DEBUG */ - -/* MEM_DEBUG not defined: define dbgMemXXX as no-op macros - * each macro returns "success" value when MEM_DEBUG not defined - */ -#ifndef dbgMemBreakpoint -#define dbgMemBreakpoint() ((void)0) -#define dbgMemCheckAll() 1 -#define dbgMemCheckPtr(p, f, s) 1 -#define dbgMemDeferFreeing(b) 1 -#define dbgMemFormatCall(i, b, s) 0 -#define dbgMemFormatErrorInfo(i, b, s) 0 -#define dbgMemPoolDeferFreeing(p, b) 1 -#define dbgMemFreeDeferred() 1 -#define dbgMemPoolFreeDeferred(p) 1 -#define dbgMemPoolInfo(p, b) 1 -#define dbgMemPoolSetCheckFrequency(p, f) 1 -#define dbgMemPoolSetDeferQueueLen(p, b) 1 -#define dbgMemPoolSetName(p, n) 1 -#define dbgMemProtectPtr(p, f) 1 -#define dbgMemPtrInfo(p, b) 1 -#define dbgMemReallocMoves(b) 1 -#define dbgMemReportLeakage(p, c1, c2) 1 -#define dbgMemReportWrongTaskRef(b) 1 -#define dbgMemScheduleChecking(b, p, i) 1 -#define dbgMemSetCheckFrequency(f) 1 -#define dbgMemSetCheckpoint(c) 1 -#define dbgMemSetDefaultErrorOutput(x, f) 1 -#define dbgMemSetDeferQueueLen(l) 1 -#define dbgMemSetDeferSizeThreshold(s) 1 -#define dbgMemSetEntryHandler(f) 0 -#define dbgMemSetExitHandler(f) 0 -#define dbgMemSetFreeFill(c) 1 -#define dbgMemSetGuardFill(c) 1 -#define dbgMemSetGuardSize(s) 1 -#define dbgMemSetInUseFill(c) 1 -#define dbgMemSetCallstackChains(s) 1 -#define dbgMemSetStackChecking(s) 1 -#define dbgMemSetSafetyLevel(s) 1 -#define dbgMemSettingsInfo(b) 1 -#define dbgMemSuppressFreeFill(b) 1 -#define dbgMemTotalCount() 1 -#define dbgMemTotalSize() 1 -#define dbgMemWalkHeap(b) MEM_POOL_OK -#endif /* dbgMemBreakpoint */ - -#endif /* MEM_DEBUG */ -#endif /* _SHI_dbgMacros */ - -#if defined(__WATCOMC__) && defined(__SW_3S) -/* Watcom stack calling convention */ - #pragma aux MemDefaultPool "_*"; - #pragma aux MemDefaultPoolBlockSizeFS "_*"; - #pragma aux MemDefaultPoolPageSize "_*"; - #pragma aux MemDefaultPoolFlags "_*"; - #pragma aux SmartHeap_malloc "_*"; - #pragma aux SmartHeap_far_malloc "_*"; - #pragma aux SmartHeap_new "_*"; -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* !defined(_SMARTHEAP_PROT) */ +/* smrtheap.h -- SmartHeap (tm) public C header file + * Professional Memory Management Library + * + * Copyright (C) 1991-1997 by Arthur D. Applegate. All Rights Reserved. + * All Rights Reserved. + * + * No part of this source code may be copied, modified or reproduced + * in any form without retaining the above copyright notice. + * This source code, or source code derived from it, may not be redistributed + * without express written permission of the author. + * + */ + +#if !defined(_SMARTHEAP_H) +#define _SMARTHEAP_H + +#include +#include + +#if !defined(macintosh) && !defined(THINK_C) && !defined(__MWERKS__) \ + && !defined(SHANSI) && UINT_MAX == 0xFFFFu \ + && (defined(_Windows) || defined(_WINDOWS) || defined(__WINDOWS__)) + #define MEM_WIN16 +#endif + +#if (UINT_MAX == 0xFFFFu) && (defined(MEM_WIN16) \ + || defined(MSDOS) || defined(__MSDOS__) || defined(__DOS__)) + /* 16-bit X86 */ + #if defined(SYS_DLL) + #if defined(_MSC_VER) && _MSC_VER <= 600 + #define MEM_ENTRY _export _loadds far pascal + #else + #define MEM_ENTRY _export far pascal + #endif + #else + #define MEM_ENTRY far pascal + #endif + #ifdef __WATCOMC__ + #define MEM_ENTRY_ANSI __far + #else + #define MEM_ENTRY_ANSI far cdecl + #endif + #define MEM_FAR far + #if defined(MEM_WIN16) + #define MEM_ENTRY2 _export far pascal + #elif defined(DOS16M) || defined(DOSX286) + #define MEM_ENTRY2 _export _loadds far pascal + #endif + +#else /* not 16-bit X86 */ + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) \ + || defined(__WIN32__) || defined(__NT__) + #define MEM_WIN32 + #if defined(_MSC_VER) + #if defined(_SHI_Pool) && defined(SYS_DLL) + #define MEM_ENTRY1 __declspec(dllexport) + #define MEM_ENTRY4 __declspec(dllexport) extern + #elif !defined(_SHI_Pool) && (defined(MEM_DEBUG) || defined(MEM_DLL)) + #define MEM_ENTRY1 __declspec(dllimport) + #if defined(_M_IX86) || defined(_X86_) + #define MemDefaultPool shi_MemDefaultPool + #define MEM_ENTRY4 __declspec(dllimport) + #endif + #endif + #endif + #if !defined(_MSC_VER) || defined(_M_IX86) || defined(_X86_) + #define MEM_ENTRY __stdcall + #else + #define MEM_ENTRY __cdecl /* for NT/RISC */ + #endif + #ifndef __WATCOMC__ + #define MEM_ENTRY_ANSI __cdecl + #endif + +#elif defined(__OS2__) + #if defined(__BORLANDC__) || defined(__WATCOMC__) + #if defined(SYS_DLL) + #define MEM_ENTRY __export __syscall + #else + #define MEM_ENTRY __syscall + #endif /* SYS_DLL */ + #ifdef __BORLANDC__ + #define MEM_ENTRY_ANSI __stdcall + #endif + #elif defined(__IBMC__) || defined(__IBMCPP__) + #if defined(SYS_DLL) && 0 + #define MEM_ENTRY _Export _System + #else + #define MEM_ENTRY _System + #endif + #define MEM_ENTRY_ANSI _Optlink + #define MEM_ENTRY3 MEM_ENTRY + #define MEM_CALLBACK MEM_ENTRY3 + #define MEM_ENTRY2 + #endif +#endif /* __OS2__ */ + +#if defined(__WATCOMC__) && defined(__SW_3S) + /* Watcom stack calling convention */ +#ifndef __OS2__ +#ifdef __WINDOWS_386__ + #pragma aux syscall "*_" parm routine [eax ebx ecx edx fs gs] modify [eax]; +#else + #pragma aux syscall "*_" parm routine [eax ebx ecx edx] modify [eax]; +#endif +#ifndef MEM_ENTRY + #define MEM_ENTRY __syscall +#endif /* MEM_ENTRY */ +#endif +#endif /* Watcom stack calling convention */ + +#endif /* end of system-specific declarations */ + +#ifndef MEM_ENTRY + #define MEM_ENTRY +#endif +#ifndef MEM_ENTRY1 + #define MEM_ENTRY1 +#endif +#ifndef MEM_ENTRY2 + #define MEM_ENTRY2 MEM_ENTRY +#endif +#ifndef MEM_ENTRY3 + #define MEM_ENTRY3 +#endif +#ifndef MEM_ENTRY4 + #define MEM_ENTRY4 extern +#endif +#ifndef MEM_CALLBACK +#define MEM_CALLBACK MEM_ENTRY2 +#endif +#ifndef MEM_ENTRY_ANSI + #define MEM_ENTRY_ANSI +#endif +#ifndef MEM_FAR + #define MEM_FAR +#endif + +#ifdef applec +/* Macintosh: Apple MPW C/C++ passes char/short parms as longs (4 bytes), + * whereas Symantec C/C++ for MPW passes these as words (2 bytes); + * therefore, canonicalize all integer parms as 'int' for this platform. + */ + #define MEM_USHORT unsigned + #define MEM_UCHAR unsigned +#else + #define MEM_USHORT unsigned short + #define MEM_UCHAR unsigned char +#endif /* applec */ + +#ifdef MEM_DEBUG +#include "heapagnt.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*** Types ***/ + +#ifndef MEM_BOOL_DEFINED +#define MEM_BOOL_DEFINED +typedef int MEM_BOOL; +#endif + +/* Version Masks */ +typedef unsigned MEM_VERSION; +#define MEM_MAJOR_VERSION(v) (((v) & 0xF000u) >> 12) +#define MEM_MINOR_VERSION(v) (((v) & 0x0F00u) >> 8) +#define MEM_UPDATE_VERSION(v) ((v) & 0x00FFu) + +/* Note: these types are struct's rather than integral types to facilitate + * compile-time type-checking. MEM_POOL and MEM_HANDLE should be regarded + * as black boxes, and treated just like handles. + * You should not have any type casts to or from MEM_POOL or MEM_HANDLE; + * nor should you dereference variables of type MEM_POOL or MEM_HANDLE + * (unless you are using SmartHeap to replace NewHandle on the Mac, and + * you have existing code that dereferences handles). + */ +#ifndef MEM_POOL_DEFINED +#define MEM_POOL_DEFINED +#ifdef _SHI_Pool + typedef struct _SHI_Pool MEM_FAR *MEM_POOL; + typedef struct _SHI_MovHandle MEM_FAR *MEM_HANDLE; +#else + #ifdef THINK_C + typedef void *MEM_POOL; + typedef void **MEM_HANDLE; + #else + typedef struct _SHI_Pool { int reserved; } MEM_FAR *MEM_POOL; + typedef struct _SHI_MovHandle { int reserved; } MEM_FAR *MEM_HANDLE; + #endif +#endif +#endif /* MEM_POOL_DEFINED */ + + +#if !defined(MEM_DEBUG) || !(defined(MEM_WIN16) || defined(MEM_WIN32)) +#define SHI_MAJOR_VERSION 3 +#define SHI_MINOR_VERSION 3 +#define SHI_UPDATE_LEVEL 0 +#endif /* !WINDOWS */ + +#ifndef MEM_DEBUG + +/* Error codes: errorCode field of MEM_ERROR_INFO */ +#ifndef MEM_ERROR_CODE_DEFINED +#define MEM_ERROR_CODE_DEFINED +typedef enum +{ + MEM_NO_ERROR=0, + MEM_INTERNAL_ERROR, + MEM_OUT_OF_MEMORY, + MEM_BLOCK_TOO_BIG, + MEM_ALLOC_ZERO, + MEM_RESIZE_FAILED, + MEM_LOCK_ERROR, + MEM_EXCEEDED_CEILING, + MEM_TOO_MANY_PAGES, + MEM_TOO_MANY_TASKS, + MEM_BAD_MEM_POOL, + MEM_BAD_BLOCK, + MEM_BAD_FREE_BLOCK, + MEM_BAD_HANDLE, + MEM_BAD_POINTER, + MEM_WRONG_TASK, + MEM_NOT_FIXED_SIZE, + MEM_BAD_FLAGS, + MEM_ERROR_CODE_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_ERROR_CODE; +#endif /* MEM_ERROR_CODE_DEFINED */ + + +/* ### we should have packing pragma around these structure decls in case + * ### user is compiling with non-default packing directive (only needed + * ### if user is packing more strictly than native int size *and* if + * ### native int size is != native long and ptr sizes) + */ + +/* Error info, passed to error-handling callback routine */ +#ifndef MEM_ERROR_INFO_DEFINED +#define MEM_ERROR_INFO_DEFINED +typedef struct _MEM_ERROR_INFO +{ + MEM_ERROR_CODE errorCode; /* error code identifying type of error */ + MEM_POOL pool; /* pool in which error occurred, if known */ +} MEM_ERROR_INFO; + +/* Error handling callback function */ +typedef MEM_BOOL (MEM_ENTRY2 * MEM_ENTRY3 MEM_ERROR_FN) + (MEM_ERROR_INFO MEM_FAR *); + +#endif /* MEM_ERROR_INFO_DEFINED */ + +#endif /* MEM_DEBUG */ + + +#ifndef MEM_BLOCK_TYPE_DEFINED +#define MEM_BLOCK_TYPE_DEFINED +/* Block Type: field of MEM_POOL_ENTRY, field of MEM_POOL_INFO, + * parameter to MemPoolPreAllocate + */ +typedef enum +{ + MEM_FS_BLOCK = 0x0001u, + MEM_VAR_MOVEABLE_BLOCK = 0x0002u, + MEM_VAR_FIXED_BLOCK = 0x0004u, + MEM_EXTERNAL_BLOCK = 0x0008u, + MEM_BLOCK_TYPE_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_BLOCK_TYPE; +#endif /* MEM_BLOCK_TYPE_DEFINED */ + +#ifndef MEM_POOL_ENTRY_DEFINED +#define MEM_POOL_ENTRY_DEFINED +/* Pool Entry: parameter to MemPoolWalk */ +typedef struct +{ + void MEM_FAR *entry; + MEM_POOL pool; + MEM_BLOCK_TYPE type; + MEM_BOOL isInUse; + unsigned long size; + MEM_HANDLE handle; + unsigned lockCount; + void MEM_FAR *reserved_ptr; +} MEM_POOL_ENTRY; +#endif /* MEM_POOL_ENTRY_DEFINED */ + +#ifndef MEM_POOL_STATUS_DEFINED +#define MEM_POOL_STATUS_DEFINED +/* Pool Status: returned by MemPoolWalk, MemPoolFirst, MemPoolNext */ +typedef enum +{ + MEM_POOL_OK = 1, + MEM_POOL_CORRUPT = -1, + MEM_POOL_CORRUPT_FATAL = -2, + MEM_POOL_END = 0, + MEM_POOL_STATUS_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_POOL_STATUS; +#endif /* MEM_POOL_STATUS_DEFINED */ + +#ifndef MEM_POINTER_STATUS_DEFINED +#define MEM_POINTER_STATUS_DEFINED +/* Pointer Status: returned by MemCheckPtr */ +typedef enum +{ + MEM_POINTER_OK = 1, + MEM_POINTER_WILD = 0, + MEM_POINTER_FREE = -1, + MEM_POINTER_STATUS_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_POINTER_STATUS; +#endif /* MEM_POINTER_STATUS_DEFINED */ + +/* Pool Info: parameter to MemPoolInfo, MemPoolFirst, MemPoolNext */ +typedef struct +{ + MEM_POOL pool; + MEM_BLOCK_TYPE type; /* disjunctive combination of block type flags */ + unsigned short blockSizeFS; + unsigned short smallBlockSize; + unsigned pageSize; + unsigned long floor; + unsigned long ceiling; + unsigned flags; + MEM_ERROR_FN errorFn; +} MEM_POOL_INFO; + +/* Flags passed to MemAlloc, MemAllocPtr, MemReAlloc, MemReAllocPtr */ +#define MEM_FIXED 0x0000u /* fixed handle-based block */ +#define MEM_ZEROINIT 0x0001u /* == TRUE for SH 1.5 compatibility */ +#define MEM_MOVEABLE 0x0002u /* moveable handle-based block */ +#define MEM_RESIZEABLE 0x0004u /* reserve space above block */ +#define MEM_RESIZE_IN_PLACE 0x0008u /* do not move block (realloc) */ +#define MEM_NOGROW 0x0010u /* do not grow heap to satisfy request */ +#define MEM_NOEXTERNAL 0x0020u /* reserved for internal use */ +#define MEM_NOCOMPACT 0x0040u /* do not compact to satisfy request */ +#define MEM_NO_SERIALIZE 0x0080u /* do not serialize this request */ +#define MEM_HANDLEBASED 0x4000u /* for internal use */ +#define MEM_RESERVED 0x8000u /* for internal use */ + +#define MEM_UNLOCK_FAILED USHRT_MAX + +/* Flags passed to MemPoolInit, MemPoolInitFS */ +#ifndef MEM_POOL_SHARED +#define MEM_POOL_SHARED 0x0001u /* == TRUE for SH 1.5 compatibility */ +#define MEM_POOL_SERIALIZE 0x0002u /* pool used in more than one thread */ +#define MEM_POOL_VIRTUAL_LOCK 0x0004u /* pool is locked in physical memory */ +#define MEM_POOL_ZEROINIT 0x0008u /* malloc/new from pool zero-inits */ +#define MEM_POOL_REGION 0x0010u /* store pool in user-supplied region*/ +#define MEM_POOL_DEFAULT 0x8000u /* pool with default characteristics */ +#endif /* MEM_POOL_SHARED */ + +MEM_ENTRY4 MEM_POOL MemDefaultPool; + +/* Default memory pool for C malloc, C++ new (for backwards compatibility) */ +#define MEM_DEFAULT_POOL MemDefaultPool + +/* define and initialize these variables at file scope to change defaults */ +extern unsigned short MemDefaultPoolBlockSizeFS; +extern unsigned MemDefaultPoolPageSize; +extern unsigned MemDefaultPoolFlags; + +/* define SmartHeap_malloc at file scope if you + * are intentionally _NOT_ linking in the SmartHeap malloc definition + * ditto for SmartHeap operator new, and fmalloc et al. + */ +extern int SmartHeap_malloc; +extern int SmartHeap_far_malloc; +extern int SmartHeap_new; + +#define MEM_ERROR_RET ULONG_MAX + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !defined(_SMARTHEAP_H) */ + + +/*** Function Prototypes ***/ + +#ifndef _SMARTHEAP_PROT +#define _SMARTHEAP_PROT + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _shAPI + #if defined(MEM_DEBUG) && !defined(SHI_NO_MEM_DEBUG) + #define _shAPI(ret, name) MEM_ENTRY1 ret MEM_ENTRY _dbg ## name + #else + #define _shAPI(ret, name) MEM_ENTRY1 ret MEM_ENTRY name + #endif +#endif + +#ifndef _dbgARGS + #if defined(MEM_DEBUG) && !defined(SHI_NO_MEM_DEBUG) + #define _dbgARGS1 const char MEM_FAR *, int + #define _dbgARGS , _dbgARGS1 + #else + #define _dbgARGS1 void + #define _dbgARGS + #endif +#endif + + +/**** HOW TO READ SmartHeap PROTOTYPES **** + * prototypes below have the follow syntax in order to support both debug + * and non-debug APIs with single-source: + * + * _shiAPI(, )([] _dbgARGS); + * + * the above translates to a C prototype as follows: + * + * ([]); + */ + +/* Library Version */ +MEM_ENTRY1 MEM_VERSION MEM_ENTRY MemVersion(void); + +/* Library Registration */ +_shAPI(MEM_BOOL, MemRegisterTask)(_dbgARGS1); +_shAPI(MEM_BOOL, MemUnregisterTask)(_dbgARGS1); + +/* Memory Pool Functions */ +_shAPI(MEM_POOL, MemPoolInit)(unsigned _dbgARGS); +_shAPI(MEM_POOL, MemPoolInitFS)(MEM_USHORT, unsigned long, + unsigned _dbgARGS); +_shAPI(MEM_POOL, MemPoolInitRegion)(void MEM_FAR *, + unsigned long size, unsigned _dbgARGS); +_shAPI(MEM_POOL, MemPoolInitNamedShared)(const char MEM_FAR *, + unsigned long size,unsigned _dbgARGS); +_shAPI(MEM_POOL, MemPoolInitNamedSharedEx)(void MEM_FAR *addr, + unsigned pidCount, unsigned long MEM_FAR *pids, void MEM_FAR *security, + const char MEM_FAR *name, unsigned long size, unsigned flags _dbgARGS); +_shAPI(MEM_POOL, MemPoolAttachShared)(MEM_POOL, const char MEM_FAR * _dbgARGS); +_shAPI(MEM_BOOL, MemPoolFree)(MEM_POOL _dbgARGS); +MEM_POOL MEM_ENTRY MemInitDefaultPool(void); +MEM_BOOL MEM_ENTRY MemFreeDefaultPool(void); +_shAPI(unsigned, MemPoolSetPageSize)(MEM_POOL, unsigned _dbgARGS); +_shAPI(MEM_BOOL, MemPoolSetBlockSizeFS)(MEM_POOL, MEM_USHORT _dbgARGS); +_shAPI(MEM_BOOL, MemPoolSetSmallBlockSize)(MEM_POOL, MEM_USHORT _dbgARGS); +_shAPI(unsigned long, MemPoolSetFloor)(MEM_POOL, unsigned long _dbgARGS); +_shAPI(unsigned long, MemPoolSetCeiling)(MEM_POOL, unsigned long _dbgARGS); +_shAPI(unsigned long, MemPoolPreAllocate)(MEM_POOL, unsigned long, + MEM_BLOCK_TYPE _dbgARGS); +_shAPI(unsigned long, MemPoolPreAllocateHandles)(MEM_POOL, + unsigned long _dbgARGS); +_shAPI(unsigned long, MemPoolShrink)(MEM_POOL _dbgARGS); +_shAPI(unsigned long, MemPoolSize)(MEM_POOL _dbgARGS); +_shAPI(unsigned long, MemPoolCount)(MEM_POOL _dbgARGS); +_shAPI(MEM_BOOL, MemPoolInfo)(MEM_POOL, void MEM_FAR *, + MEM_POOL_INFO MEM_FAR* _dbgARGS); +_shAPI(MEM_POOL_STATUS, MemPoolFirst)(MEM_POOL_INFO MEM_FAR *, + MEM_BOOL _dbgARGS); +_shAPI(MEM_POOL_STATUS,MemPoolNext)(MEM_POOL_INFO MEM_FAR*,MEM_BOOL _dbgARGS); +_shAPI(MEM_POOL_STATUS,MemPoolWalk)(MEM_POOL,MEM_POOL_ENTRY MEM_FAR*_dbgARGS); +_shAPI(MEM_BOOL, MemPoolCheck)(MEM_POOL _dbgARGS); +_shAPI(MEM_BOOL, MemPoolLock)(MEM_POOL _dbgARGS); +_shAPI(MEM_BOOL, MemPoolUnlock)(MEM_POOL _dbgARGS); + +/* Handle-based API for moveable memory within heap. */ +_shAPI(MEM_HANDLE, MemAlloc)(MEM_POOL, unsigned, unsigned long _dbgARGS); +_shAPI(MEM_HANDLE, MemReAlloc)(MEM_HANDLE,unsigned long,unsigned _dbgARGS); +_shAPI(MEM_BOOL, MemFree)(MEM_HANDLE _dbgARGS); +_shAPI(void MEM_FAR *, MemLock)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned, MemUnlock)(MEM_HANDLE _dbgARGS); +_shAPI(void MEM_FAR *, MemFix)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned, MemUnfix)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned, MemLockCount)(MEM_HANDLE _dbgARGS); +#ifndef MemFlags +#define MemFlags(mem) MemLockCount(mem) +#endif +_shAPI(MEM_BOOL, MemIsMoveable)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned long, MemSize)(MEM_HANDLE _dbgARGS); +_shAPI(unsigned long, MemSizeRequested)(MEM_HANDLE _dbgARGS); +_shAPI(MEM_HANDLE, MemHandle)(void MEM_FAR * _dbgARGS); +#ifndef MEM_REFERENCE + #ifdef MEM_DEBUG + MEM_ENTRY1 void MEM_FAR * MEM_ENTRY _dbgMemReference(MEM_HANDLE, + const char MEM_FAR *, int); + #define MEM_REFERENCE(handle) \ + _dbgMemReference(handle, __FILE__, __LINE__) + #else + #define MEM_REFERENCE(handle) (*(void MEM_FAR * MEM_FAR *)handle) + #endif +#endif + +/* General Heap Allocator (returns direct pointer to memory) */ +_shAPI(void MEM_FAR*,MemAllocPtr)(MEM_POOL,unsigned long,unsigned _dbgARGS); +_shAPI(void MEM_FAR *, MemReAllocPtr)(void MEM_FAR *, unsigned long, + unsigned _dbgARGS); +_shAPI(MEM_BOOL, MemFreePtr)(void MEM_FAR * _dbgARGS); +_shAPI(unsigned long, MemSizePtr)(void MEM_FAR * _dbgARGS); +_shAPI(MEM_POINTER_STATUS, MemCheckPtr)(MEM_POOL, void MEM_FAR * _dbgARGS); + +/* Fixed-Size Allocator */ +_shAPI(void MEM_FAR *, MemAllocFS)(MEM_POOL _dbgARGS); +_shAPI(MEM_BOOL, MemFreeFS)(void MEM_FAR * _dbgARGS); + +/* Error Handling Functions */ +MEM_ENTRY1 MEM_ERROR_FN MEM_ENTRY MemSetErrorHandler(MEM_ERROR_FN); +MEM_ENTRY1 MEM_BOOL MEM_ENTRY MemDefaultErrorHandler(MEM_ERROR_INFO MEM_FAR*); +MEM_ENTRY1 void MEM_ENTRY MemErrorUnwind(void); + +#ifdef MEM_WIN32 +/* patching control */ + +#ifndef MEM_PATCHING_DEFINED +#define MEM_PATCHING_DEFINED +typedef enum +{ + MEM_PATCH_ALL = 0, + MEM_SKIP_PATCHING_THIS_DLL = 1, + MEM_DISABLE_SYSTEM_HEAP_PATCHING = 2, + MEM_DISABLE_ALL_PATCHING = 4|2|1, + MEM_PATCHING_INT_MAX = INT_MAX /* to ensure enum is full int in size */ +} MEM_PATCHING; +#endif /* MEM_PATCHING_DEFINED */ + +#ifdef _MSC_VER +__declspec(dllexport) +#endif +MEM_PATCHING MEM_ENTRY MemSetPatching(const char ***skipDLLs); + +#endif /* MEM_WIN32 */ + +/* internal routines */ +MEM_ENTRY1 MEM_BOOL MEM_ENTRY _shi_enterCriticalSection(void); +MEM_ENTRY1 void MEM_ENTRY _shi_leaveCriticalSection(void); +MEM_BOOL shi_call_new_handler_msc(size_t, MEM_BOOL); + + +/* Wrapper macros for debugging API */ +#ifndef _SHI_dbgMacros +#ifdef MEM_DEBUG +#define MemRegisterTask() _dbgMemRegisterTask(__FILE__, __LINE__) +#define MemUnregisterTask() _dbgMemUnregisterTask(__FILE__, __LINE__) +#define MemPoolInit(flags) _dbgMemPoolInit(flags, __FILE__, __LINE__) +#define MemPoolInitFS(bs, bc, f) _dbgMemPoolInitFS(bs,bc,f,__FILE__,__LINE__) +#define MemPoolInitRegion(addr, sz, f) \ + _dbgMemPoolInitRegion(addr, sz, f, __FILE__, __LINE__) +#define MemPoolInitNamedShared(nm, sz, f) \ + _dbgMemPoolInitNamedShared(nm, sz, f, __FILE__, __LINE__) +#define MemPoolInitNamedSharedEx(a, c, p, sec, nm, sz, f) \ + _dbgMemPoolInitNamedSharedEx(a, c, p, sec, nm, sz, f, __FILE__, __LINE__) +#define MemPoolAttachShared(p, n) \ + _dbgMemPoolAttachShared(p, n, __FILE__, __LINE__) +#define MemPoolFree(pool) _dbgMemPoolFree(pool, __FILE__, __LINE__) +#define MemPoolSetPageSize(p, s) _dbgMemPoolSetPageSize(p,s,__FILE__,__LINE__) +#define MemPoolSetBlockSizeFS(p, s) \ + _dbgMemPoolSetBlockSizeFS(p, s, __FILE__, __LINE__) +#define MemPoolSetSmallBlockSize(p, s) \ + _dbgMemPoolSetSmallBlockSize(p, s, __FILE__, __LINE__) +#define MemPoolSetFloor(p, f) _dbgMemPoolSetFloor(p, f, __FILE__, __LINE__) +#define MemPoolSetCeiling(p, c) _dbgMemPoolSetCeiling(p,c,__FILE__, __LINE__) +#define MemPoolPreAllocate(p,s,t) \ + _dbgMemPoolPreAllocate(p,s,t,__FILE__, __LINE__) +#define MemPoolPreAllocateHandles(p,h) \ + _dbgMemPoolPreAllocateHandles(p,h,__FILE__, __LINE__) +#define MemPoolShrink(p) _dbgMemPoolShrink(p, __FILE__, __LINE__) +#define MemPoolCheck(p) _dbgMemPoolCheck(p, __FILE__, __LINE__) +#define MemPoolWalk(p, e) _dbgMemPoolWalk(p, e, __FILE__, __LINE__) +#define MemPoolSize(p) _dbgMemPoolSize(p, __FILE__, __LINE__) +#define MemPoolCount(p) _dbgMemPoolCount(p, __FILE__, __LINE__) +#define MemPoolInfo(p,x,i) _dbgMemPoolInfo(p,x,i, __FILE__, __LINE__) +#define MemPoolFirst(i, b) _dbgMemPoolFirst(i, b, __FILE__, __LINE__) +#define MemPoolNext(i, b) _dbgMemPoolNext(i, b, __FILE__, __LINE__) +#define MemPoolLock(p) _dbgMemPoolLock(p, __FILE__, __LINE__) +#define MemPoolUnlock(p) _dbgMemPoolUnlock(p, __FILE__, __LINE__) +#define MemAlloc(p, f, s) _dbgMemAlloc(p, f, s, __FILE__, __LINE__) +#define MemReAlloc(h, s, f) _dbgMemReAlloc(h, s, f, __FILE__, __LINE__) +#define MemFree(h) _dbgMemFree(h, __FILE__, __LINE__) +#define MemLock(h) _dbgMemLock(h, __FILE__, __LINE__) +#define MemUnlock(h) _dbgMemUnlock(h, __FILE__, __LINE__) +#define MemFix(h) _dbgMemFix(h, __FILE__, __LINE__) +#define MemUnfix(h) _dbgMemUnfix(h, __FILE__, __LINE__) +#define MemSize(h) _dbgMemSize(h, __FILE__, __LINE__) +#define MemSizeRequested(h) _dbgMemSizeRequested(h, __FILE__, __LINE__) +#define MemLockCount(h) _dbgMemLockCount(h, __FILE__, __LINE__) +#define MemIsMoveable(h) _dbgMemIsMoveable(h, __FILE__, __LINE__) +#define MemHandle(p) _dbgMemHandle(p, __FILE__, __LINE__) +#define MemAllocPtr(p, s, f) _dbgMemAllocPtr(p, s, f, __FILE__, __LINE__) +#define MemReAllocPtr(p, s, f) _dbgMemReAllocPtr(p, s, f, __FILE__,__LINE__) +#define MemFreePtr(p) _dbgMemFreePtr(p, __FILE__, __LINE__) +#define MemSizePtr(p) _dbgMemSizePtr(p, __FILE__, __LINE__) +#define MemCheckPtr(p, x) _dbgMemCheckPtr(p, x, __FILE__, __LINE__) +#define MemAllocFS(p) _dbgMemAllocFS(p, __FILE__, __LINE__) +#define MemFreeFS(p) _dbgMemFreeFS(p, __FILE__, __LINE__) + +#else /* MEM_DEBUG */ + +/* MEM_DEBUG not defined: define dbgMemXXX as no-op macros + * each macro returns "success" value when MEM_DEBUG not defined + */ +#ifndef dbgMemBreakpoint +#define dbgMemBreakpoint() ((void)0) +#define dbgMemCheckAll() 1 +#define dbgMemCheckPtr(p, f, s) 1 +#define dbgMemDeferFreeing(b) 1 +#define dbgMemFormatCall(i, b, s) 0 +#define dbgMemFormatErrorInfo(i, b, s) 0 +#define dbgMemPoolDeferFreeing(p, b) 1 +#define dbgMemFreeDeferred() 1 +#define dbgMemPoolFreeDeferred(p) 1 +#define dbgMemPoolInfo(p, b) 1 +#define dbgMemPoolSetCheckFrequency(p, f) 1 +#define dbgMemPoolSetDeferQueueLen(p, b) 1 +#define dbgMemPoolSetName(p, n) 1 +#define dbgMemProtectPtr(p, f) 1 +#define dbgMemPtrInfo(p, b) 1 +#define dbgMemReallocMoves(b) 1 +#define dbgMemReportLeakage(p, c1, c2) 1 +#define dbgMemReportWrongTaskRef(b) 1 +#define dbgMemScheduleChecking(b, p, i) 1 +#define dbgMemSetCheckFrequency(f) 1 +#define dbgMemSetCheckpoint(c) 1 +#define dbgMemSetDefaultErrorOutput(x, f) 1 +#define dbgMemSetDeferQueueLen(l) 1 +#define dbgMemSetDeferSizeThreshold(s) 1 +#define dbgMemSetEntryHandler(f) 0 +#define dbgMemSetExitHandler(f) 0 +#define dbgMemSetFreeFill(c) 1 +#define dbgMemSetGuardFill(c) 1 +#define dbgMemSetGuardSize(s) 1 +#define dbgMemSetInUseFill(c) 1 +#define dbgMemSetCallstackChains(s) 1 +#define dbgMemSetStackChecking(s) 1 +#define dbgMemSetSafetyLevel(s) 1 +#define dbgMemSettingsInfo(b) 1 +#define dbgMemSuppressFreeFill(b) 1 +#define dbgMemTotalCount() 1 +#define dbgMemTotalSize() 1 +#define dbgMemWalkHeap(b) MEM_POOL_OK +#endif /* dbgMemBreakpoint */ + +#endif /* MEM_DEBUG */ +#endif /* _SHI_dbgMacros */ + +#if defined(__WATCOMC__) && defined(__SW_3S) +/* Watcom stack calling convention */ + #pragma aux MemDefaultPool "_*"; + #pragma aux MemDefaultPoolBlockSizeFS "_*"; + #pragma aux MemDefaultPoolPageSize "_*"; + #pragma aux MemDefaultPoolFlags "_*"; + #pragma aux SmartHeap_malloc "_*"; + #pragma aux SmartHeap_far_malloc "_*"; + #pragma aux SmartHeap_new "_*"; +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !defined(_SMARTHEAP_PROT) */