mirror of
https://github.com/isledecomp/isle.git
synced 2026-01-21 07:11:16 +00:00
Merge branch 'isledecomp:master' into newguy
This commit is contained in:
commit
671f306fd2
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -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
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ Release/
|
||||
ISLE.EXE
|
||||
LEGO1.DLL
|
||||
build/
|
||||
*.swp
|
||||
|
||||
BIN
3rdparty/smartheap/SHLW32MT.LIB
vendored
Normal file
BIN
3rdparty/smartheap/SHLW32MT.LIB
vendored
Normal file
Binary file not shown.
63
3rdparty/smartheap/SHMALLOC.H
vendored
Normal file
63
3rdparty/smartheap/SHMALLOC.H
vendored
Normal file
@ -0,0 +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) */
|
||||
BIN
3rdparty/smartheap/SHMFC4M.LIB
vendored
Normal file
BIN
3rdparty/smartheap/SHMFC4M.LIB
vendored
Normal file
Binary file not shown.
656
3rdparty/smartheap/SMRTHEAP.H
vendored
Normal file
656
3rdparty/smartheap/SMRTHEAP.H
vendored
Normal file
@ -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 <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#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(<return-type>, <API name>)([<parms>] _dbgARGS);
|
||||
*
|
||||
* the above translates to a C prototype as follows:
|
||||
*
|
||||
* <return-type> <API name>([<parms>]);
|
||||
*/
|
||||
|
||||
/* 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) */
|
||||
159
3rdparty/smartheap/SMRTHEAP.HPP
vendored
Normal file
159
3rdparty/smartheap/SMRTHEAP.HPP
vendored
Normal file
@ -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 <new.h>
|
||||
|
||||
#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) <type>'
|
||||
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]) <type>'
|
||||
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) <type>'
|
||||
#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) */
|
||||
@ -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
|
||||
@ -134,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
|
||||
@ -177,6 +179,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 +206,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)
|
||||
|
||||
|
||||
@ -11,4 +11,24 @@
|
||||
#define COMPAT_CONST
|
||||
#endif
|
||||
|
||||
#endif // ISLECOMPAT_H
|
||||
#define MSVC420_VERSION 1020
|
||||
|
||||
// STL compatibility.
|
||||
#if defined(_MSC_VER) && _MSC_VER <= MSVC420_VERSION
|
||||
#include <STL.H>
|
||||
#else
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
using namespace std;
|
||||
template <class T>
|
||||
using List = list<T>;
|
||||
#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.
|
||||
#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
|
||||
|
||||
@ -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
|
||||
#endif // LEGOSTREAM_H
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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
|
||||
@ -30,8 +31,13 @@ class MxCore
|
||||
return !strcmp(name, MxCore::ClassName());
|
||||
}
|
||||
|
||||
inline MxU32 GetId()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int m_id;
|
||||
MxU32 m_id;
|
||||
|
||||
};
|
||||
|
||||
|
||||
34
LEGO1/mxdisplaysurface.h
Normal file
34
LEGO1/mxdisplaysurface.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef MXDISPLAYSURFACE_H
|
||||
#define MXDISPLAYSURFACE_H
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include "mxcore.h"
|
||||
#include "mxpalette.h"
|
||||
#include "mxvideoparam.h"
|
||||
|
||||
#include "decomp.h"
|
||||
|
||||
// VTABLE 0x100dc768
|
||||
class MxDisplaySurface : public MxCore
|
||||
{
|
||||
public:
|
||||
MxDisplaySurface();
|
||||
virtual ~MxDisplaySurface() override;
|
||||
|
||||
virtual MxResult Init(MxVideoParam *p_videoParam, LPDIRECTDRAWSURFACE p_surface1, LPDIRECTDRAWSURFACE p_surface2, LPDIRECTDRAWCLIPPER p_clipper);
|
||||
virtual MxResult Create(MxVideoParam *p_videoParam);
|
||||
virtual void Clear();
|
||||
virtual void SetPalette(MxPalette *p_palette);
|
||||
virtual void vtable24(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4);
|
||||
virtual MxBool vtable28(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4);
|
||||
virtual MxBool vtable2c(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool);
|
||||
virtual MxBool vtable30(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, MxBool);
|
||||
virtual undefined4 vtable34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4);
|
||||
virtual void Display(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4);
|
||||
virtual undefined4 vtable3c(undefined4*);
|
||||
virtual undefined4 vtable40(undefined4);
|
||||
virtual undefined4 vtable44(undefined4, undefined4*, undefined4, undefined4);
|
||||
};
|
||||
|
||||
#endif // MXDISPLAYSURFACE_H
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// OFFSET: LEGO1 0x100c92c0
|
||||
MxDSSound::MxDSSound()
|
||||
{
|
||||
// TODO
|
||||
this->m_lastField = 0x4f;
|
||||
this->SetType(MxDSType_Sound);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
#include "mxioinfo.h"
|
||||
#include "decomp.h"
|
||||
|
||||
// This class should be 72 bytes in size, same as the MMIOINFO struct.
|
||||
// The current implementation has MMIOINFO as the only member of the class,
|
||||
// but this assert will enforce the size if we decide to change that.
|
||||
DECOMP_SIZE_ASSERT(MXIOINFO, sizeof(MMIOINFO));
|
||||
|
||||
// OFFSET: LEGO1 0x100cc800
|
||||
MXIOINFO::MXIOINFO()
|
||||
{
|
||||
memset(&m_info, 0, sizeof(MMIOINFO));
|
||||
memset(&m_info, 0, sizeof(m_info));
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100cc820
|
||||
@ -13,37 +19,427 @@ MXIOINFO::~MXIOINFO()
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100cc830
|
||||
MxU16 MXIOINFO::Open(const char *filename, DWORD fdwOpen)
|
||||
MxU16 MXIOINFO::Open(const char *p_filename, MxULong p_flags)
|
||||
{
|
||||
return 0;
|
||||
OFSTRUCT _unused;
|
||||
MxU16 result = 0;
|
||||
|
||||
m_info.lBufOffset = 0;
|
||||
m_info.lDiskOffset = 0;
|
||||
|
||||
// Cast of p_flags to u16 forces the `movzx` instruction
|
||||
m_info.hmmio = (HMMIO)OpenFile(p_filename, &_unused, (MxU16)p_flags);
|
||||
|
||||
if ((HFILE)m_info.hmmio != HFILE_ERROR) {
|
||||
m_info.dwFlags = p_flags;
|
||||
if (p_flags & MMIO_ALLOCBUF) {
|
||||
|
||||
// Default buffer length of 8k if none specified
|
||||
int len = m_info.cchBuffer ? m_info.cchBuffer : 8192;
|
||||
HPSTR buf = new char[len];
|
||||
|
||||
if (!buf) {
|
||||
result = MMIOERR_OUTOFMEMORY;
|
||||
m_info.cchBuffer = 0;
|
||||
m_info.dwFlags &= ~MMIO_ALLOCBUF;
|
||||
m_info.pchBuffer = 0;
|
||||
} else {
|
||||
m_info.pchBuffer = buf;
|
||||
m_info.cchBuffer = len;
|
||||
}
|
||||
|
||||
m_info.pchEndRead = m_info.pchBuffer;
|
||||
m_info.pchNext = m_info.pchBuffer;
|
||||
m_info.pchEndWrite = m_info.pchBuffer + m_info.cchBuffer;
|
||||
}
|
||||
} else {
|
||||
result = MMIOERR_CANNOTOPEN;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100cc8e0
|
||||
void MXIOINFO::Close(MxLong arg)
|
||||
MxU16 MXIOINFO::Close(MxLong p_unused)
|
||||
{
|
||||
|
||||
MxU16 result = 0;
|
||||
|
||||
if (m_info.hmmio) {
|
||||
result = Flush(0);
|
||||
_lclose((HFILE)m_info.hmmio);
|
||||
m_info.hmmio = 0;
|
||||
|
||||
if (m_info.dwFlags & MMIO_ALLOCBUF)
|
||||
delete[] m_info.pchBuffer;
|
||||
|
||||
m_info.pchEndWrite = 0;
|
||||
m_info.pchEndRead = 0;
|
||||
m_info.pchBuffer = 0;
|
||||
m_info.dwFlags = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100cc930
|
||||
MxULong MXIOINFO::Read(HPSTR pch, LONG cch)
|
||||
MxLong MXIOINFO::Read(void *p_buf, MxLong p_len)
|
||||
{
|
||||
return 0;
|
||||
MxLong bytes_read = 0;
|
||||
|
||||
if (m_info.pchBuffer) {
|
||||
|
||||
int bytes_left = m_info.pchEndRead - m_info.pchNext;
|
||||
while (p_len > 0) {
|
||||
|
||||
if (bytes_left > 0) {
|
||||
if (p_len < bytes_left)
|
||||
bytes_left = p_len;
|
||||
|
||||
memcpy(p_buf, m_info.pchNext, bytes_left);
|
||||
p_len -= bytes_left;
|
||||
|
||||
m_info.pchNext += bytes_left;
|
||||
bytes_read += bytes_left;
|
||||
}
|
||||
|
||||
if (p_len <= 0 || Advance(0))
|
||||
break;
|
||||
|
||||
bytes_left = m_info.pchEndRead - m_info.pchNext;
|
||||
if (bytes_left <= 0)
|
||||
break;
|
||||
}
|
||||
} else if (m_info.hmmio && p_len > 0) {
|
||||
bytes_read = _hread((HFILE)m_info.hmmio, p_buf, p_len);
|
||||
|
||||
if (bytes_read == -1) {
|
||||
bytes_read = 0;
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
} else {
|
||||
m_info.lDiskOffset += bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100cca00
|
||||
LONG MXIOINFO::Seek(LONG lOffset, int iOrigin)
|
||||
MxLong MXIOINFO::Seek(MxLong p_offset, int p_origin)
|
||||
{
|
||||
return 0;
|
||||
MxLong result = -1;
|
||||
|
||||
// If buffered I/O
|
||||
if (m_info.pchBuffer) {
|
||||
if (p_origin == SEEK_CUR) {
|
||||
if (!p_offset) {
|
||||
// don't seek at all and just return where we are.
|
||||
return m_info.lBufOffset + (m_info.pchNext - m_info.pchBuffer);
|
||||
} else {
|
||||
// With SEEK_CUR, p_offset is a relative offset.
|
||||
// Get the absolute position instead and use SEEK_SET.
|
||||
p_offset += m_info.lBufOffset + (m_info.pchNext - m_info.pchBuffer);
|
||||
p_origin = SEEK_SET;
|
||||
}
|
||||
} else if (p_origin == SEEK_END) {
|
||||
// not possible with buffered I/O
|
||||
return -1;
|
||||
}
|
||||
|
||||
// else p_origin == SEEK_SET.
|
||||
|
||||
// is p_offset between the start and end of the buffer?
|
||||
// i.e. can we do the seek without reading more from disk?
|
||||
if (p_offset >= m_info.lBufOffset && p_offset < m_info.lBufOffset + m_info.cchBuffer) {
|
||||
m_info.pchNext = m_info.pchBuffer + (p_offset - m_info.lBufOffset);
|
||||
result = p_offset;
|
||||
} else {
|
||||
// we have to read another chunk from disk.
|
||||
if (m_info.hmmio && !Flush(0)) {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, p_offset, p_origin);
|
||||
|
||||
if (m_info.lDiskOffset == -1) {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
} else {
|
||||
|
||||
// align offset to buffer size
|
||||
int new_offset = p_offset - (p_offset % m_info.cchBuffer);
|
||||
m_info.lBufOffset = new_offset;
|
||||
|
||||
// do we need to seek again?
|
||||
// (i.e. are we already aligned to buffer size?)
|
||||
if (p_offset != new_offset) {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, new_offset, SEEK_SET);
|
||||
|
||||
if (m_info.lDiskOffset == -1) {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_info.lBufOffset == m_info.lDiskOffset) {
|
||||
// is the file open for writing only?
|
||||
if ((m_info.dwFlags & MMIO_RWMODE) &&
|
||||
((m_info.dwFlags & MMIO_RWMODE) != MMIO_READWRITE)) {
|
||||
|
||||
m_info.pchNext = m_info.pchBuffer - m_info.lBufOffset + p_offset;
|
||||
|
||||
result = p_offset;
|
||||
} else {
|
||||
// We can read from the file. Fill the buffer.
|
||||
int bytes_read = _hread((HFILE)m_info.hmmio, m_info.pchBuffer, m_info.cchBuffer);
|
||||
|
||||
if (bytes_read == -1) {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
} else {
|
||||
m_info.lDiskOffset += bytes_read;
|
||||
m_info.pchNext = p_offset - m_info.lBufOffset + m_info.pchBuffer;
|
||||
m_info.pchEndRead = m_info.pchBuffer + bytes_read;
|
||||
|
||||
if (m_info.pchNext < m_info.pchEndRead) {
|
||||
result = p_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No buffer so just seek the file directly (if we have a valid handle)
|
||||
if (m_info.hmmio) {
|
||||
// i.e. if we just want to get the current file position
|
||||
if (p_origin == SEEK_CUR && p_offset == 0) {
|
||||
return m_info.lDiskOffset;
|
||||
} else {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, p_offset, p_origin);
|
||||
|
||||
result = m_info.lDiskOffset;
|
||||
|
||||
if (result == -1) {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100ccbc0
|
||||
void MXIOINFO::SetBuffer(LPSTR pchBuffer, LONG cchBuffer, LONG unk)
|
||||
MxU16 MXIOINFO::SetBuffer(char *p_buf, MxLong p_len, MxLong p_unused)
|
||||
{
|
||||
|
||||
MxU16 result = Flush(0);
|
||||
|
||||
if (m_info.dwFlags & MMIO_ALLOCBUF) {
|
||||
m_info.dwFlags &= ~MMIO_ALLOCBUF;
|
||||
delete[] m_info.pchBuffer;
|
||||
}
|
||||
|
||||
m_info.pchBuffer = p_buf;
|
||||
m_info.cchBuffer = p_len;
|
||||
m_info.pchEndWrite = m_info.pchBuffer + m_info.cchBuffer;
|
||||
m_info.pchEndRead = m_info.pchBuffer;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100ccc10
|
||||
MxU16 MXIOINFO::Flush(MxU16 p_unused)
|
||||
{
|
||||
MxU16 result = 0;
|
||||
|
||||
// if buffer is dirty
|
||||
if (m_info.dwFlags & MMIO_DIRTY) {
|
||||
// if we have allocated an IO buffer
|
||||
if (m_info.pchBuffer) {
|
||||
// if we have a file open for writing
|
||||
if (m_info.hmmio && (m_info.dwFlags & MMIO_RWMODE)) {
|
||||
// (pulling this value out into a variable forces it into EBX)
|
||||
MxLong cchBuffer = m_info.cchBuffer;
|
||||
if (cchBuffer > 0) {
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, m_info.lBufOffset, SEEK_SET);
|
||||
}
|
||||
|
||||
// Was the previous seek (if required) successful?
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
result = MMIOERR_CANNOTSEEK;
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
} else {
|
||||
MxLong bytes_written = _hwrite((HFILE)m_info.hmmio, m_info.pchBuffer, cchBuffer);
|
||||
|
||||
if (bytes_written != -1 && bytes_written == cchBuffer) {
|
||||
m_info.lDiskOffset += bytes_written;
|
||||
m_info.pchNext = m_info.pchBuffer;
|
||||
m_info.dwFlags &= ~MMIO_DIRTY;
|
||||
} else {
|
||||
result = MMIOERR_CANNOTWRITE;
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = MMIOERR_CANNOTWRITE;
|
||||
}
|
||||
} else {
|
||||
result = MMIOERR_UNBUFFERED;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100ccd00
|
||||
MxU16 MXIOINFO::Advance(MxU16 p_option)
|
||||
{
|
||||
MxU16 result = 0;
|
||||
MxULong rwmode = m_info.dwFlags & MMIO_RWMODE;
|
||||
|
||||
if (m_info.pchBuffer) {
|
||||
MxLong cch = m_info.cchBuffer;
|
||||
|
||||
// If we can and should write to the file,
|
||||
// if we are being asked to write to the file,
|
||||
// and if there is a buffer *to* write:
|
||||
if ((rwmode == MMIO_WRITE || rwmode == MMIO_READWRITE) &&
|
||||
(m_info.dwFlags & MMIO_DIRTY) &&
|
||||
((p_option & MMIO_WRITE) || (rwmode == MMIO_READWRITE)) &&
|
||||
cch > 0) {
|
||||
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, m_info.lBufOffset, SEEK_SET);
|
||||
}
|
||||
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
result = MMIOERR_CANNOTSEEK;
|
||||
} else {
|
||||
MxLong bytes_written = _hwrite((HFILE)m_info.hmmio, m_info.pchBuffer, cch);
|
||||
|
||||
if (bytes_written != -1 && bytes_written == cch) {
|
||||
m_info.lDiskOffset += bytes_written;
|
||||
m_info.pchNext = m_info.pchBuffer;
|
||||
m_info.pchEndRead = m_info.pchBuffer;
|
||||
m_info.dwFlags &= ~MMIO_DIRTY;
|
||||
} else {
|
||||
result = MMIOERR_CANNOTWRITE;
|
||||
}
|
||||
}
|
||||
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
|
||||
}
|
||||
|
||||
m_info.lBufOffset += cch;
|
||||
if ((!rwmode || rwmode == MMIO_READWRITE) && cch > 0) {
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, m_info.lBufOffset, SEEK_SET);
|
||||
}
|
||||
|
||||
// if previous seek failed
|
||||
if (m_info.lBufOffset != m_info.lDiskOffset) {
|
||||
result = MMIOERR_CANNOTSEEK;
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
} else {
|
||||
int bytes_read = _hread((HFILE)m_info.hmmio, m_info.pchBuffer, cch);
|
||||
|
||||
if (bytes_read == -1) {
|
||||
result = MMIOERR_CANNOTREAD;
|
||||
m_info.lDiskOffset = _llseek((HFILE)m_info.hmmio, 0, SEEK_CUR);
|
||||
} else {
|
||||
m_info.lDiskOffset += bytes_read;
|
||||
m_info.pchNext = m_info.pchBuffer;
|
||||
m_info.pchEndRead = m_info.pchBuffer + bytes_read;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = MMIOERR_UNBUFFERED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100cce60
|
||||
MxU16 MXIOINFO::Descend(LPMMCKINFO pmmcki, const MMCKINFO *pmmckiParent, UINT fuDescend)
|
||||
MxU16 MXIOINFO::Descend(MMCKINFO *p_chunkInfo, const MMCKINFO *p_parentInfo, MxU16 p_descend)
|
||||
{
|
||||
return 0;
|
||||
MxU16 result = 0;
|
||||
|
||||
if (!p_chunkInfo)
|
||||
return MMIOERR_BASE; // ?
|
||||
|
||||
if (!p_descend) {
|
||||
p_chunkInfo->dwFlags = 0;
|
||||
if (Read(p_chunkInfo, 8) != 8) {
|
||||
result = MMIOERR_CANNOTREAD;
|
||||
} else {
|
||||
if (m_info.pchBuffer) {
|
||||
p_chunkInfo->dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
|
||||
} else {
|
||||
p_chunkInfo->dwDataOffset = m_info.lDiskOffset;
|
||||
}
|
||||
|
||||
if (p_chunkInfo->ckid == FOURCC_RIFF || p_chunkInfo->ckid == FOURCC_LIST) {
|
||||
if (Read(&p_chunkInfo->fccType, 4) != 4) {
|
||||
result = MMIOERR_CANNOTREAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MxULong ofs = MAXLONG;
|
||||
|
||||
if (p_parentInfo)
|
||||
ofs = p_parentInfo->cksize + p_parentInfo->dwDataOffset;
|
||||
|
||||
BOOL running = TRUE;
|
||||
BOOL read_ok = FALSE;
|
||||
MMCKINFO tmp;
|
||||
tmp.dwFlags = 0;
|
||||
|
||||
// This loop is... something
|
||||
do {
|
||||
if (Read(&tmp, 8) != 8) {
|
||||
// If the first read fails, report read error. Else EOF.
|
||||
result = read_ok ? MMIOERR_CHUNKNOTFOUND : MMIOERR_CANNOTREAD;
|
||||
running = FALSE;
|
||||
} else {
|
||||
read_ok = TRUE;
|
||||
if (m_info.pchBuffer) {
|
||||
tmp.dwDataOffset = m_info.pchNext - m_info.pchBuffer + m_info.lBufOffset;
|
||||
} else {
|
||||
tmp.dwDataOffset = m_info.lDiskOffset;
|
||||
}
|
||||
|
||||
if (ofs < tmp.dwDataOffset) {
|
||||
result = MMIOERR_CHUNKNOTFOUND;
|
||||
running = FALSE;
|
||||
} else {
|
||||
if ((p_descend == MMIO_FINDLIST && tmp.ckid == FOURCC_LIST) ||
|
||||
(p_descend == MMIO_FINDRIFF && tmp.ckid == FOURCC_RIFF)) {
|
||||
if (Read(&tmp.fccType, 4) != 4) {
|
||||
result = MMIOERR_CANNOTREAD;
|
||||
} else {
|
||||
if (p_chunkInfo->fccType != tmp.fccType)
|
||||
continue;
|
||||
}
|
||||
running = FALSE;
|
||||
} else {
|
||||
if (p_chunkInfo->ckid != tmp.ckid) {
|
||||
if (Seek((tmp.cksize&1)+tmp.cksize, SEEK_CUR) != -1) {
|
||||
continue;
|
||||
} else {
|
||||
result = MMIOERR_CANNOTSEEK;
|
||||
}
|
||||
}
|
||||
running = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (running);
|
||||
|
||||
if (!result)
|
||||
memcpy(p_chunkInfo, &tmp, sizeof(MMCKINFO));
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -12,13 +12,17 @@ class MXIOINFO
|
||||
MXIOINFO();
|
||||
__declspec(dllexport) ~MXIOINFO();
|
||||
|
||||
MxU16 Open(const char *filename, DWORD fdwOpen);
|
||||
void Close(MxLong arg);
|
||||
LONG Seek(LONG lOffset, int iOrigin);
|
||||
MxULong Read(HPSTR pch, LONG cch);
|
||||
void SetBuffer(LPSTR pchBuffer, LONG cchBuffer, LONG unk);
|
||||
MxU16 Descend(LPMMCKINFO pmmcki, const MMCKINFO *pmmckiParent, UINT fuDescend);
|
||||
MxU16 Open(const char *, MxULong);
|
||||
MxU16 Close(MxLong);
|
||||
MxLong Read(void *, MxLong);
|
||||
MxLong Seek(MxLong, int);
|
||||
MxU16 SetBuffer(char *, MxLong, MxLong);
|
||||
MxU16 Flush(MxU16);
|
||||
MxU16 Advance(MxU16);
|
||||
MxU16 Descend(MMCKINFO *, const MMCKINFO *, MxU16);
|
||||
|
||||
// NOTE: In MXIOINFO, the `hmmio` member of MMIOINFO is used like
|
||||
// an HFILE (int) instead of an HMMIO (WORD).
|
||||
MMIOINFO m_info;
|
||||
};
|
||||
|
||||
|
||||
@ -1,15 +1,185 @@
|
||||
#include "legoomni.h"
|
||||
#include "mxautolocker.h"
|
||||
#include "mxcore.h"
|
||||
#include "mxnotificationmanager.h"
|
||||
#include "mxparam.h"
|
||||
#include "mxtypes.h"
|
||||
|
||||
// OFFSET: LEGO1 0x100ac450 STUB
|
||||
MxNotificationManager::~MxNotificationManager()
|
||||
#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)
|
||||
{
|
||||
// TODO
|
||||
m_target = p_target;
|
||||
m_param = p_param->Clone();
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100ac800 STUB
|
||||
MxLong MxNotificationManager::Tickle()
|
||||
// OFFSET: LEGO1 0x100ac240
|
||||
MxNotification::~MxNotification()
|
||||
{
|
||||
// TODO
|
||||
delete m_param;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
// 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
|
||||
void MxNotificationManager::FlushPending(MxCore *p_listener)
|
||||
{
|
||||
MxNotificationPtrList pending;
|
||||
MxNotification *notif;
|
||||
|
||||
{
|
||||
MxAutoLocker lock(&m_lock);
|
||||
|
||||
// Find all notifications from, and addressed to, p_listener.
|
||||
if (m_sendList != NULL) {
|
||||
MxNotificationPtrList::iterator it = m_sendList->begin();
|
||||
while (it != m_sendList->end()) {
|
||||
notif = *it;
|
||||
if ((notif->GetTarget()->GetId() == p_listener->GetId()) ||
|
||||
(notif->GetParam()->GetSender()) && (notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) {
|
||||
m_sendList->erase(it++);
|
||||
pending.push_back(notif);
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MxNotificationPtrList::iterator it = m_queue->begin();
|
||||
while (it != m_queue->end()) {
|
||||
notif = *it;
|
||||
if ((notif->GetTarget()->GetId() == p_listener->GetId()) ||
|
||||
(notif->GetParam()->GetSender()) && (notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) {
|
||||
m_queue->erase(it++);
|
||||
pending.push_back(notif);
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deliver those notifications.
|
||||
while (pending.size() != 0) {
|
||||
notif = pending.front();
|
||||
pending.pop_front();
|
||||
notif->GetTarget()->Notify(*notif->GetParam());
|
||||
delete notif;
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100ac6c0
|
||||
MxResult MxNotificationManager::Send(MxCore *p_listener, MxParam *p_param)
|
||||
{
|
||||
MxAutoLocker lock(&m_lock);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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<MxU32>
|
||||
{};
|
||||
|
||||
class MxNotificationPtrList : public List<MxNotification *>
|
||||
{};
|
||||
|
||||
// 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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
11
LEGO1/mxparam.cpp
Normal file
11
LEGO1/mxparam.cpp
Normal file
@ -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);
|
||||
}
|
||||
33
LEGO1/mxparam.h
Normal file
33
LEGO1/mxparam.h
Normal file
@ -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
|
||||
@ -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
|
||||
#endif // MXTHREAD_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();
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -23,9 +23,9 @@ 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_displaySurface = NULL;
|
||||
this->m_unk5c = 0;
|
||||
this->m_videoParam.SetPalette(NULL);
|
||||
this->m_unk60 = FALSE;
|
||||
@ -45,10 +45,10 @@ MxLong MxVideoManager::RealizePalette(MxPalette *p_palette)
|
||||
|
||||
this->m_criticalSection.Enter();
|
||||
|
||||
if (p_palette && this->m_videoParam.GetPalette())
|
||||
{
|
||||
if (p_palette && this->m_videoParam.GetPalette()) {
|
||||
p_palette->GetEntries(paletteEntries);
|
||||
// TODO
|
||||
this->m_videoParam.GetPalette()->SetEntries(paletteEntries);
|
||||
this->m_displaySurface->SetPalette(this->m_videoParam.GetPalette());
|
||||
}
|
||||
|
||||
this->m_criticalSection.Leave();
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define MXVIDEOMANAGER_H
|
||||
|
||||
#include "mxunknown100dc6b0.h"
|
||||
#include "mxdisplaysurface.h"
|
||||
#include "mxvideoparam.h"
|
||||
|
||||
// VTABLE 0x100dc810
|
||||
@ -21,12 +22,12 @@ 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;
|
||||
MxDisplaySurface *m_displaySurface;
|
||||
int m_unk5c;
|
||||
MxBool m_unk60;
|
||||
};
|
||||
|
||||
@ -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 = '<OFFSET>'
|
||||
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 = '<OFFSET%d>' % 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)
|
||||
|
||||
@ -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');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user