l/glrage: add mingw fixes; build

This commit is contained in:
rr- 2021-11-14 23:42:18 +01:00
parent 7a2adfd4b9
commit 146e32ee94
No known key found for this signature in database
GPG key ID: CC65E6FD28CAE42A
63 changed files with 14347 additions and 6831 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "lib/glm"]
path = lib/glm
url = https://github.com/g-truc/glm

View file

@ -4,6 +4,7 @@
Initial build:
- Pull Git submodules (`git submodule init` and `git submodule update`)
- Compile the project (described in the next section)
- Copy `build/Tomb1Main.dll` and the `cfg` directory to your TombATI directory

View file

@ -5,6 +5,7 @@ RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y \
gcc-mingw-w64-i686 \
g++-mingw-w64-i686 \
make \
git \
python3-pip \

View file

@ -10,6 +10,9 @@ exe_wrapper = 'wine'
ld = '/usr/bin/i686-w64-mingw32-ld'
cmake = '/usr/bin/cmake'
[properties]
skip_sanity_check = true
[host_machine]
system = 'windows'
cpu_family = 'x86'

485
lib/ati3dcif/ATI3DCIF.h Normal file
View file

@ -0,0 +1,485 @@
#pragma once
#include <stdint.h>
#pragma pack(push, 8)
typedef unsigned int C3D_BOOL;
typedef int C3D_INT32;
typedef unsigned int C3D_UINT32;
typedef unsigned short C3D_UINT16;
typedef unsigned char C3D_UINT8;
typedef float C3D_FLOAT32;
typedef unsigned int* C3D_PBOOL;
typedef int* C3D_PINT32;
typedef unsigned int* C3D_PUINT32;
typedef unsigned short* C3D_PUINT16;
typedef unsigned char* C3D_PUINT8;
typedef float* C3D_PFLOAT32;
typedef void* C3D_PVOID;
#define C3D_FORCE_SIZE 0x7FFFFFFF
typedef enum
{
C3D_EC_OK = 0,
C3D_EC_GENFAIL = 1,
C3D_EC_MEMALLOCFAIL = 2,
C3D_EC_BADPARAM = 3,
C3D_EC_UNUSED0 = 4,
C3D_EC_BADSTATE = 5,
C3D_EC_NOTIMPYET = 6,
C3D_EC_UNUSED1 = 7,
C3D_EC_CHIPCAPABILITY = 8,
C3D_EC_NUM = 9,
C3D_EC_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EC,
*C3D_PEC;
typedef struct
{
C3D_INT32 top;
C3D_INT32 left;
C3D_INT32 bottom;
C3D_INT32 right;
} C3D_RECT, *C3D_PRECT;
typedef union
{
struct
{
unsigned r : 8;
unsigned g : 8;
unsigned b : 8;
unsigned a : 8;
};
C3D_UINT32 u32All;
} C3D_COLOR, *C3D_PCOLOR;
#define C3D_LOAD_PALETTE_ENTRY 0x40
#define C3D_NO_LOAD_PALETTE_ENTRY 0x00
typedef union
{
struct
{
unsigned r : 8;
unsigned g : 8;
unsigned b : 8;
unsigned flags : 8;
};
C3D_UINT32 u32All;
} C3D_PALETTENTRY, *C3D_PPALETTENTRY;
typedef struct
{
C3D_UINT16 ul;
C3D_UINT16 ur;
C3D_UINT16 ll;
C3D_UINT16 lr;
} C3D_CODEBOOKENTRY, *C3D_PCODEBOOKENTRY;
#define C3D_CAPS1_BASE 0x00000000
#define C3D_CAPS1_FOG 0x00000001
#define C3D_CAPS1_POINT 0x00000002
#define C3D_CAPS1_RECT 0x00000004
#define C3D_CAPS1_Z_BUFFER 0x00000008
#define C3D_CAPS1_CI4_TMAP 0x00000010
#define C3D_CAPS1_CI8_TMAP 0x00000020
#define C3D_CAPS1_LOAD_OBJECT 0x00000040
#define C3D_CAPS1_DITHER_EN 0x00000080
#define C3D_CAPS1_ENH_PERSP 0x00000100
#define C3D_CAPS1_SCISSOR 0x00000200
#define C3D_CAPS1_PROFILE_IF 0x01000000
#define C3D_CAPS2_TEXTURE_COMPOSITE 0x00000001
#define C3D_CAPS2_TEXTURE_CLAMP 0x00000002
#define C3D_CAPS2_DESTINATION_ALPHA_BLEND 0x00000004
#define C3D_CAPS2_TEXTURE_TILING 0x00000008
typedef struct
{
uint32_t u32Size;
uint32_t u32FrameBuffBase;
uint32_t u32OffScreenHeap;
uint32_t u32OffScreenSize;
uint32_t u32TotalRAM;
uint32_t u32ASICID;
uint32_t u32ASICRevision;
uint32_t u32CIFCaps1;
uint32_t u32CIFCaps2;
uint32_t u32CIFCaps3;
uint32_t u32CIFCaps4;
uint32_t u32CIFCaps5;
} C3D_3DCIFINFO, *PC3D_3DCIFINFO;
typedef enum
{
C3D_EV_VTCF = 3,
C3D_EV_TLVERTEX = 4,
C3D_EV_NUM = 5,
C3D_EV_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EVERTEX,
*C3D_PEVERTEX;
typedef struct
{
C3D_FLOAT32 x, y, z;
C3D_FLOAT32 s, t, w;
C3D_FLOAT32 r, g, b, a;
} C3D_VTCF, *C3D_PVTCF;
typedef struct
{
union
{
C3D_FLOAT32 sx;
C3D_FLOAT32 x;
};
union
{
C3D_FLOAT32 sy;
C3D_FLOAT32 y;
};
union
{
C3D_FLOAT32 sz;
C3D_FLOAT32 z;
};
union
{
C3D_FLOAT32 rhw;
C3D_FLOAT32 w;
};
union
{
C3D_UINT32 color;
struct
{
C3D_UINT8 b;
C3D_UINT8 g;
C3D_UINT8 r;
C3D_UINT8 a;
};
};
union
{
C3D_UINT32 specular;
struct
{
C3D_UINT8 spec_b;
C3D_UINT8 spec_g;
C3D_UINT8 spec_r;
C3D_UINT8 spec_a;
};
};
union
{
C3D_FLOAT32 tu;
C3D_FLOAT32 s;
};
union
{
C3D_FLOAT32 tv;
C3D_FLOAT32 t;
};
struct
{
C3D_FLOAT32 rhw;
C3D_FLOAT32 tu;
C3D_FLOAT32 tv;
} composite;
} C3D_TLVERTEX;
typedef void* C3D_VSTRIP;
typedef void** C3D_VLIST;
typedef void** C3D_PVARRAY;
typedef enum
{
C3D_EPRIM_LINE = 0,
C3D_EPRIM_TRI = 1,
C3D_EPRIM_QUAD = 2,
C3D_EPRIM_RECT = 3,
C3D_EPRIM_POINT = 4,
C3D_EPRIM_NUM = 5,
C3D_EPRIM_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EPRIM,
*C3D_PEPRIM;
typedef enum
{
C3D_ESH_NONE = 0,
C3D_ESH_SOLID = 1,
C3D_ESH_FLAT = 2,
C3D_ESH_SMOOTH = 3,
C3D_ESH_NUM = 4,
C3D_ESH_FORCE_U32 = C3D_FORCE_SIZE
} C3D_ESHADE,
*C3D_PESHADE;
typedef enum
{
C3D_EASRC_ZERO = 0,
C3D_EASRC_ONE = 1,
C3D_EASRC_DSTCLR = 2,
C3D_EASRC_INVDSTCLR = 3,
C3D_EASRC_SRCALPHA = 4,
C3D_EASRC_INVSRCALPHA = 5,
C3D_EASRC_DSTALPHA = 6,
C3D_EASRC_INVDSTALPHA = 7,
C3D_EASRC_NUM = 8,
C3D_EASRC_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EASRC,
*C3D_PEASRC;
typedef enum
{
C3D_EADST_ZERO = 0,
C3D_EADST_ONE = 1,
C3D_EADST_SRCCLR = 2,
C3D_EADST_INVSRCCLR = 3,
C3D_EADST_SRCALPHA = 4,
C3D_EADST_INVSRCALPHA = 5,
C3D_EADST_DSTALPHA = 6,
C3D_EADST_INVDSTALPHA = 7,
C3D_EADST_NUM = 8,
C3D_EADST_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EADST,
*C3D_PEADST;
typedef enum
{
C3D_EASEL_ZERO = 0,
C3D_EASEL_ONE = 1,
C3D_EASEL_SRCALPHA = 4,
C3D_EASEL_INVSRCALPHA = 5,
C3D_EASEL_DSTALPHA = 6,
C3D_EASEL_INVDSTALPHA = 7,
C3D_EASEL_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EASEL,
*C3D_PEASEL;
typedef enum
{
C3D_EACMP_NEVER = 0,
C3D_EACMP_LESS = 1,
C3D_EACMP_LEQUAL = 2,
C3D_EACMP_EQUAL = 3,
C3D_EACMP_GEQUAL = 4,
C3D_EACMP_GREATER = 5,
C3D_EACMP_NOTEQUAL = 6,
C3D_EACMP_ALWAYS = 7,
C3D_EACMP_MAX = 8,
C3D_EACMP_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EACMP,
*C3D_PEACMP;
typedef enum
{
C3D_ETEXTILE_DEFAULT = 0,
C3D_ETEXTILE_OFF = 1,
C3D_ETEXTILE_ON = 2,
C3D_ETEXTILE_MAX = 3,
C3D_ETEXTILE_FORCE_U32 = C3D_FORCE_SIZE
} C3D_ETEXTILE,
*C3D_PETEXTILE;
typedef void* C3D_HTX;
typedef C3D_HTX* C3D_PHTX;
typedef void* C3D_HTXPAL;
typedef C3D_HTXPAL* C3D_PHTXPAL;
typedef enum
{
C3D_ECI_TMAP_TRUE_COLOR = 0,
C3D_ECI_TMAP_4BIT_HI = 1,
C3D_ECI_TMAP_4BIT_LOW = 2,
C3D_ECI_TMAP_8BIT = 3,
C3D_ECI_TMAP_VQ = 4,
C3D_ECI_TMAP_NUM = 5,
C3D_ECI_TMAP_FORCE_U32 = C3D_FORCE_SIZE
} C3D_ECI_TMAP_TYPE;
typedef enum
{
C3D_ETL_NONE = 0,
C3D_ETL_MODULATE = 1,
C3D_ETL_ALPHA_DECAL = 2,
C3D_ETL_NUM = 3,
C3D_ETL_FORCE_U32 = C3D_FORCE_SIZE
} C3D_ETLIGHT,
*C3D_PETLIGHT;
typedef enum
{
C3D_ETPC_NONE = 0,
C3D_ETPC_ONE = 1,
C3D_ETPC_TWO = 2,
C3D_ETPC_THREE = 3,
C3D_ETPC_FOUR = 4,
C3D_ETPC_FIVE = 5,
C3D_ETPC_SIX = 6,
C3D_ETPC_SEVEN = 7,
C3D_ETPC_EIGHT = 8,
C3D_ETPC_NINE = 9,
C3D_ETPC_NUM = 10,
C3D_ETPC_FORCE_U32 = C3D_FORCE_SIZE
} C3D_ETPERSPCOR,
*C3D_PETPERSPCOR;
typedef enum
{
C3D_ETFILT_MINPNT_MAGPNT = 0,
C3D_ETFILT_MINPNT_MAG2BY2 = 1,
C3D_ETFILT_MIN2BY2_MAG2BY2 = 2,
C3D_ETFILT_MIPLIN_MAGPNT = 3,
C3D_ETFILT_MIPLIN_MAG2BY2 = 4,
C3D_ETFILT_MIPTRI_MAG2BY2 = 5,
C3D_ETFILT_MIN2BY2_MAGPNT = 6,
C3D_ETFILT_NUM = 7,
C3D_ETFILT_FORCE_U32 = C3D_FORCE_SIZE
} C3D_ETEXFILTER,
*C3D_PETEXFILTER;
typedef enum
{
C3D_ETEXOP_NONE = 0,
C3D_ETEXOP_CHROMAKEY = 1,
C3D_ETEXOP_ALPHA = 2,
C3D_ETEXOP_ALPHA_MASK = 3,
C3D_ETEXOP_NUM = 4,
C3D_ETEXOP_FORCE_U32 = C3D_FORCE_SIZE
} C3D_ETEXOP,
*C3D_PETEXOP;
typedef enum
{
C3D_EPF_RGB1555 = 3,
C3D_EPF_RGB565 = 4,
C3D_EPF_RGB8888 = 6,
C3D_EPF_RGB332 = 7,
C3D_EPF_Y8 = 8,
C3D_EPF_YUV422 = 11,
C3D_EPF_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EPIXFMT,
*C3D_PEPIXFMT;
typedef enum
{
C3D_ETF_CI4 = 1,
C3D_ETF_CI8 = 2,
C3D_ETF_RGB1555 = 3,
C3D_ETF_RGB565 = 4,
C3D_ETF_RGB8888 = 6,
C3D_ETF_RGB332 = 7,
C3D_ETF_Y8 = 8,
C3D_ETF_YUV422 = 11,
C3D_ETF_RGB4444 = 15,
C3D_ETF_VQ = 20,
C3D_ETF_FORCE_U32 = C3D_FORCE_SIZE
} C3D_ETEXFMT,
*C3D_PETEXFMT;
#define cu32MAX_TMAP_LEV 11
typedef struct
{
C3D_UINT32 u32Size;
C3D_BOOL bMipMap;
C3D_PVOID apvLevels[cu32MAX_TMAP_LEV];
C3D_UINT32 u32MaxMapXSizeLg2;
C3D_UINT32 u32MaxMapYSizeLg2;
C3D_ETEXFMT eTexFormat;
C3D_COLOR clrTexChromaKey;
C3D_HTXPAL htxpalTexPalette;
C3D_BOOL bClampS;
C3D_BOOL bClampT;
C3D_BOOL bAlphaBlend;
// NOTE: this version of the structure mismatches the ATI technical
// reference manual, but is consistent with the assignments to u32Size
// member in TombATI.exe.
} C3D_TMAP, *C3D_PTMAP;
typedef enum
{
C3D_ETEXCOMPFCN_BLEND = 0,
C3D_ETEXCOMPFCN_MOD = 1,
C3D_ETEXCOMPFCN_ADD_SPEC = 2,
C3D_ETEXCOMPFCN_MAX = 3,
C3D_ETEXCOMPFCN_FORCE_U32 = C3D_FORCE_SIZE
} C3D_ETEXCOMPFCN,
*C3D_PETEXCOMPFCN;
typedef enum
{
C3D_EZMODE_OFF = 0,
C3D_EZMODE_TESTON = 1,
C3D_EZMODE_TESTON_WRITEZ = 2,
C3D_EZMODE_MAX = 3,
C3D_EZMODE_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EZMODE,
*C3D_PEZMODE;
typedef enum
{
C3D_EZCMP_NEVER = 0,
C3D_EZCMP_LESS = 1,
C3D_EZCMP_LEQUAL = 2,
C3D_EZCMP_EQUAL = 3,
C3D_EZCMP_GEQUAL = 4,
C3D_EZCMP_GREATER = 5,
C3D_EZCMP_NOTEQUAL = 6,
C3D_EZCMP_ALWAYS = 7,
C3D_EZCMP_MAX = 8,
C3D_EZCMP_FORCE_U32 = C3D_FORCE_SIZE
} C3D_EZCMP,
*C3D_PEZCMP;
typedef void* C3D_HRC;
typedef void* C3D_PRSDATA;
typedef enum
{
C3D_ERS_FG_CLR = 0,
C3D_ERS_VERTEX_TYPE = 1,
C3D_ERS_PRIM_TYPE = 2,
C3D_ERS_SOLID_CLR = 3,
C3D_ERS_SHADE_MODE = 4,
C3D_ERS_TMAP_EN = 5,
C3D_ERS_TMAP_SELECT = 6,
C3D_ERS_TMAP_LIGHT = 7,
C3D_ERS_TMAP_PERSP_COR = 8,
C3D_ERS_TMAP_FILTER = 9,
C3D_ERS_TMAP_TEXOP = 10,
C3D_ERS_ALPHA_SRC = 11,
C3D_ERS_ALPHA_DST = 12,
C3D_ERS_SURF_DRAW_PTR = 13,
C3D_ERS_SURF_DRAW_PITCH = 14,
C3D_ERS_SURF_DRAW_PF = 15,
C3D_ERS_SURF_VPORT = 16,
C3D_ERS_FOG_EN = 17,
C3D_ERS_DITHER_EN = 18,
C3D_ERS_Z_CMP_FNC = 19,
C3D_ERS_Z_MODE = 20,
C3D_ERS_SURF_Z_PTR = 21,
C3D_ERS_SURF_Z_PITCH = 22,
C3D_ERS_SURF_SCISSOR = 23,
C3D_ERS_COMPOSITE_EN = 24,
C3D_ERS_COMPOSITE_SELECT = 25,
C3D_ERS_COMPOSITE_FNC = 26,
C3D_ERS_COMPOSITE_FACTOR = 27,
C3D_ERS_COMPOSITE_FILTER = 28,
C3D_ERS_COMPOSITE_FACTOR_ALPHA = 29,
C3D_ERS_LOD_BIAS_LEVEL = 30,
C3D_ERS_ALPHA_DST_TEST_ENABLE = 31,
C3D_ERS_ALPHA_DST_TEST_FNC = 32,
C3D_ERS_ALPHA_DST_WRITE_SELECT = 33,
C3D_ERS_ALPHA_DST_REFERENCE = 34,
C3D_ERS_SPECULAR_EN = 35,
C3D_ERS_ENHANCED_COLOR_RANGE_EN = 36,
C3D_ERS_NUM = 37,
C3D_ERS_FORCE_U32 = 0x7FFFFFFF,
} C3D_ERSID,
*C3D_PERSID;
#pragma pack(pop)

View file

@ -38,14 +38,29 @@ HandleException()
}
}
// export macro for CIF implementation
#define EXPORT(function_name, return_type, parameters) \
function_name##_t function_name##_lib = function_name; \
return_type WINAPI function_name parameters
extern "C" {
EXPORT(ATI3DCIF_Init, C3D_EC, (void))
C3D_EC WINAPI ATI3DCIF_Term(void)
{
LOG_TRACE("");
try {
if (renderer) {
renderer.release();
}
} catch (...) {
return HandleException();
}
// SDK PDF says "TRUE if successful, otherwise FALSE", but the
// function uses C3D_EC as return value.
// In other words: TRUE = C3D_EC_GENFAIL and FALSE = C3D_EC_OK? WTF...
// Anyway, most apps don't seem to care about the return value
// of this function, so stick with C3D_EC_OK for now.
return C3D_EC_OK;
}
C3D_EC WINAPI ATI3DCIF_Init(void)
{
LOG_TRACE("");
@ -69,27 +84,7 @@ EXPORT(ATI3DCIF_Init, C3D_EC, (void))
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_Term, C3D_EC, (void))
{
LOG_TRACE("");
try {
if (renderer) {
renderer.release();
}
} catch (...) {
return HandleException();
}
// SDK PDF says "TRUE if successful, otherwise FALSE", but the
// function uses C3D_EC as return value.
// In other words: TRUE = C3D_EC_GENFAIL and FALSE = C3D_EC_OK? WTF...
// Anyway, most apps don't seem to care about the return value
// of this function, so stick with C3D_EC_OK for now.
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_GetInfo, C3D_EC, (PC3D_3DCIFINFO p3DCIFInfo))
C3D_EC WINAPI ATI3DCIF_GetInfo(PC3D_3DCIFINFO p3DCIFInfo)
{
LOG_TRACE("");
@ -103,7 +98,7 @@ EXPORT(ATI3DCIF_GetInfo, C3D_EC, (PC3D_3DCIFINFO p3DCIFInfo))
// Host pointer to frame buffer base (TODO: allocate memory?)
p3DCIFInfo->u32FrameBuffBase = 0;
// Host pointer to offscreen heap (TODO: allocate memory?)
p3DCIFInfo->u32OffScreenHeap = 0;
p3DCIFInfo->u32OffScreenHeap = 0;
p3DCIFInfo->u32OffScreenSize = 0x4fe800; // Size of offscreen heap
p3DCIFInfo->u32TotalRAM = 8 << 20; // Total amount of RAM on the card
p3DCIFInfo->u32ASICID = 0x409; // ASIC Id. code
@ -131,7 +126,7 @@ EXPORT(ATI3DCIF_GetInfo, C3D_EC, (PC3D_3DCIFINFO p3DCIFInfo))
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_TextureReg, C3D_EC, (C3D_PTMAP ptmapToReg, C3D_PHTX phtmap))
C3D_EC WINAPI ATI3DCIF_TextureReg(C3D_PTMAP ptmapToReg, C3D_PHTX phtmap)
{
LOG_TRACE("0x%p, 0x%p", *ptmapToReg, *phtmap);
@ -144,7 +139,7 @@ EXPORT(ATI3DCIF_TextureReg, C3D_EC, (C3D_PTMAP ptmapToReg, C3D_PHTX phtmap))
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_TextureUnreg, C3D_EC, (C3D_HTX htxToUnreg))
C3D_EC WINAPI ATI3DCIF_TextureUnreg(C3D_HTX htxToUnreg)
{
LOG_TRACE("0x%p", htxToUnreg);
@ -157,8 +152,7 @@ EXPORT(ATI3DCIF_TextureUnreg, C3D_EC, (C3D_HTX htxToUnreg))
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_TexturePaletteCreate, C3D_EC,
(C3D_ECI_TMAP_TYPE epalette, void* pPalette, C3D_PHTXPAL phtpalCreated))
C3D_EC WINAPI ATI3DCIF_TexturePaletteCreate(C3D_ECI_TMAP_TYPE epalette, void* pPalette, C3D_PHTXPAL phtpalCreated)
{
LOG_TRACE("%s, 0x%p, 0x%p", cif::C3D_ECI_TMAP_TYPE_NAMES[epalette],
pPalette, phtpalCreated);
@ -172,7 +166,7 @@ EXPORT(ATI3DCIF_TexturePaletteCreate, C3D_EC,
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_TexturePaletteDestroy, C3D_EC, (C3D_HTXPAL htxpalToDestroy))
C3D_EC WINAPI ATI3DCIF_TexturePaletteDestroy(C3D_HTXPAL htxpalToDestroy)
{
LOG_TRACE("0x%p", htxpalToDestroy);
@ -185,9 +179,7 @@ EXPORT(ATI3DCIF_TexturePaletteDestroy, C3D_EC, (C3D_HTXPAL htxpalToDestroy))
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_TexturePaletteAnimate, C3D_EC,
(C3D_HTXPAL htxpalToAnimate, C3D_UINT32 u32StartIndex,
C3D_UINT32 u32NumEntries, C3D_PPALETTENTRY pclrPalette))
C3D_EC WINAPI ATI3DCIF_TexturePaletteAnimate(C3D_HTXPAL htxpalToAnimate, C3D_UINT32 u32StartIndex, C3D_UINT32 u32NumEntries, C3D_PPALETTENTRY pclrPalette)
{
LOG_TRACE("0x%p, %d, %d, 0x%p", htxpalToAnimate, u32StartIndex,
u32NumEntries, *pclrPalette);
@ -202,7 +194,7 @@ EXPORT(ATI3DCIF_TexturePaletteAnimate, C3D_EC,
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_ContextCreate, C3D_HRC, (void))
C3D_HRC WINAPI ATI3DCIF_ContextCreate(void)
{
LOG_TRACE("");
@ -220,7 +212,7 @@ EXPORT(ATI3DCIF_ContextCreate, C3D_HRC, (void))
return (C3D_HRC)1;
}
EXPORT(ATI3DCIF_ContextDestroy, C3D_EC, (C3D_HRC hRC))
C3D_EC WINAPI ATI3DCIF_ContextDestroy(C3D_HRC hRC)
{
LOG_TRACE("0x%p", hRC);
@ -234,8 +226,7 @@ EXPORT(ATI3DCIF_ContextDestroy, C3D_EC, (C3D_HRC hRC))
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_ContextSetState, C3D_EC,
(C3D_HRC hRC, C3D_ERSID eRStateID, C3D_PRSDATA pRStateData))
C3D_EC WINAPI ATI3DCIF_ContextSetState(C3D_HRC hRC, C3D_ERSID eRStateID, C3D_PRSDATA pRStateData)
{
#ifdef LOG_TRACE_ENABLED
std::string stateDataStr =
@ -253,7 +244,7 @@ EXPORT(ATI3DCIF_ContextSetState, C3D_EC,
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_RenderBegin, C3D_EC, (C3D_HRC hRC))
C3D_EC WINAPI ATI3DCIF_RenderBegin(C3D_HRC hRC)
{
LOG_TRACE("0x%p", hRC);
@ -266,7 +257,7 @@ EXPORT(ATI3DCIF_RenderBegin, C3D_EC, (C3D_HRC hRC))
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_RenderEnd, C3D_EC, (void))
C3D_EC WINAPI ATI3DCIF_RenderEnd(void)
{
LOG_TRACE("");
@ -279,15 +270,14 @@ EXPORT(ATI3DCIF_RenderEnd, C3D_EC, (void))
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_RenderSwitch, C3D_EC, (C3D_HRC hRC))
C3D_EC WINAPI ATI3DCIF_RenderSwitch(C3D_HRC hRC)
{
LOG_TRACE("0x%p", hRC);
// function has officially never been implemented
return C3D_EC_NOTIMPYET;
}
EXPORT(ATI3DCIF_RenderPrimStrip, C3D_EC,
(C3D_VSTRIP vStrip, C3D_UINT32 u32NumVert))
C3D_EC WINAPI ATI3DCIF_RenderPrimStrip(C3D_VSTRIP vStrip, C3D_UINT32 u32NumVert)
{
LOG_TRACE("0x%p, %d", vStrip, u32NumVert);
@ -300,8 +290,7 @@ EXPORT(ATI3DCIF_RenderPrimStrip, C3D_EC,
return C3D_EC_OK;
}
EXPORT(
ATI3DCIF_RenderPrimList, C3D_EC, (C3D_VLIST vList, C3D_UINT32 u32NumVert))
C3D_EC WINAPI ATI3DCIF_RenderPrimList(C3D_VLIST vList, C3D_UINT32 u32NumVert)
{
LOG_TRACE("0x%p, %d", vList, u32NumVert);
@ -314,8 +303,7 @@ EXPORT(
return C3D_EC_OK;
}
EXPORT(ATI3DCIF_RenderPrimMesh, C3D_EC,
(C3D_PVARRAY vMesh, C3D_PUINT32 pu32Indicies, C3D_UINT32 u32NumIndicies))
C3D_EC WINAPI ATI3DCIF_RenderPrimMesh(C3D_PVARRAY vMesh, C3D_PUINT32 pu32Indicies, C3D_UINT32 u32NumIndicies)
{
LOG_TRACE("0x%p, %d", vMesh, u32NumIndicies);
@ -323,7 +311,31 @@ EXPORT(ATI3DCIF_RenderPrimMesh, C3D_EC,
return C3D_EC_NOTIMPYET;
}
// export macro for CIF implementation
#define EXPORT(function_name, return_type, parameters) \
function_name##_t function_name##_lib = function_name; \
return_type WINAPI function_name parameters \
C3D_EC (*WINAPI ATI3DCIF_Term_lib)(void) = ATI3DCIF_Term;
C3D_EC (*WINAPI ATI3DCIF_Init_lib)(void) = ATI3DCIF_Init;
C3D_EC (*WINAPI ATI3DCIF_GetInfo_lib)(PC3D_3DCIFINFO p3DCIFInfo) = ATI3DCIF_GetInfo;
C3D_EC (*WINAPI ATI3DCIF_TextureReg_lib)(C3D_PTMAP ptmapToReg, C3D_PHTX phtmap) = ATI3DCIF_TextureReg;
C3D_EC (*WINAPI ATI3DCIF_TextureUnreg_lib)(C3D_HTX htxToUnreg) = ATI3DCIF_TextureUnreg;
C3D_EC (*WINAPI ATI3DCIF_TexturePaletteCreate_lib)(C3D_ECI_TMAP_TYPE epalette, void* pPalette, C3D_PHTXPAL phtpalCreated) = ATI3DCIF_TexturePaletteCreate;
C3D_EC (*WINAPI ATI3DCIF_TexturePaletteDestroy_lib)(C3D_HTXPAL htxpalToDestroy) = ATI3DCIF_TexturePaletteDestroy;
C3D_EC (*WINAPI ATI3DCIF_TexturePaletteAnimate_lib)(C3D_HTXPAL htxpalToAnimate, C3D_UINT32 u32StartIndex, C3D_UINT32 u32NumEntries, C3D_PPALETTENTRY pclrPalette) = ATI3DCIF_TexturePaletteAnimate;
C3D_HRC (*WINAPI ATI3DCIF_ContextCreate_lib)(void) = ATI3DCIF_ContextCreate;
C3D_EC (*WINAPI ATI3DCIF_ContextDestroy_lib)(C3D_HRC hRC) = ATI3DCIF_ContextDestroy;
C3D_EC (*WINAPI ATI3DCIF_ContextSetState_lib)(C3D_HRC hRC, C3D_ERSID eRStateID, C3D_PRSDATA pRStateData) = ATI3DCIF_ContextSetState;
C3D_EC (*WINAPI ATI3DCIF_RenderBegin_lib)(C3D_HRC hRC) = ATI3DCIF_RenderBegin;
C3D_EC (*WINAPI ATI3DCIF_RenderEnd_lib)(void) = ATI3DCIF_RenderEnd;
C3D_EC (*WINAPI ATI3DCIF_RenderSwitch_lib)(C3D_HRC hRC) = ATI3DCIF_RenderSwitch;
C3D_EC (*WINAPI ATI3DCIF_RenderPrimStrip_lib)(C3D_VSTRIP vStrip, C3D_UINT32 u32NumVert) = ATI3DCIF_RenderPrimStrip;
C3D_EC (*WINAPI ATI3DCIF_RenderPrimList_lib)(C3D_VLIST vList, C3D_UINT32 u32NumVert) = ATI3DCIF_RenderPrimList;
C3D_EC (*WINAPI ATI3DCIF_RenderPrimMesh_lib)(C3D_PVARRAY vMesh, C3D_PUINT32 pu32Indicies, C3D_UINT32 u32NumIndicies) = ATI3DCIF_RenderPrimMesh;
} // extern "C"
} // namespace cif
} // namespace glrage
} // namespace glrage

View file

@ -60,11 +60,11 @@ Renderer::Renderer()
}
// compile and link shaders and configure program
std::wstring basePath = m_context.getBasePath();
std::string basePath = m_context.getBasePath();
m_program.attach(gl::Shader(GL_VERTEX_SHADER)
.fromFile(basePath + L"\\shaders\\ati3dcif.vsh"));
.fromFile(basePath + "\\shaders\\ati3dcif.vsh"));
m_program.attach(gl::Shader(GL_FRAGMENT_SHADER)
.fromFile(basePath + L"\\shaders\\ati3dcif.fsh"));
.fromFile(basePath + "\\shaders\\ati3dcif.fsh"));
m_program.link();
m_program.fragmentData("fragColor");
m_program.bind();
@ -201,7 +201,7 @@ void Renderer::texturePaletteAnimate(C3D_HTXPAL htxpalToAnimate,
C3D_UINT32 u32StartIndex, C3D_UINT32 u32NumEntries,
C3D_PPALETTENTRY pclrPalette)
{
throw Error(__FUNCTION__ ": Not implemented", C3D_EC_NOTIMPYET);
throw Error(std::string(__FUNCTION__) + ": Not implemented", C3D_EC_NOTIMPYET);
}
void Renderer::renderPrimStrip(C3D_VSTRIP vStrip, C3D_UINT32 u32NumVert)
@ -356,4 +356,4 @@ void Renderer::zMode(StateVar::Value& value)
}
} // namespace cif
} // namespace glrage
} // namespace glrage

View file

@ -20,16 +20,16 @@ State::State()
{C3D_EASRC{C3D_EASRC_ONE}}, // C3D_ERS_ALPHA_SRC
{C3D_EADST{C3D_EADST_ZERO}}, // C3D_ERS_ALPHA_DST
{C3D_PVOID{NULL}}, // C3D_ERS_SURF_DRAW_PTR
{C3D_UINT32{NULL}}, // C3D_ERS_SURF_DRAW_PITCH
{C3D_UINT32{0}}, // C3D_ERS_SURF_DRAW_PITCH
{C3D_EPIXFMT{C3D_EPF_RGB8888}}, // C3D_ERS_SURF_DRAW_PF
{C3D_RECT{NULL}}, // C3D_ERS_SURF_VPORT
{C3D_RECT{0, 0, 0, 0}}, // C3D_ERS_SURF_VPORT
{C3D_BOOL{C3D_FALSE}}, // C3D_ERS_FOG_EN
{C3D_BOOL{C3D_TRUE}}, // C3D_ERS_DITHER_EN
{C3D_EZCMP{C3D_EZCMP_ALWAYS}}, // C3D_ERS_Z_CMP_FNC
{C3D_EZMODE{C3D_EZMODE_OFF}}, // C3D_ERS_Z_MODE
{C3D_PVOID{NULL}}, // C3D_ERS_SURF_Z_PTR
{C3D_UINT32{NULL}}, // C3D_ERS_SURF_Z_PITCH
{C3D_RECT{NULL}}, // C3D_ERS_SURF_SCISSOR
{C3D_UINT32{0}}, // C3D_ERS_SURF_Z_PITCH
{C3D_RECT{0, 0, 0, 0}}, // C3D_ERS_SURF_SCISSOR
{C3D_BOOL{C3D_FALSE}}, // C3D_ERS_COMPOSITE_EN
{C3D_HTX{NULL}}, // C3D_ERS_COMPOSITE_SELECT
{C3D_ETEXCOMPFCN{C3D_ETEXCOMPFCN_MAX}}, // C3D_ERS_COMPOSITE_FNC
@ -83,4 +83,4 @@ void State::registerObserver(const StateVar::Observer& observer, C3D_ERSID id)
}
} // namespace cif
} // namespace glrage
} // namespace glrage

View file

@ -1,5 +1,8 @@
#include "StateVar.hpp"
#include <cstring>
#include <stdexcept>
namespace glrage {
namespace cif {
@ -42,4 +45,4 @@ void StateVar::notify()
}
} // namespace cif
} // namespace glrage
} // namespace glrage

View file

@ -3,8 +3,10 @@
#include "ati3dcif.hpp"
#include <array>
#include <vector>
#include <cstring>
#include <functional>
#include <stdexcept>
#include <vector>
namespace glrage {
namespace cif {
@ -71,4 +73,4 @@ private:
};
} // namespace cif
} // namespace glrage
} // namespace glrage

View file

@ -1,5 +1,4 @@
#include <windows.h>
#include <atlimage.h>
#include "Texture.hpp"
#include "Error.hpp"
#include "Utils.hpp"
@ -13,7 +12,7 @@
#include <fstream>
#include <sstream>
#include "openssl/md5.h"
// #include "openssl/md5.h"
#include <glrage_util/StringUtils.hpp>
#undef max
@ -120,63 +119,63 @@ void Texture::load(C3D_PTMAP tmap, std::vector<C3D_PALETTENTRY>& palette)
case C3D_ETF_CI8: {
uint8_t* src = static_cast<uint8_t*>(tmap->apvLevels[level]);
unsigned char md5sum[16];
MD5(&src[0], size, md5sum);
std::string hex;
for (int i = 0; i < 16; i++)
hex += StringUtils::format("%02X", md5sum[i]);
// unsigned char md5sum[16];
// MD5(&src[0], size, md5sum);
// std::string hex;
// for (int i = 0; i < 16; i++)
// hex += StringUtils::format("%02X", md5sum[i]);
std::map<std::string, std::string>& keys = getTextureKeys();
// std::map<std::string, std::string>& keys = getTextureKeys();
std::vector<uint8_t> dst;
bool override = false;
CImage image;
if (level == 0 && keys.find(hex) != keys.end())
{
std::string fileName = m_config.getString("patch.texture_directory", "") + "\\" + keys[hex];
std::wstring wFileName(fileName.begin(), fileName.end());
if (SUCCEEDED(image.Load(wFileName.c_str())))
override = true;
else
LOG_INFO("Missing texture file: %s", fileName.c_str());
}
// bool override = false;
// CImage image;
// if (level == 0 && keys.find(hex) != keys.end())
// {
// std::string fileName = m_config.getString("patch.texture_directory", "") + "\\" + keys[hex];
// std::string wFileName(fileName.begin(), fileName.end());
// if (SUCCEEDED(image.Load(wFileName.c_str())))
// override = true;
// else
// LOG_INFO("Missing texture file: %s", fileName.c_str());
// }
if (override)
{
// This texture has a replacement image on disc.
// Use it for all levels, even if mimmaps are available
levels = 1;
m_keyOnAlpha = true;
width = image.GetWidth();
height = image.GetHeight();
bool use_map = (width == TRANS_TEX_DIM && height == TRANS_TEX_DIM);
if (use_map)
m_translucency_map.assign(TRANS_MAP_DIM * TRANS_MAP_DIM, 0);
int pitch = image.GetPitch();
uint8_t *bits = reinterpret_cast<uint8_t *>(image.GetBits());
dst.resize(abs(pitch) * height);
uint8_t *dstp = &dst[0];
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x++)
{
if (use_map && bits[4 * x + 3] != 255)
{
uint32_t map_x = x / TRANS_MAP_FACTOR;
uint32_t map_y = y / TRANS_MAP_FACTOR;
m_translucency_map[map_y * TRANS_MAP_DIM + map_x] = 1;
if (bits[4 * x + 3] != 0)
m_is_translucent = true;
}
dstp[4 * x + 0] = bits[4 * x + 2];
dstp[4 * x + 1] = bits[4 * x + 1];
dstp[4 * x + 2] = bits[4 * x + 0];
dstp[4 * x + 3] = bits[4 * x + 3];
}
bits += pitch;
dstp += abs(pitch);
}
}
else
// if (override)
// {
// // This texture has a replacement image on disc.
// // Use it for all levels, even if mimmaps are available
// levels = 1;
// m_keyOnAlpha = true;
// width = image.GetWidth();
// height = image.GetHeight();
// bool use_map = (width == TRANS_TEX_DIM && height == TRANS_TEX_DIM);
// if (use_map)
// m_translucency_map.assign(TRANS_MAP_DIM * TRANS_MAP_DIM, 0);
// int pitch = image.GetPitch();
// uint8_t *bits = reinterpret_cast<uint8_t *>(image.GetBits());
// dst.resize(abs(pitch) * height);
// uint8_t *dstp = &dst[0];
// for (size_t y = 0; y < height; y++)
// {
// for (size_t x = 0; x < width; x++)
// {
// if (use_map && bits[4 * x + 3] != 255)
// {
// uint32_t map_x = x / TRANS_MAP_FACTOR;
// uint32_t map_y = y / TRANS_MAP_FACTOR;
// m_translucency_map[map_y * TRANS_MAP_DIM + map_x] = 1;
// if (bits[4 * x + 3] != 0)
// m_is_translucent = true;
// }
// dstp[4 * x + 0] = bits[4 * x + 2];
// dstp[4 * x + 1] = bits[4 * x + 1];
// dstp[4 * x + 2] = bits[4 * x + 0];
// dstp[4 * x + 3] = bits[4 * x + 3];
// }
// bits += pitch;
// dstp += abs(pitch);
// }
// }
// else
{
// Resolve indices to RGBA, which requires less code and is
// faster than texture palettes in shaders.
@ -258,4 +257,4 @@ std::vector<uint8_t>& Texture::translucencyMap()
}
} // namespace cif
} // namespace glrage
} // namespace glrage

View file

@ -1,5 +1,9 @@
#include "TransDelay.hpp"
#include <cfloat>
#include <cmath>
#include <algorithm>
#include <glrage_util/Logger.hpp>
namespace glrage {
@ -38,10 +42,10 @@ bool TransDelay::delayTriangle(C3D_VTCF *verts)
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
}
int32_t ixmin = max(static_cast<int32_t>(floorf(xmin)), 0);
int32_t iymin = max(static_cast<int32_t>(floorf(ymin)), 0);
int32_t ixmax = min(static_cast<int32_t>(ceilf(xmax)), 32);
int32_t iymax = min(static_cast<int32_t>(ceilf(ymax)), 32);
int32_t ixmin = std::max(static_cast<int32_t>(floorf(xmin)), 0);
int32_t iymin = std::max(static_cast<int32_t>(floorf(ymin)), 0);
int32_t ixmax = std::min(static_cast<int32_t>(ceilf(xmax)), 32);
int32_t iymax = std::min(static_cast<int32_t>(ceilf(ymax)), 32);
auto map = group->texture->translucencyMap();
for (int32_t iy = iymin; iy < iymax; iy++)
{
@ -113,4 +117,4 @@ void TransDelay::render(const std::function<void(std::vector<C3D_VTCF>)>& render
}
} // namespace cif
} // namespace glrage
} // namespace glrage

View file

@ -7,26 +7,26 @@
namespace glrage {
namespace cif {
const char* C3D_EC_NAMES[];
const char* C3D_EVERTEX_NAMES[];
const char* C3D_EPRIM_NAMES[];
const char* C3D_ESHADE_NAMES[];
const char* C3D_EASRC_NAMES[];
const char* C3D_EADST_NAMES[];
const char* C3D_EACMP_NAMES[];
const char* C3D_ETEXTILE_NAMES[];
const char* C3D_ECI_TMAP_TYPE_NAMES[];
const char* C3D_ETLIGHT_NAMES[];
const char* C3D_ETPERSPCOR_NAMES[];
const char* C3D_ETEXFILTER_NAMES[];
const char* C3D_ETEXOP_NAMES[];
const char* C3D_ETEXCOMPFCN_NAMES[];
const char* C3D_EZMODE_NAMES[];
const char* C3D_EZCMP_NAMES[];
const char* C3D_ERSID_NAMES[];
const char* C3D_EASEL_NAMES[];
const char* C3D_EPIXFMT_NAMES[];
const char* C3D_ETEXFMT_NAMES[];
extern const char* C3D_EC_NAMES[];
extern const char* C3D_EVERTEX_NAMES[];
extern const char* C3D_EPRIM_NAMES[];
extern const char* C3D_ESHADE_NAMES[];
extern const char* C3D_EASRC_NAMES[];
extern const char* C3D_EADST_NAMES[];
extern const char* C3D_EACMP_NAMES[];
extern const char* C3D_ETEXTILE_NAMES[];
extern const char* C3D_ECI_TMAP_TYPE_NAMES[];
extern const char* C3D_ETLIGHT_NAMES[];
extern const char* C3D_ETPERSPCOR_NAMES[];
extern const char* C3D_ETEXFILTER_NAMES[];
extern const char* C3D_ETEXOP_NAMES[];
extern const char* C3D_ETEXCOMPFCN_NAMES[];
extern const char* C3D_EZMODE_NAMES[];
extern const char* C3D_EZCMP_NAMES[];
extern const char* C3D_ERSID_NAMES[];
extern const char* C3D_EASEL_NAMES[];
extern const char* C3D_EPIXFMT_NAMES[];
extern const char* C3D_ETEXFMT_NAMES[];
class Utils
{
@ -36,4 +36,4 @@ public:
};
} // namespace cif
} // namespace glrage
} // namespace glrage

View file

@ -18,4 +18,4 @@
#define C3D_FALSE 0
// include actual ATI3DCIF.H from 3D Rage SDK
#include <ragesdk/include/ATI3DCIF.H>
#include <ati3dcif/ATI3DCIF.h>

View file

@ -181,7 +181,7 @@ void DebugUtils::dumpInfo(DDSURFACEDESC& desc)
}
void DebugUtils::dumpBuffer(
DDSURFACEDESC& desc, void* buffer, const std::wstring& path)
DDSURFACEDESC& desc, void* buffer, const std::string& path)
{
uint32_t imageSize = desc.dwWidth * desc.dwHeight;
uint32_t dataSize = imageSize * 3;
@ -219,7 +219,7 @@ void DebugUtils::dumpBuffer(
std::ofstream file(path, std::ofstream::binary);
if (!file.good()) {
throw std::runtime_error("Can't open file '" +
StringUtils::wideToUtf8(path) + "': " +
path + "': " +
ErrorUtils::getSystemErrorString());
}
@ -241,4 +241,4 @@ std::string DebugUtils::getSurfaceName(DDSURFACEDESC& desc)
}
} // namespace ddraw
} // namespace glrage
} // namespace glrage

View file

@ -12,9 +12,9 @@ class DebugUtils
public:
static void dumpInfo(DDSURFACEDESC& desc);
static void dumpBuffer(
DDSURFACEDESC& desc, void* buffer, const std::wstring& path);
DDSURFACEDESC& desc, void* buffer, const std::string& path);
static std::string getSurfaceName(DDSURFACEDESC& desc);
};
} // namespace ddraw
} // namespace glrage
} // namespace glrage

View file

@ -9,7 +9,8 @@
namespace glrage {
namespace ddraw {
HRESULT WINAPI DirectDrawCreate(
extern "C" {
HRESULT __declspec(dllexport) WINAPI DirectDrawCreate(
GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnknown FAR* pUnkOuter)
{
LOG_TRACE("%p, %p, %p", lpGUID, lplpDD, pUnkOuter);
@ -29,6 +30,7 @@ HRESULT WINAPI DirectDrawCreate(
return DD_OK;
}
}
} // namespace ddraw
} // namespace glrage
} // namespace glrage

View file

@ -3,7 +3,7 @@
#include <glrage_gl/Shader.hpp>
#include <glrage_gl/Utils.hpp>
#include "openssl/md5.h"
// #include "openssl/md5.h"
#include <glrage_util/StringUtils.hpp>
namespace glrage {
@ -37,11 +37,11 @@ Renderer::Renderer()
m_sampler.parameteri(GL_TEXTURE_MIN_FILTER, filterMethodEnum);
// configure shaders
std::wstring basePath = m_context.getBasePath();
std::string basePath = m_context.getBasePath();
m_program.attach(gl::Shader(GL_VERTEX_SHADER)
.fromFile(basePath + L"\\shaders\\ddraw.vsh"));
.fromFile(basePath + "\\shaders\\ddraw.vsh"));
m_program.attach(gl::Shader(GL_FRAGMENT_SHADER)
.fromFile(basePath + L"\\shaders\\ddraw.fsh"));
.fromFile(basePath + "\\shaders\\ddraw.fsh"));
m_program.link();
m_program.fragmentData("fragColor");
@ -58,35 +58,35 @@ void Renderer::upload(DDSURFACEDESC& desc, std::vector<uint8_t>& data)
GLenum tex_type = TEX_TYPE;
m_surfaceTexture.bind();
if (texDir.length() > 0 && desc.dwWidth == TITLE_WIDTH && desc.dwHeight == TITLE_HEIGHT)
{
uint8_t md5sum[16];
MD5(&data[0], data.size(), md5sum);
uint8_t *key = reinterpret_cast<uint8_t *>("\x4D\xD5\x68\xAD\xD2\x7E\x5B\xC2\x07\xF0\xD3\xC4\xB8\xEC\xCE\x67");
if (memcmp(md5sum, key, 16) == 0)
{
if (m_overrideImage.IsNull())
{
std::string fileName = texDir + "\\TITLEH.PNG";
std::wstring wFileName(fileName.begin(), fileName.end());
CImage image;
if (SUCCEEDED(image.Load(wFileName.c_str())))
{
m_overrideImage.Create(image.GetWidth(), -image.GetHeight(), 24, 0);
image.BitBlt(m_overrideImage.GetDC(), 0, 0);
}
}
// if (texDir.length() > 0 && desc.dwWidth == TITLE_WIDTH && desc.dwHeight == TITLE_HEIGHT)
// {
// uint8_t md5sum[16];
// MD5(&data[0], data.size(), md5sum);
// uint8_t *key = reinterpret_cast<uint8_t *>("\x4D\xD5\x68\xAD\xD2\x7E\x5B\xC2\x07\xF0\xD3\xC4\xB8\xEC\xCE\x67");
// if (memcmp(md5sum, key, 16) == 0)
// {
// if (m_overrideImage.IsNull())
// {
// std::string fileName = texDir + "\\TITLEH.PNG";
// std::string wFileName(fileName.begin(), fileName.end());
// CImage image;
// if (SUCCEEDED(image.Load(wFileName.c_str())))
// {
// m_overrideImage.Create(image.GetWidth(), -image.GetHeight(), 24, 0);
// image.BitBlt(m_overrideImage.GetDC(), 0, 0);
// }
// }
if (!m_overrideImage.IsNull())
{
bits = reinterpret_cast<uint8_t *>(m_overrideImage.GetBits());
width = m_overrideImage.GetWidth();
height = m_overrideImage.GetHeight();
tex_format = GL_BGR;
tex_type = GL_UNSIGNED_BYTE;
}
}
}
// if (!m_overrideImage.IsNull())
// {
// bits = reinterpret_cast<uint8_t *>(m_overrideImage.GetBits());
// width = m_overrideImage.GetWidth();
// height = m_overrideImage.GetHeight();
// tex_format = GL_BGR;
// tex_type = GL_UNSIGNED_BYTE;
// }
// }
// }
// update buffer if the size is unchanged, otherwise create a new one
if (width != m_width || height != m_height) {
@ -141,4 +141,4 @@ void Renderer::render()
}
} // namespace ddraw
} // namespace glrage
} // namespace glrage

View file

@ -1,6 +1,6 @@
#pragma once
#include <atlimage.h>
// #include <atlimage.h>
#include "ddraw.hpp"
#include <glrage/GLRage.hpp>
@ -41,8 +41,8 @@ private:
gl::Texture m_surfaceTexture = GL_TEXTURE_2D;
gl::Sampler m_sampler;
gl::Program m_program;
CImage m_overrideImage;
// CImage m_overrideImage;
};
} // namespace ddraw
} // namespace glrage
} // namespace glrage

View file

@ -1,7 +1,7 @@
#pragma once
#include <Unknwnbase.h>
#include <Windows.h>
#include <unknwnbase.h>
#include <windows.h>
namespace glrage {
namespace ddraw {
@ -21,4 +21,4 @@ private:
};
} // namespace ddraw
} // namespace glrage
} // namespace glrage

1
lib/glm Submodule

@ -0,0 +1 @@
Subproject commit 8f39bb8730d45570384f3156eb0126b835024d69

View file

@ -2,7 +2,7 @@
#include "GameID.hpp"
#include <Windows.h>
#include <windows.h>
#include <cstdint>
#include <string>
@ -35,9 +35,11 @@ public:
virtual void setRendered() = 0;
virtual bool isRendered() = 0;
virtual HWND getHWnd() = 0;
virtual std::wstring getBasePath() = 0;
virtual std::string getBasePath() = 0;
virtual GameID getGameID() = 0;
virtual void setGameID(GameID gameID) = 0;
virtual ~Context() = default;
};
} // namespace glrage
} // namespace glrage

View file

@ -7,7 +7,7 @@
#include <glrage_gl/gl_core_3_3.h>
#include <glrage_gl/wgl_ext.h>
#include <Shlwapi.h>
#include <shlwapi.h>
#include <stdexcept>
@ -33,7 +33,7 @@ BOOL CALLBACK ContextImpl::callbackEnumWindowsProc(HWND hwnd, LPARAM _this)
ContextImpl::ContextImpl()
{
// load main config file
m_config.load(getBasePath() + L"\\glrage.ini");
m_config.load(getBasePath() + "\\glrage.ini");
// init rect
SetRectEmpty(&m_tmprect);
@ -65,7 +65,7 @@ void ContextImpl::init()
// The exact point where the application will create its window is unknown,
// but a valid OpenGL context is required at this point, so just create a
// dummy window for now and transfer the context later.
auto m_hwndTmp = CreateWindow(L"STATIC", L"", WS_POPUP | WS_DISABLED, 0, 0,
auto m_hwndTmp = CreateWindow("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0,
1, 1, NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(m_hwndTmp, SW_HIDE);
@ -157,7 +157,7 @@ void ContextImpl::attach()
}
m_pid = GetCurrentProcessId();
EnumWindows(&callbackEnumWindowsProc, NULL);
EnumWindows(&callbackEnumWindowsProc, (LPARAM)NULL);
}
void ContextImpl::detach()
@ -442,13 +442,13 @@ HWND ContextImpl::getHWnd()
return m_hwnd;
}
std::wstring ContextImpl::getBasePath()
std::string ContextImpl::getBasePath()
{
HMODULE hModule = nullptr;
DWORD dwFlags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
auto windowProc = reinterpret_cast<LPCWSTR>(&callbackWindowProc);
auto windowProc = reinterpret_cast<LPCSTR>(&callbackWindowProc);
if (!GetModuleHandleEx(dwFlags, windowProc, &hModule)) {
throw std::runtime_error("Can't get module handle");
}
@ -470,4 +470,4 @@ void ContextImpl::setGameID(GameID gameID)
m_gameID = gameID;
}
} // namespace glrage
} // namespace glrage

View file

@ -37,7 +37,7 @@ public:
void setRendered();
bool isRendered();
HWND getHWnd();
std::wstring getBasePath();
std::string getBasePath();
GameID getGameID();
void setGameID(GameID gameID);
@ -87,7 +87,7 @@ private:
Screenshot m_screenshot;
// temporary rectangle
RECT m_tmprect{0};
RECT m_tmprect = {0, 0, 0, 0};
// DirectDraw display mode
int32_t m_width = 0;
@ -101,4 +101,4 @@ private:
GameID m_gameID = GameID::Unknown;
};
} // namespace glrage
} // namespace glrage

View file

@ -4,8 +4,6 @@
using namespace glrage;
extern "C" { int _afxForceUSRDLL; }
BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)
{
LOG_TRACE("%p,%d", hInst, dwReason);
@ -17,4 +15,4 @@ BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)
}
return TRUE;
}
}

View file

@ -17,4 +17,4 @@ GLRAPI Config& GLRage::getConfig()
return Config::instance();
}
} // namespace glrage
} // namespace glrage

View file

@ -1,6 +0,0 @@
#include "MoviePlayerImpl.hpp"
MoviePlayer *MoviePlayer::GetPlayer()
{
return new MoviePlayerImpl();
}

View file

@ -1,13 +0,0 @@
#pragma once
class MoviePlayer
{
public:
virtual HRESULT Create(HWND hwnd)=0;
virtual HRESULT Play(LPCSTR path)=0;
virtual HRESULT GetEvent(HANDLE *handle)=0;
virtual bool IsPlaying()=0;
virtual void WaitForPlayback() = 0;
static MoviePlayer *GetPlayer();
};

View file

@ -1,221 +0,0 @@
#include <afxwin.h>
#include "MoviePlayerImpl.hpp"
#include "Dshow.h"
#include "d3d9.h"
#include "vmr9.h"
#include "evr.h"
#include "uuids.h"
MoviePlayerImpl::MoviePlayerImpl(void)
{
}
MoviePlayerImpl::~MoviePlayerImpl(void)
{
m_cwnd.Detach();
}
HRESULT MoviePlayerImpl::Create(HWND hwnd)
{
HRESULT hr;
m_cwnd.Attach(hwnd);
hr = m_builder.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER);
if(FAILED(hr))
return hr;
{
CComPtr<IFilterGraph> graph;
hr = m_builder.QueryInterface(&graph);
if(FAILED(hr))
return hr;
hr = graph.QueryInterface(&m_control);
if(FAILED(hr))
return hr;
hr = graph.QueryInterface(&m_event);
if(FAILED(hr))
return hr;
}
/* Try using the EVR */
hr = CreateEVR(&m_cwnd);
/* Use VMR9 as fallback */
if(FAILED(hr))
hr = CreateVMR9(&m_cwnd);
return hr;
}
HRESULT MoviePlayerImpl::Play(LPCSTR path)
{
HRESULT hr;
CA2W wide_path(path);
m_is_complete = false;
hr = m_builder->RenderFile(wide_path, NULL);
if(FAILED(hr))
return hr;
return m_control->Run();
}
HRESULT MoviePlayerImpl::GetEvent(HANDLE *handle)
{
return m_event->GetEventHandle((OAEVENT *)handle);
}
bool MoviePlayerImpl::IsPlaying()
{
long lEventCode;
LONG_PTR lParam1;
LONG_PTR lParam2;
HRESULT hr;
hr = m_event->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
if(hr == S_OK && lEventCode == EC_COMPLETE)
m_is_complete = true;
return !m_is_complete;
}
void MoviePlayerImpl::WaitForPlayback()
{
HANDLE event;
MSG msg;
GetEvent(&event);
bool playing = true;
// Ignore any already pressed keys
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
while (playing)
{
MsgWaitForMultipleObjects(1, &event, false, INFINITE, QS_ALLINPUT);
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
if (msg.message == WM_KEYDOWN)
{
switch (msg.wParam)
{
case VK_ESCAPE:
case VK_RETURN:
case VK_SPACE:
playing = false;
}
}
}
}
if (!IsPlaying())
playing = false;
}
m_control->Stop();
}
HRESULT MoviePlayerImpl::CreateVMR9(CWnd * wnd)
{
CComPtr<IBaseFilter> vmr;
HRESULT hr;
hr = vmr.CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER);
if(FAILED(hr))
return hr;
{
CComPtr<IVMRFilterConfig9> config;
hr = vmr.QueryInterface(&config);
if(FAILED(hr))
return hr;
hr = config->SetRenderingMode(VMRMode_Windowless);
if(FAILED(hr))
return hr;
hr = config->SetNumberOfStreams(1);
if(FAILED(hr))
return hr;
}
{
CComPtr<IVMRWindowlessControl9> win;
RECT rect;
hr = vmr.QueryInterface(&win);
if(FAILED(hr))
return hr;
hr = win->SetVideoClippingWindow(wnd->m_hWnd);
if(FAILED(hr))
return hr;
hr = win->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);
if(FAILED(hr))
return hr;
wnd->GetClientRect(&rect);
hr = win->SetVideoPosition(NULL, &rect);
if(FAILED(hr))
return hr;
}
/* Add filter to the graph as the last step so that there
* is no clean up needed in the error case */
return m_builder->AddFilter(vmr, L"Video Mixing Renderer");
}
HRESULT MoviePlayerImpl::CreateEVR(CWnd * wnd)
{
CComPtr<IBaseFilter> evr;
HRESULT hr;
hr = evr.CoCreateInstance(CLSID_EnhancedVideoRenderer, NULL, CLSCTX_INPROC_SERVER);
if(FAILED(hr))
return hr;
{
CComPtr<IMFGetService> service;
CComPtr<IMFVideoDisplayControl> control;
RECT rect;
hr = evr.QueryInterface(&service);
if(FAILED(hr))
return hr;
hr = service->GetService(MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl, (LPVOID *)&control);
if(FAILED(hr))
return hr;
hr = control->SetVideoWindow(wnd->m_hWnd);
if(FAILED(hr))
return hr;
wnd->GetClientRect(&rect);
hr = control->SetVideoPosition(NULL, &rect);
if(FAILED(hr))
return hr;
}
/* Add filter to the graph as the last step so that there
* is no clean up needed in the error case */
return m_builder->AddFilter(evr, L"Enhanced Video Renderer");
}

View file

@ -1,27 +0,0 @@
#pragma once
#include <afxwin.h>
#include "Dshow.h"
#include "MoviePlayer.hpp"
class MoviePlayerImpl : public MoviePlayer
{
private:
CComPtr<IGraphBuilder> m_builder;
CComPtr<IMediaControl> m_control;
CComPtr<IMediaEvent> m_event;
bool m_is_complete;
CWnd m_cwnd;
public:
MoviePlayerImpl(void);
~MoviePlayerImpl(void);
HRESULT Create(HWND hwnd);
HRESULT Play(LPCSTR path);
HRESULT GetEvent(HANDLE *handle);
bool IsPlaying();
void WaitForPlayback();
private:
HRESULT CreateVMR9(CWnd * wnd);
HRESULT CreateEVR(CWnd * wnd);
};

View file

@ -29,13 +29,13 @@ void Screenshot::captureScheduled()
void Screenshot::capture()
{
// find unused screenshot file name
std::wstring basePath = ContextImpl::instance().getBasePath();
std::wstring path;
std::string basePath = ContextImpl::instance().getBasePath();
std::string path;
DWORD dwAttrib;
do {
std::string fileName =
StringUtils::format("screenshot%04d.tga", m_index++);
path = basePath + L"\\" + StringUtils::utf8ToWide(fileName);
path = basePath + "\\" + fileName;
dwAttrib = GetFileAttributes(path.c_str());
} while (dwAttrib != INVALID_FILE_ATTRIBUTES && m_index < 9999);
@ -48,4 +48,4 @@ void Screenshot::capture()
gl::Screenshot::capture(path);
}
} // namespace glrage
} // namespace glrage

View file

@ -1,5 +0,0 @@
@echo off
set version_file=gitversion.h
set version_var=GIT_VERSION
for /f "tokens=*" %%i in ('git describe --tags') do set version_str=%%i
echo #define %version_var% "%version_str%" > %version_file%

View file

@ -26,13 +26,13 @@ struct TGAHeader
uint8_t blank3;
};
void Screenshot::capture(const std::wstring& path)
void Screenshot::capture(const std::string& path)
{
// open screenshot file
std::ofstream file(path, std::ofstream::binary);
if (!file.good()) {
throw std::runtime_error("Can't open screenshot file '" +
StringUtils::wideToUtf8(path) + "': " +
path + "': " +
ErrorUtils::getSystemErrorString());
}
@ -45,7 +45,7 @@ void Screenshot::capture(const std::wstring& path)
capture(buffer, width, height, depth, GL_BGR, GL_UNSIGNED_BYTE, false);
// create Targa header
TGAHeader tgaHeader = {0};
TGAHeader tgaHeader = {{0, 0}, 0, {0,0,0,0,0,0,0,0,0}, 0, 0, 0, 0};
tgaHeader.format = 2;
tgaHeader.width = width;
tgaHeader.height = height;
@ -86,4 +86,4 @@ void Screenshot::capture(std::vector<uint8_t>& buffer, GLint& width,
}
} // namespace gl
} // namespace glrage
} // namespace glrage

View file

@ -12,11 +12,11 @@ namespace gl {
class Screenshot
{
public:
static void capture(const std::wstring& path);
static void capture(const std::string& path);
static void capture(std::vector<uint8_t>& buffer, GLint& width,
GLint& height, GLint depth, GLenum format, GLenum type,
bool vflip = false);
};
} // namespace gl
} // namespace glrage
} // namespace glrage

View file

@ -30,14 +30,14 @@ void Shader::bind()
{
}
Shader& Shader::fromFile(const std::wstring& path)
Shader& Shader::fromFile(const std::string& path)
{
// open and check shader file
std::ifstream file;
file.open(path.c_str());
if (!file.good()) {
throw std::runtime_error("Can't open shader file '" +
StringUtils::wideToUtf8(path) + "': " +
path + "': " +
ErrorUtils::getSystemErrorString());
}
@ -92,4 +92,4 @@ bool Shader::compiled()
}
} // namespace gl
} // namespace glrage
} // namespace glrage

View file

@ -14,11 +14,11 @@ public:
Shader(GLenum shaderType);
~Shader();
void bind();
Shader& fromFile(const std::wstring& path);
Shader& fromFile(const std::string& path);
Shader& fromString(const std::string& program);
std::string infoLog();
bool compiled();
};
} // namespace gl
} // namespace glrage
} // namespace glrage

View file

@ -31,7 +31,7 @@ const char* Utils::getErrorString(GLenum err)
}
}
void Utils::checkError(char* section)
void Utils::checkError(const char* section)
{
for (GLenum err; (err = glGetError()) != GL_NO_ERROR;) {
#ifdef _DEBUG
@ -42,4 +42,4 @@ void Utils::checkError(char* section)
}
} // namespace gl
} // namespace glrage
} // namespace glrage

View file

@ -9,8 +9,8 @@ class Utils
{
public:
static const char* getErrorString(GLenum);
static void checkError(char*);
static void checkError(const char*);
};
} // namespace gl
} // namespace glrage
} // namespace glrage

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,188 +1,194 @@
#include "wgl_ext.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include "wgl_ext.h"
#if defined(__APPLE__)
#include <dlfcn.h>
static void* AppleGLGetProcAddress (const char *name)
static void* AppleGLGetProcAddress(const char* name)
{
static void* image = NULL;
if (NULL == image)
image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
static void* image = NULL;
return (image ? dlsym(image, name) : NULL);
if (NULL == image)
image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/"
"Current/OpenGL",
RTLD_LAZY);
return (image ? dlsym(image, name) : NULL);
}
#endif /* __APPLE__ */
#if defined(__sgi) || defined (__sun)
#if defined(__sgi) || defined(__sun)
#include <dlfcn.h>
#include <stdio.h>
static void* SunGetProcAddress (const GLubyte* name)
static void* SunGetProcAddress(const GLubyte* name)
{
static void* h = NULL;
static void* gpa;
static void* h = NULL;
static void* gpa;
if (h == NULL)
{
if ((h = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL)) == NULL) return NULL;
gpa = dlsym(h, "glXGetProcAddress");
}
if (h == NULL) {
if ((h = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL)) == NULL)
return NULL;
gpa = dlsym(h, "glXGetProcAddress");
}
if (gpa != NULL)
return ((void*(*)(const GLubyte*))gpa)(name);
else
return dlsym(h, (const char*)name);
if (gpa != NULL)
return ((void* (*)(const GLubyte*))gpa)(name);
else
return dlsym(h, (const char*)name);
}
#endif /* __sgi || __sun */
#if defined(_WIN32)
#ifdef _MSC_VER
#pragma warning(disable: 4055)
#pragma warning(disable: 4054)
#pragma warning(disable: 4996)
#pragma warning(disable : 4055)
#pragma warning(disable : 4054)
#pragma warning(disable : 4996)
#endif
static int TestPointer(const PROC pTest)
{
ptrdiff_t iTest;
if(!pTest) return 0;
iTest = (ptrdiff_t)pTest;
if(iTest == 1 || iTest == 2 || iTest == 3 || iTest == -1) return 0;
return 1;
ptrdiff_t iTest;
if (!pTest)
return 0;
iTest = (ptrdiff_t)pTest;
if (iTest == 1 || iTest == 2 || iTest == 3 || iTest == -1)
return 0;
return 1;
}
static PROC WinGetProcAddress(const char *name)
static PROC WinGetProcAddress(const char* name)
{
HMODULE glMod = NULL;
PROC pFunc = wglGetProcAddress((LPCSTR)name);
if(TestPointer(pFunc))
{
return pFunc;
}
glMod = GetModuleHandleA("OpenGL32.dll");
return (PROC)GetProcAddress(glMod, (LPCSTR)name);
HMODULE glMod = NULL;
PROC pFunc = wglGetProcAddress((LPCSTR)name);
if (TestPointer(pFunc)) {
return pFunc;
}
glMod = GetModuleHandleA("OpenGL32.dll");
return (PROC)GetProcAddress(glMod, (LPCSTR)name);
}
#define IntGetProcAddress(name) WinGetProcAddress(name)
#else
#if defined(__APPLE__)
#define IntGetProcAddress(name) AppleGLGetProcAddress(name)
#else
#if defined(__sgi) || defined(__sun)
#define IntGetProcAddress(name) SunGetProcAddress(name)
#else /* GLX */
#include <GL/glx.h>
#if defined(__APPLE__)
#define IntGetProcAddress(name) AppleGLGetProcAddress(name)
#else
#if defined(__sgi) || defined(__sun)
#define IntGetProcAddress(name) SunGetProcAddress(name)
#else /* GLX */
#include <GL/glx.h>
#define IntGetProcAddress(name) (*glXGetProcAddressARB)((const GLubyte*)name)
#endif
#endif
#define IntGetProcAddress(name) (*glXGetProcAddressARB)((const GLubyte*)name)
#endif
#endif
#endif
int wgl_ext_EXT_swap_control = 0;
/* Extension: EXT_swap_control*/
typedef int (CODEGEN_FUNCPTR *PFN_PTRC_WGLGETSWAPINTERVALEXTPROC)(void);
typedef int(CODEGEN_FUNCPTR* PFN_PTRC_WGLGETSWAPINTERVALEXTPROC)(void);
static int CODEGEN_FUNCPTR Switch_GetSwapIntervalEXT(void);
typedef BOOL (CODEGEN_FUNCPTR *PFN_PTRC_WGLSWAPINTERVALEXTPROC)(int);
typedef BOOL(CODEGEN_FUNCPTR* PFN_PTRC_WGLSWAPINTERVALEXTPROC)(int);
static BOOL CODEGEN_FUNCPTR Switch_SwapIntervalEXT(int interval);
/* Extension: EXT_swap_control*/
PFN_PTRC_WGLGETSWAPINTERVALEXTPROC _ptrc_wglGetSwapIntervalEXT = Switch_GetSwapIntervalEXT;
PFN_PTRC_WGLSWAPINTERVALEXTPROC _ptrc_wglSwapIntervalEXT = Switch_SwapIntervalEXT;
PFN_PTRC_WGLGETSWAPINTERVALEXTPROC _ptrc_wglGetSwapIntervalEXT =
Switch_GetSwapIntervalEXT;
PFN_PTRC_WGLSWAPINTERVALEXTPROC _ptrc_wglSwapIntervalEXT =
Switch_SwapIntervalEXT;
/* Extension: EXT_swap_control*/
static int CODEGEN_FUNCPTR Switch_GetSwapIntervalEXT(void)
{
_ptrc_wglGetSwapIntervalEXT = (PFN_PTRC_WGLGETSWAPINTERVALEXTPROC)IntGetProcAddress("wglGetSwapIntervalEXT");
return _ptrc_wglGetSwapIntervalEXT();
_ptrc_wglGetSwapIntervalEXT =
(PFN_PTRC_WGLGETSWAPINTERVALEXTPROC)IntGetProcAddress(
"wglGetSwapIntervalEXT");
return _ptrc_wglGetSwapIntervalEXT();
}
static BOOL CODEGEN_FUNCPTR Switch_SwapIntervalEXT(int interval)
{
_ptrc_wglSwapIntervalEXT = (PFN_PTRC_WGLSWAPINTERVALEXTPROC)IntGetProcAddress("wglSwapIntervalEXT");
return _ptrc_wglSwapIntervalEXT(interval);
_ptrc_wglSwapIntervalEXT =
(PFN_PTRC_WGLSWAPINTERVALEXTPROC)IntGetProcAddress(
"wglSwapIntervalEXT");
return _ptrc_wglSwapIntervalEXT(interval);
}
static void ClearExtensionVariables(void)
{
wgl_ext_EXT_swap_control = 0;
wgl_ext_EXT_swap_control = 0;
}
typedef struct wgl_MapTable_s
{
char *extName;
int *extVariable;
}wgl_MapTable;
char* extName;
int* extVariable;
} wgl_MapTable;
static wgl_MapTable g_mappingTable[1]; /*This is intensionally left uninitialized.*/
static wgl_MapTable
g_mappingTable[1]; /*This is intensionally left uninitialized.*/
static void LoadExtByName(const char *extensionName)
static void LoadExtByName(const char* extensionName)
{
wgl_MapTable *tableEnd = &g_mappingTable[1];
wgl_MapTable *entry = &g_mappingTable[0];
for(; entry != tableEnd; ++entry)
{
if(strcmp(entry->extName, extensionName) == 0)
break;
}
if(entry != tableEnd)
*(entry->extVariable) = 1;
wgl_MapTable* tableEnd = &g_mappingTable[1];
wgl_MapTable* entry = &g_mappingTable[0];
for (; entry != tableEnd; ++entry) {
if (strcmp(entry->extName, extensionName) == 0)
break;
}
if (entry != tableEnd)
*(entry->extVariable) = 1;
}
static void ProcExtsFromExtString(const char *strExtList)
static void ProcExtsFromExtString(const char* strExtList)
{
size_t iExtListLen = strlen(strExtList);
const char *strExtListEnd = strExtList + iExtListLen;
const char *strCurrPos = strExtList;
char strWorkBuff[256];
size_t iExtListLen = strlen(strExtList);
const char* strExtListEnd = strExtList + iExtListLen;
const char* strCurrPos = strExtList;
char strWorkBuff[256];
while(*strCurrPos)
{
/*Get the extension at our position.*/
int iStrLen = 0;
const char *strEndStr = strchr(strCurrPos, ' ');
int iStop = 0;
if(strEndStr == NULL)
{
strEndStr = strExtListEnd;
iStop = 1;
}
while (*strCurrPos) {
/*Get the extension at our position.*/
int iStrLen = 0;
const char* strEndStr = strchr(strCurrPos, ' ');
int iStop = 0;
if (strEndStr == NULL) {
strEndStr = strExtListEnd;
iStop = 1;
}
iStrLen = (int)((ptrdiff_t)strEndStr - (ptrdiff_t)strCurrPos);
iStrLen = (int)((ptrdiff_t)strEndStr - (ptrdiff_t)strCurrPos);
if(iStrLen > 255)
return;
if (iStrLen > 255)
return;
strncpy(strWorkBuff, strCurrPos, iStrLen);
strWorkBuff[iStrLen] = '\0';
strncpy(strWorkBuff, strCurrPos, iStrLen);
strWorkBuff[iStrLen] = '\0';
LoadExtByName(strWorkBuff);
LoadExtByName(strWorkBuff);
strCurrPos = strEndStr + 1;
if(iStop) break;
}
strCurrPos = strEndStr + 1;
if (iStop)
break;
}
}
void wgl_CheckExtensions(HDC hdc)
{
ClearExtensionVariables();
{
typedef const char * (CODEGEN_FUNCPTR *MYGETEXTSTRINGPROC)(HDC);
MYGETEXTSTRINGPROC InternalGetExtensionString = (MYGETEXTSTRINGPROC)IntGetProcAddress("wglGetExtensionsStringARB");
if(!InternalGetExtensionString) return;
ProcExtsFromExtString((const char *)InternalGetExtensionString(hdc));
}
ClearExtensionVariables();
{
typedef const char*(CODEGEN_FUNCPTR * MYGETEXTSTRINGPROC)(HDC);
MYGETEXTSTRINGPROC InternalGetExtensionString =
(MYGETEXTSTRINGPROC)IntGetProcAddress("wglGetExtensionsStringARB");
if (!InternalGetExtensionString)
return;
ProcExtsFromExtString((const char*)InternalGetExtensionString(hdc));
}
}

View file

@ -8,10 +8,10 @@
#define __wglext_h_
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#define WIN32_LEAN_AND_MEAN 1
#endif
#ifndef NOMINMAX
#define NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
@ -41,19 +41,18 @@ typedef double GLclampd;
#endif /*GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS*/
#ifndef GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS
#define GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS
#endif /*GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS*/
struct _GPU_DEVICE {
DWORD cb;
CHAR DeviceName[32];
CHAR DeviceString[128];
DWORD Flags;
RECT rcVirtualScreen;
struct _GPU_DEVICE
{
DWORD cb;
CHAR DeviceName[32];
CHAR DeviceString[128];
DWORD Flags;
RECT rcVirtualScreen;
};
DECLARE_HANDLE(HPBUFFERARB);
DECLARE_HANDLE(HPBUFFEREXT);
@ -61,25 +60,25 @@ DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);
DECLARE_HANDLE(HPVIDEODEV);
DECLARE_HANDLE(HGPUNV);
DECLARE_HANDLE(HVIDEOINPUTDEVICENV);
typedef struct _GPU_DEVICE *PGPU_DEVICE;
typedef struct _GPU_DEVICE* PGPU_DEVICE;
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif /*__cplusplus*/
/***********************/
/* Extension Variables*/
/***********************/
/* Extension Variables*/
extern int wgl_ext_EXT_swap_control;
extern int wgl_ext_EXT_swap_control;
/* Extension: EXT_swap_control*/
extern int (CODEGEN_FUNCPTR *_ptrc_wglGetSwapIntervalEXT)(void);
/* Extension: EXT_swap_control*/
extern int(CODEGEN_FUNCPTR* _ptrc_wglGetSwapIntervalEXT)(void);
#define wglGetSwapIntervalEXT _ptrc_wglGetSwapIntervalEXT
extern BOOL (CODEGEN_FUNCPTR *_ptrc_wglSwapIntervalEXT)(int interval);
extern BOOL(CODEGEN_FUNCPTR* _ptrc_wglSwapIntervalEXT)(int interval);
#define wglSwapIntervalEXT _ptrc_wglSwapIntervalEXT
void wgl_CheckExtensions(HDC hdc);
void wgl_CheckExtensions(HDC hdc);
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View file

@ -3,7 +3,7 @@
#include <glrage/ContextImpl.hpp>
#include <glrage_util/Config.hpp>
#include <Windows.h>
#include <windows.h>
namespace glrage {
@ -35,7 +35,10 @@ void AssaultRigsPatch::apply()
height = ctx.getScreenHeight();
}
patch(0x490234, "80 02 00 00 E0 01 00 00", Chunk() << width << height);
auto c = Chunk();
c = c << width;
c = c << height;
patch(0x490234, "80 02 00 00 E0 01 00 00", c);
// Replace "640 BY 480" in the options with "CUSTOM".
patch(0x486AC0, "36 34 30 20 42 59 20 34 38 30",
@ -47,4 +50,4 @@ void AssaultRigsPatch::apply()
patchNop(0x004342F8, "0F 86 59 F4 FF FF");
}
} // namespace glrage
} // namespace glrage

View file

@ -28,14 +28,19 @@ bool Patch::patch(
const size_t size = expectedData.size();
std::vector<uint8_t> actualData(size);
HANDLE proc = GetCurrentProcess();
LPVOID lpaddr = NULL;
DWORD numRead = 0;
DWORD numWritten = 0;
DWORD oldProtect = 0;
// vectors must match in size
if (size != replacementData.size()) {
goto end;
}
// apply read/write flags to the memory page
DWORD oldProtect = 0;
LPVOID lpaddr = reinterpret_cast<LPVOID>(addr);
lpaddr = reinterpret_cast<LPVOID>(addr);
if (!VirtualProtect(lpaddr, size, PAGE_EXECUTE_READWRITE, &oldProtect)) {
goto end;
}
@ -43,8 +48,6 @@ bool Patch::patch(
restoreProtect = true;
// read current memory to a temporary vector
HANDLE proc = GetCurrentProcess();
DWORD numRead = 0;
if (!ReadProcessMemory(proc, lpaddr, &actualData[0], size, &numRead) ||
numRead != size) {
goto end;
@ -56,7 +59,6 @@ bool Patch::patch(
}
// write patched data to memory
DWORD numWritten = 0;
if (!WriteProcessMemory(
proc, lpaddr, &replacementData[0], size, &numWritten) ||
numWritten != size) {
@ -92,18 +94,19 @@ bool Patch::patch(uint32_t addr, const Chunk& replacement)
const std::vector<uint8_t> replacementData = replacement.data();
const size_t size = replacementData.size();
// apply read/write flags to the memory page
HANDLE proc = GetCurrentProcess();
DWORD numWritten = 0;
DWORD oldProtect = 0;
// apply read/write flags to the memory page
LPVOID lpaddr = reinterpret_cast<LPVOID>(addr);
if (!VirtualProtect(lpaddr, size, PAGE_EXECUTE_READWRITE, &oldProtect)) {
goto end;
}
restoreProtect = true;
HANDLE proc = GetCurrentProcess();
// write patched data to memory
DWORD numWritten = 0;
if (!WriteProcessMemory(
proc, lpaddr, &replacementData[0], size, &numWritten) ||
numWritten != size) {
@ -135,7 +138,10 @@ void Patch::patchAddr(
int32_t addrFunc = reinterpret_cast<int32_t>(func);
int32_t addrCallNew = addrFunc - addr - 5;
patch(addr, expected, Chunk() << op << addrCallNew);
auto c = Chunk();
c = c << op;
c = c << addrCallNew;
patch(addr, expected, c);
}
bool Patch::patchNop(uint32_t addr, const Chunk& expected)
@ -145,4 +151,4 @@ bool Patch::patchNop(uint32_t addr, const Chunk& expected)
return patch(addr, expected, replacement);
}
} // namespace glrage
} // namespace glrage

View file

@ -5,7 +5,7 @@
#include <glrage/GameID.hpp>
#include <glrage_util/Config.hpp>
#include <Windows.h>
#include <windows.h>
#include <array>
#include <cstdint>
@ -16,9 +16,9 @@ namespace glrage {
struct ModuleContext
{
std::wstring path;
std::string path;
std::string fileName;
std::wstring fileNameW;
std::string fileNameW;
VS_FIXEDFILEINFO fileInfo;
};
@ -43,4 +43,4 @@ protected:
Config& m_config{Config::instance()};
};
} // namespace glrage
} // namespace glrage

View file

@ -7,8 +7,8 @@
#include <glrage_util/ErrorUtils.hpp>
#include <glrage_util/StringUtils.hpp>
#include <Shlwapi.h>
#include <Windows.h>
#include <shlwapi.h>
#include <windows.h>
#include <algorithm>
#include <cstdint>
@ -32,30 +32,15 @@ void RuntimePatcher::patch()
// run known patches
// clang-format off
std::map<std::string, std::shared_ptr<Patch>> patches = {
{"Tomb Raider", std::make_shared<TombRaiderPatch>(false)},
{"Tomb Raider Gold", std::make_shared<TombRaiderPatch>(true)},
{"Assault Rigs", std::make_shared<AssaultRigsPatch>()},
{"Wipeout", std::make_shared<WipeoutPatch>()}
};
// clang-format on
ContextImpl& ctx = ContextImpl::instance();
Config& config = Config::instance();
// load game patch config
config.load(ctx.getBasePath() + L"\\patches\\" + m_ctx.fileNameW + L".ini");
config.load(ctx.getBasePath() + "\\patches\\" + m_ctx.fileNameW + ".ini");
// apply patch module as defined in the config
std::string game = config.getString("patch.game", "");
auto patchResult = patches.find(game);
if (patchResult == patches.end()) {
ErrorUtils::error("Invalid patch module '" + game + "'");
}
auto patch = patchResult->second;
auto patch = std::make_shared<TombRaiderPatch>(false);
patch->setContext(m_ctx);
patch->apply();
// patch->apply();
ctx.setGameID(patch->gameID());
}
@ -71,14 +56,14 @@ void RuntimePatcher::getModulePath()
// remove extension
m_ctx.fileNameW =
m_ctx.fileNameW.substr(0, m_ctx.fileNameW.find_last_of(L"."));
m_ctx.fileNameW.substr(0, m_ctx.fileNameW.find_last_of("."));
// convert to lower case
transform(m_ctx.fileNameW.begin(), m_ctx.fileNameW.end(),
m_ctx.fileNameW.begin(), ::towlower);
// convert to UTF-8
m_ctx.fileName = StringUtils::wideToUtf8(m_ctx.fileNameW);
m_ctx.fileName = m_ctx.fileNameW;
}
void RuntimePatcher::getModuleVersion()
@ -95,10 +80,10 @@ void RuntimePatcher::getModuleVersion()
UINT fileInfoLen = 0;
VS_FIXEDFILEINFO* fileInfoBuf;
if (VerQueryValue(&versionInfo[0], L"\\",
if (VerQueryValue(&versionInfo[0], "\\",
reinterpret_cast<LPVOID*>(&fileInfoBuf), &fileInfoLen)) {
m_ctx.fileInfo = *fileInfoBuf;
}
}
} // namespace glrage
} // namespace glrage

View file

@ -1,13 +1,8 @@
#include <shlwapi.h>
#include "TombRaiderHooks.hpp"
#include <glrage_util/Logger.hpp>
#include <cmath>
//#include <vector>
#include <glrage/MoviePlayer.hpp>
#include <glrage/GLRage.hpp>
namespace glrage {
@ -22,7 +17,6 @@ typedef void* TombRaiderCreateOverlayText(
int16_t x, int16_t y, int16_t a3, const char* text);
typedef int16_t TombRaiderSetFOV(int16_t fov);
typedef BOOL TombRaiderSoundSetVolume(uint8_t volume);
typedef BOOL TombRaiderPlayRplFile(int32_t fmvIndex, int32_t unknown);
/** Tomb Raider structs **/
@ -67,9 +61,6 @@ static TombRaiderRenderCollectedItem* m_tombRenderCollectedItem = nullptr;
// changes the global sound effect volume
static TombRaiderSoundSetVolume* m_tombSoundSetVolume = nullptr;
// Call back into game exe to play standard FMV file
static TombRaiderPlayRplFile* m_tombPlayRplFile = nullptr;
/** Tomb Raider var pointers **/
// Pointer to the key state table. If an entry is 1, then the key is pressed.
@ -81,9 +72,6 @@ static int32_t* m_tombNumAudioSamples = nullptr;
// Audio sample pointer table.
static TombRaiderAudioSample*** m_tombSampleTable = nullptr;
// Table of in-game video file paths
static char **m_tombFMVPaths = nullptr;
// Sound init booleans. There are two for some reason and both are set to 1 at
// the same location.
static BOOL* m_tombSoundInit1 = nullptr;
@ -165,13 +153,11 @@ void TombRaiderHooks::init(bool ub)
m_tombSetFOV = reinterpret_cast<TombRaiderSetFOV*>(0x4026D0);
m_tombRenderCollectedItem = reinterpret_cast<TombRaiderRenderCollectedItem*>(ub ? 0x435800 : 0x435D80);
m_tombSoundSetVolume = reinterpret_cast<TombRaiderSoundSetVolume*>(ub ? 0x42AFF0 : 0x42B410);
m_tombPlayRplFile = reinterpret_cast<TombRaiderPlayRplFile*>(0x41CDF0);
// var pointers
m_tombKeyStates = reinterpret_cast<uint8_t**>(ub ? 0x45B348 : 0x45B998);
m_tombNumAudioSamples = reinterpret_cast<int32_t*>(ub ? 0x45B324 : 0x45B96C);
m_tombSampleTable = reinterpret_cast<TombRaiderAudioSample***>(ub ? 0x45B314 : 0x45B954);
m_tombFMVPaths = reinterpret_cast < char **>(0x453AC0);
m_tombSoundInit1 = reinterpret_cast<BOOL*>(ub ? 0x459CF4 : 0x45A31C);
m_tombSoundInit2 = reinterpret_cast<BOOL*>(ub ? 0x459CF8 : 0x45A320);
m_tombSFXVolume = reinterpret_cast<uint8_t*>(ub ? 0x455D38 : 0x456330);
@ -452,46 +438,6 @@ int16_t TombRaiderHooks::setFOV(int16_t fov)
return m_tombSetFOV(fov);
}
BOOL TombRaiderHooks::playFMV(int32_t fmvIndex, int32_t unknown)
{
std::string path(m_tombFMVPaths[fmvIndex]);
std::string newPath = path.substr(0, path.find_last_of('.')) + ".avi";
if (::PathFileExists(std::wstring(newPath.begin(), newPath.end()).c_str()))
playAviFile(newPath.c_str());
else if (::PathFileExists(std::wstring(path.begin(), path.end()).c_str()))
m_tombPlayRplFile(fmvIndex, unknown);
return TRUE;
}
void TombRaiderHooks::playAviFile(const char *path)
{
LOG_TRACE("Play FMV: %s", path);
Context& m_context(GLRage::getContext());
MoviePlayer *moviePlayer = MoviePlayer::GetPlayer();
HRESULT hr = moviePlayer->Create(m_context.getHWnd());
if (FAILED(hr))
goto exit;
hr = moviePlayer->Play(path);
if (FAILED(hr))
goto exit;
moviePlayer->WaitForPlayback();
exit:
delete moviePlayer;
if (FAILED(hr) && hr != 0x80040216)
{
std::string str;
if (hr == 0x80040265)
str = "Try installing the codec pack from https://www.codecguide.com/";
else
str = StringUtils::format("0x%08x", hr);
MessageBox(m_context.getHWnd(), std::wstring(str.begin(), str.end()).c_str(), L"Movie playback failed", MB_OK);
}
}
BOOL TombRaiderHooks::musicPlayRemap(int16_t trackID)
{
LOG_TRACE("%d", trackID);
@ -720,4 +666,4 @@ int32_t TombRaiderHooks::getOverlayScale(int32_t base)
return static_cast<int32_t>(std::round(result));
}
} // namespace glrage
} // namespace glrage

View file

@ -1,8 +1,8 @@
#pragma once
#include <Windows.h>
#include <windows.h>
#include <mmsystem.h>
#include <dsound.h>
#include <mmeapi.h>
#include <cstdint>
#include <map>
@ -39,8 +39,6 @@ public:
static void* createFPSText(
int16_t x, int16_t y, int16_t a3, const char* text);
static int16_t setFOV(int16_t fov);
static BOOL playFMV(int32_t fmvIndex, int32_t unknown);
static void playAviFile(const char *path);
// other vars
static bool m_musicAlwaysLoop;
@ -55,4 +53,4 @@ private:
static int32_t getOverlayScale(int32_t base);
};
} // namespace glrage
} // namespace glrage

View file

@ -34,7 +34,6 @@ void TombRaiderPatch::apply()
// optional patches
applyGraphicPatches();
applySoundPatches();
applyFMVPatches();
applyKeyboardPatches();
applyLogicPatches();
}
@ -96,7 +95,9 @@ void TombRaiderPatch::applyGraphicPatches()
float filterRed = m_config.getFloat("patch.watercolor_filter_red", 0.45f);
float filterGreen = m_config.getFloat("patch.watercolor_filter_green", 1.0f);
Chunk c = Chunk() << filterRed << filterGreen;
Chunk c = Chunk();
c = c << filterRed;
c = c << filterGreen;
patch(0x451028, "9A 99 19 3F 33 33 33 3F", c);
}
@ -121,9 +122,9 @@ void TombRaiderPatch::applyGraphicPatches()
patch(m_ub ? 0x407CB4 : 0x407CA7, "58 02 00 00", height);
patch(m_ub ? 0x407CBE : 0x407CB1, "00 C0 47 44",
static_cast<float_t>(width - 1));
static_cast<float>(width - 1));
patch(m_ub ? 0x407CC8 : 0x407CBB, "00 C0 15 44",
static_cast<float_t>(height - 1));
static_cast<float>(height - 1));
// update clipping size
patch(m_ub ? 0x408A64 : 0x408A57, "20 03", static_cast<int16_t>(width));
@ -142,17 +143,17 @@ void TombRaiderPatch::applyGraphicPatches()
// UI scale patch, rescales the in-game overlay to keep the proportions
// of the 800x600 resolution on higher resolutions.
if (m_ub) {
patchAddr(0x41DA85, "E8 76 23 01 00", TombRaiderHooks::renderHealthBar, 0xE8);
patchAddr(0x41DC0C, "E8 EF 21 01 00", TombRaiderHooks::renderHealthBar, 0xE8);
patchAddr(0x41DAD7, "E8 A4 24 01 00", TombRaiderHooks::renderAirBar, 0xE8);
patchAddr(0x41DB71, "E8 8A 7C 01 00", TombRaiderHooks::renderCollectedItem, 0xE8);
patchAddr(0x4394C2, "E8 09 FC FF FF", TombRaiderHooks::createFPSText, 0xE8);
patchAddr(0x41DA85, "E8 76 23 01 00", (void*)&TombRaiderHooks::renderHealthBar, 0xE8);
patchAddr(0x41DC0C, "E8 EF 21 01 00", (void*)&TombRaiderHooks::renderHealthBar, 0xE8);
patchAddr(0x41DAD7, "E8 A4 24 01 00", (void*)&TombRaiderHooks::renderAirBar, 0xE8);
patchAddr(0x41DB71, "E8 8A 7C 01 00", (void*)&TombRaiderHooks::renderCollectedItem, 0xE8);
patchAddr(0x4394C2, "E8 09 FC FF FF", (void*)&TombRaiderHooks::createFPSText, 0xE8);
} else {
patchAddr(0x41DD85, "E8 46 25 01 00", TombRaiderHooks::renderHealthBar, 0xE8);
patchAddr(0x41DF0C, "E8 BF 23 01 00", TombRaiderHooks::renderHealthBar, 0xE8);
patchAddr(0x41DDD7, "E8 74 26 01 00", TombRaiderHooks::renderAirBar, 0xE8);
patchAddr(0x41DE71, "E8 0A 7F 01 00", TombRaiderHooks::renderCollectedItem, 0xE8);
patchAddr(0x439B72, "E8 09 FC FF FF", TombRaiderHooks::createFPSText, 0xE8);
patchAddr(0x41DD85, "E8 46 25 01 00", (void*)&TombRaiderHooks::renderHealthBar, 0xE8);
patchAddr(0x41DF0C, "E8 BF 23 01 00", (void*)&TombRaiderHooks::renderHealthBar, 0xE8);
patchAddr(0x41DDD7, "E8 74 26 01 00", (void*)&TombRaiderHooks::renderAirBar, 0xE8);
patchAddr(0x41DE71, "E8 0A 7F 01 00", (void*)&TombRaiderHooks::renderCollectedItem, 0xE8);
patchAddr(0x439B72, "E8 09 FC FF FF", (void*)&TombRaiderHooks::createFPSText, 0xE8);
}
}
@ -183,18 +184,18 @@ void TombRaiderPatch::applyGraphicPatches()
// replace FOV conversion function with custom function
patchAddr(
0x402669, "E8 62 00 00 00", TombRaiderHooks::setFOV, 0xE8);
0x402669, "E8 62 00 00 00", (void*)&TombRaiderHooks::setFOV, 0xE8);
if (m_ub) {
patchAddr(0x4113E9, "E8 E2 12 FF FF", TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x411624, "E8 A7 10 FF FF", TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41AACC, "E8 FF 7B FE FF", TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41E45F, "E8 6C 42 FE FF", TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x4113E9, "E8 E2 12 FF FF", (void*)&TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x411624, "E8 A7 10 FF FF", (void*)&TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41AACC, "E8 FF 7B FE FF", (void*)&TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41E45F, "E8 6C 42 FE FF", (void*)&TombRaiderHooks::setFOV, 0xE8);
} else {
patchAddr(0x411469, "E8 62 12 FF FF", TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41171A, "E8 B1 0F FF FF", TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41ABBC, "E8 0F 7B FE FF", TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41E7DF, "E8 EC 3E FE FF", TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x411469, "E8 62 12 FF FF", (void*)&TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41171A, "E8 B1 0F FF FF", (void*)&TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41ABBC, "E8 0F 7B FE FF", (void*)&TombRaiderHooks::setFOV, 0xE8);
patchAddr(0x41E7DF, "E8 EC 3E FE FF", (void*)&TombRaiderHooks::setFOV, 0xE8);
}
}
}
@ -248,14 +249,14 @@ void TombRaiderPatch::applyGraphicPatches()
// Set the width of diacritical signs to -1 to remove the extra spacing
// generated by them at end of the strings.
if (m_ub) {
patch(0x4565EB, "0A", "FF"); // ¨ (Combinable Diaeresis/Umlaut)
patch(0x4565EB, "0A", "FF"); // (Combinable Diaeresis/Umlaut)
patch(0x4565ED, "06", "FF"); // ^ (Combinable Circumflex)
patch(0x4565EE, "06", "FF"); // ´ (Combinable Acute Accent)
patch(0x4565EE, "06", "FF"); // (Combinable Acute Accent)
patch(0x4565F5, "10", "FF"); // ` (Combinable Grave Accent)
} else {
patch(0x456C23, "0A", "FF"); // ¨ (Combinable Diaeresis/Umlaut)
patch(0x456C23, "0A", "FF"); // (Combinable Diaeresis/Umlaut)
patch(0x456C25, "06", "FF"); // ^ (Combinable Circumflex)
patch(0x456C26, "06", "FF"); // ´ (Combinable Acute Accent)
patch(0x456C26, "06", "FF"); // (Combinable Acute Accent)
patch(0x456C2D, "10", "FF"); // ` (Combinable Grave Accent)
}
@ -305,19 +306,19 @@ void TombRaiderPatch::applySoundPatches()
// It also replaces the subroutine for normal sounds to fix the annoying
// panning issue.
if (m_ub) {
patchAddr(0x437B59, "E8 42 22 FE FF", TombRaiderHooks::soundInit, 0xE8);
patchAddr(0x4386CA, "E8 01 18 FF FF", TombRaiderHooks::soundBufferSetVolume, 0xE8);
patchAddr(0x4386EA, "E8 E1 17 FF FF", TombRaiderHooks::soundBufferSetPan, 0xE8);
patchAddr(0x4385F2, "E8 29 F2 FF FF", TombRaiderHooks::soundPlayOneShot, 0xE8);
patchAddr(0x438648, "E8 A3 F2 FF FF", TombRaiderHooks::soundPlayLoop, 0xE8);
patchAddr(0x438680, "A1 74 60 45 00", TombRaiderHooks::soundStopAll, 0xE9);
patchAddr(0x437B59, "E8 42 22 FE FF", (void*)&TombRaiderHooks::soundInit, 0xE8);
patchAddr(0x4386CA, "E8 01 18 FF FF", (void*)&TombRaiderHooks::soundBufferSetVolume, 0xE8);
patchAddr(0x4386EA, "E8 E1 17 FF FF", (void*)&TombRaiderHooks::soundBufferSetPan, 0xE8);
patchAddr(0x4385F2, "E8 29 F2 FF FF", (void*)&TombRaiderHooks::soundPlayOneShot, 0xE8);
patchAddr(0x438648, "E8 A3 F2 FF FF", (void*)&TombRaiderHooks::soundPlayLoop, 0xE8);
patchAddr(0x438680, "A1 74 60 45 00", (void*)&TombRaiderHooks::soundStopAll, 0xE9);
} else {
patchAddr(0x438129, "E8 62 1D FE FF", TombRaiderHooks::soundInit, 0xE8);
patchAddr(0x438D0A, "E8 21 F2 FF FF", TombRaiderHooks::soundBufferSetVolume, 0xE8);
patchAddr(0x438D2A, "E8 01 F2 FF FF", TombRaiderHooks::soundBufferSetPan, 0xE8);
patchAddr(0x438C32, "E8 D9 F1 FF FF", TombRaiderHooks::soundPlayOneShot, 0xE8);
patchAddr(0x438C88, "E8 33 EF FF FF", TombRaiderHooks::soundPlayLoop, 0xE8);
patchAddr(0x438CC0, "A1 88 66 45 00", TombRaiderHooks::soundStopAll, 0xE9);
patchAddr(0x438129, "E8 62 1D FE FF", (void*)&TombRaiderHooks::soundInit, 0xE8);
patchAddr(0x438D0A, "E8 21 F2 FF FF", (void*)&TombRaiderHooks::soundBufferSetVolume, 0xE8);
patchAddr(0x438D2A, "E8 01 F2 FF FF", (void*)&TombRaiderHooks::soundBufferSetPan, 0xE8);
patchAddr(0x438C32, "E8 D9 F1 FF FF", (void*)&TombRaiderHooks::soundPlayOneShot, 0xE8);
patchAddr(0x438C88, "E8 33 EF FF FF", (void*)&TombRaiderHooks::soundPlayLoop, 0xE8);
patchAddr(0x438CC0, "A1 88 66 45 00", (void*)&TombRaiderHooks::soundStopAll, 0xE9);
}
// Very optional patch: change ambient track in Lost Valley from "derelict"
@ -332,15 +333,15 @@ void TombRaiderPatch::applySoundPatches()
// Patch bad mapping function in UB that remaps the music volume from 0-10
// to 5-255 instead of 0-65536, which is the value range for auxSetVolume.
if (m_ub) {
patchAddr(0x438A70, "0F BF 44 24 04", TombRaiderHooks::musicSetVolume, 0xE9);
patchAddr(0x438A70, "0F BF 44 24 04", (void*)&TombRaiderHooks::musicSetVolume, 0xE9);
}
// Patch missing music volume updates when changing the volume in the
// options and when reading atiset.dat.
if (!m_ub) {
patchAddr(0x42E941, "E8 EA 95 00 00", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x42E94D, "E8 DE 95 00 00", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x438508, "E8 23 FA FF FF", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x42E941, "E8 EA 95 00 00", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x42E94D, "E8 DE 95 00 00", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x438508, "E8 23 FA FF FF", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
}
// Add missing music volume controls in original TR1 or disable existing ones
@ -361,52 +362,52 @@ void TombRaiderPatch::applySoundPatches()
}
} else {
if (musicMuteUnderwater) {
patchAddr(0x410B7C, "E8 AF 73 02 00", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x410BB3, "E8 78 73 02 00", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x410B7C, "E8 AF 73 02 00", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x410BB3, "E8 78 73 02 00", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
}
if (musicMuteMenu) {
patchAddr(0x41E81A, "E8 11 97 01 00", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x41F83C, "E8 EF 86 01 00", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x41F8A4, "E8 87 86 01 00", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x41E81A, "E8 11 97 01 00", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x41F83C, "E8 EF 86 01 00", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x41F8A4, "E8 87 86 01 00", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
}
// Update volume when loading a level or when starting demo mode.
// Somewhat redundant, but it doesn't harm.
patchAddr(0x41D190, "E8 9B AD 01 00", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x41D318, "E8 13 AC 01 00", TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x41D190, "E8 9B AD 01 00", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
patchAddr(0x41D318, "E8 13 AC 01 00", (void*)&TombRaiderHooks::musicSetVolume, 0xE8);
}
// Hook low-level CD play function to fix a volume bug.
patchAddr(m_ub ? 0x4379E0 : 0x437FB0, "83 EC 18 53 8B", TombRaiderHooks::musicPlay, 0xE9);
patchAddr(m_ub ? 0x4379E0 : 0x437FB0, "83 EC 18 53 8B", (void*)&TombRaiderHooks::musicPlay, 0xE9);
// Soundtrack patch. Allows both ambient and music cues to be played via
// MCI.
if (m_config.getBool("patch.full_soundtrack", false)) {
// hook play function (level music)
if (m_ub) {
patchAddr(0x438700, "66 83 3D 3C 5D", TombRaiderHooks::musicPlayRemap, 0xE9);
patchAddr(0x438700, "66 83 3D 3C 5D", (void*)&TombRaiderHooks::musicPlayRemap, 0xE9);
} else {
patchAddr(0x438D40, "66 83 3D 34 63", TombRaiderHooks::musicPlayRemap, 0xE9);
patchAddr(0x438D40, "66 83 3D 34 63", (void*)&TombRaiderHooks::musicPlayRemap, 0xE9);
}
// hook play function (cutscene music, not present in UB)
if (!m_ub) {
patchAddr(0x439030, "66 83 3D 34 63", TombRaiderHooks::musicPlayRemap, 0xE9);
patchAddr(0x439030, "66 83 3D 34 63", (void*)&TombRaiderHooks::musicPlayRemap, 0xE9);
}
// hook stop function
if (m_ub) {
patchAddr(0x438880, "66 A1 F4 34 45", TombRaiderHooks::musicStop, 0xE9);
patchAddr(0x438880, "66 A1 F4 34 45", (void*)&TombRaiderHooks::musicStop, 0xE9);
} else {
patchAddr(0x438E40, "66 A1 DC 34 45", TombRaiderHooks::musicStop, 0xE9);
patchAddr(0x438E40, "66 A1 DC 34 45", (void*)&TombRaiderHooks::musicStop, 0xE9);
}
// hook function that is called when a track has finished
if (m_ub) {
patchAddr(0x437AF0, "A1 0C B3 45 00", TombRaiderHooks::musicPlayLoop, 0xE9);
patchAddr(0x437AF0, "A1 0C B3 45 00", (void*)&TombRaiderHooks::musicPlayLoop, 0xE9);
} else {
patchAddr(0x4380C0, "A1 4C B9 45 00", TombRaiderHooks::musicPlayLoop, 0xE9);
patchAddr(0x4380C0, "A1 4C B9 45 00", (void*)&TombRaiderHooks::musicPlayLoop, 0xE9);
}
// also pass 0 to the CD play sub when loading a level so the background
@ -430,20 +431,15 @@ void TombRaiderPatch::applySoundPatches()
// insert missing SFX volume initialization by replacing a nullsub call
// after loading the settings
if (m_ub) {
patchAddr(0x437FA6, "E8 25 1F FF FF", TombRaiderHooks::soundUpdateVolume, 0xE8);
patchAddr(0x437FA6, "E8 25 1F FF FF", (void*)&TombRaiderHooks::soundUpdateVolume, 0xE8);
} else {
patchAddr(0x438576, "E8 B5 F9 FF FF", TombRaiderHooks::soundUpdateVolume, 0xE8);
patchAddr(0x438576, "E8 B5 F9 FF FF", (void*)&TombRaiderHooks::soundUpdateVolume, 0xE8);
}
}
void TombRaiderPatch::applyFMVPatches()
{
if (m_config.getBool("patch.fmv_override", true) && !m_ub) {
patchAddr(0x43858B, "E8 60 48 FE FF", TombRaiderHooks::playFMV, 0xE8);
patchAddr(0x43859A, "E8 51 48 FE FF", TombRaiderHooks::playFMV, 0xE8);
patchAddr(0x4385A4, "E8 47 48 FE FF", TombRaiderHooks::playFMV, 0xE8);
patchAddr(0x41D073, "E8 78 FD FF FF", TombRaiderHooks::playFMV, 0xE8);
}
// Disable an instruction in UB that removes the volume settings from the in-game menu
if (m_ub) {
patchNop(0x41F655, "66 89 15 0C 5A 45 00");
}
}
void TombRaiderPatch::applyKeyboardPatches()
@ -468,9 +464,9 @@ void TombRaiderPatch::applyKeyboardPatches()
// custom key bindings are only implemented for joystick buttons, this
// patch implements the function stub to return the previously pressed key
if (m_ub) {
patchAddr(0x42EAF8, "E8 F3 8D 00 00", TombRaiderHooks::getPressedKey, 0xE8);
patchAddr(0x42EAF8, "E8 F3 8D 00 00", (void*)&TombRaiderHooks::getPressedKey, 0xE8);
} else {
patchAddr(0x42EF35, "E8 86 8C 00 00", TombRaiderHooks::getPressedKey, 0xE8);
patchAddr(0x42EF35, "E8 86 8C 00 00", (void*)&TombRaiderHooks::getPressedKey, 0xE8);
}
}
@ -582,18 +578,18 @@ void TombRaiderPatch::applyLogicPatches()
void TombRaiderPatch::applyLocalePatches()
{
std::wstring basePath = ContextImpl::instance().getBasePath();
std::wstring localePath = basePath + L"\\patches\\locale\\";
std::string basePath = ContextImpl::instance().getBasePath();
std::string localePath = basePath + "\\patches\\locale\\";
// load locale file
std::string locale = m_config.getString("patch.localization_locale", "en_GB");
std::wstring langPath = localePath + StringUtils::utf8ToWide(locale) + L".txt";
std::string langPath = localePath + locale + ".txt";
std::ifstream langStream(langPath);
if (!langStream.good()) {
throw std::runtime_error(
StringUtils::format("Can't open translation file '%s': %s",
StringUtils::wideToUtf8(langPath),
langPath,
ErrorUtils::getSystemErrorString()));
}
@ -611,13 +607,13 @@ void TombRaiderPatch::applyLocalePatches()
}
// load string data file
std::wstring stringsPath = localePath + L"strings.txt";
std::string stringsPath = localePath + "strings.txt";
std::ifstream stringsStream(stringsPath);
if (!stringsStream.good()) {
throw std::runtime_error(
StringUtils::format("Can't open translation strings file '%s': %s",
StringUtils::wideToUtf8(stringsPath),
stringsPath,
ErrorUtils::getSystemErrorString()));
}
@ -664,4 +660,4 @@ void TombRaiderPatch::applyLocalePatches()
// clang-format on
} // namespace glrage
} // namespace glrage

View file

@ -15,7 +15,6 @@ private:
void applyCrashPatches();
void applyGraphicPatches();
void applySoundPatches();
void applyFMVPatches();
void applyKeyboardPatches();
void applyLogicPatches();
void applyLocalePatches();

View file

@ -2,7 +2,7 @@
#include "Patch.hpp"
#include <Windows.h>
#include <windows.h>
namespace glrage {
@ -17,4 +17,4 @@ private:
UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni);
};
} // namespace glrage
} // namespace glrage

View file

@ -88,11 +88,4 @@ fov_vertical = true
localization = false
; Locale used for localization.
localization_locale = en_GB
; Directory containing a texture override pack. There is no harm to this being set
; with the pack not present.
texture_directory = "TR1HD"
; Use alternative higher-quality FMV movies if present
fmv_override = true
localization_locale = en_GB

View file

@ -13,11 +13,10 @@ Config& Config::instance()
return instance;
}
void Config::load(const std::wstring& path)
void Config::load(const std::string& path)
{
std::string pathUtf = StringUtils::wideToUtf8(path);
if (ini_parse(pathUtf.c_str(), valueHandler, this)) {
LOG_INFO("Can't open ini file %s", pathUtf.c_str());
if (ini_parse(path.c_str(), valueHandler, this)) {
LOG_INFO("Can't open ini file %s", path.c_str());
}
}
@ -65,4 +64,4 @@ int Config::valueHandler(void* user, const char* section, const char* name,
return 1;
}
} // namespace glrage
} // namespace glrage

View file

@ -11,7 +11,7 @@ class Config
public:
static Config& instance();
void load(const std::wstring& path);
void load(const std::string& path);
std::string getString(
const std::string& name, const std::string& defaultValue);
int32_t getInt(const std::string& name, const int32_t defaultValue);
@ -29,4 +29,4 @@ private:
std::map<std::string, std::string> m_values;
};
} // namespace glrage
} // namespace glrage

View file

@ -5,8 +5,7 @@ namespace glrage {
void ErrorUtils::warning(const std::string& message)
{
MessageBox(hwnd, StringUtils::utf8ToWide(message).c_str(), L"Warning",
MB_ICONWARNING | MB_OK);
MessageBox(hwnd, message.c_str(), "Warning", MB_ICONWARNING | MB_OK);
}
void ErrorUtils::warning(
@ -31,8 +30,7 @@ void ErrorUtils::warning(const std::exception& exception)
void ErrorUtils::error(const std::string& message)
{
MessageBox(hwnd, StringUtils::utf8ToWide(message).c_str(), L"Error",
MB_ICONERROR | MB_OK);
MessageBox(hwnd, message.c_str(), "Error", MB_ICONERROR | MB_OK);
ExitProcess(1);
}
@ -59,7 +57,7 @@ void ErrorUtils::error(const std::exception& exception)
std::string ErrorUtils::getSystemErrorString()
{
static char error[1024];
strerror_s(error, errno);
strerror_s(error, sizeof(error), errno);
return error;
}
@ -96,4 +94,4 @@ void ErrorUtils::setHWnd(HWND _hwnd)
hwnd = _hwnd;
}
} // namespace glrage
} // namespace glrage

View file

@ -1,6 +1,6 @@
#pragma once
#include <Windows.h>
#include <windows.h>
#include <string>
namespace glrage {
@ -30,4 +30,4 @@ private:
static HWND hwnd;
};
} // namespace glrage
} // namespace glrage

View file

@ -7,19 +7,11 @@ static const size_t bufferSize = 1024;
void Logger::printf(const char* format, ...)
{
char output[bufferSize + 2]; // reserve 2 chars for \r\n
va_list list;
va_start(list, format);
vsnprintf_s(output, bufferSize, _TRUNCATE, &format[0], list);
vprintf(format, list);
va_end(list);
auto len = strnlen_s(output, bufferSize);
auto tmp = &output[len];
*tmp++ = '\r';
*tmp++ = '\n';
*tmp++ = 0;
OutputDebugStringA(output);
puts("");
}
void Logger::printf(const std::string& msg)
@ -46,4 +38,4 @@ void Logger::tracef(void* returnAddress, const char* function, const char* forma
void Logger::tracef(void* returnAddress, const char* function, const std::string& msg)
{
tracef(returnAddress, function, msg.c_str());
}
}

View file

@ -1,6 +1,6 @@
#pragma once
#include <Windows.h>
#include <windows.h>
#include <intrin.h>
#include <string>
@ -20,4 +20,4 @@ public:
static void printf(const std::string& msg);
static void tracef(void* returnAddress, const char* function, const char* format, ...);
static void tracef(void* returnAddress, const char* function, const std::string& msg);
};
};

View file

@ -77,18 +77,4 @@ std::vector<uint8_t> StringUtils::hexToBytes(const std::string& str)
return data;
}
std::wstring StringUtils::utf8ToWide(const std::string& str)
{
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>
convert;
return convert.from_bytes(str);
}
std::string StringUtils::wideToUtf8(const std::wstring& str)
{
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>
convert;
return convert.to_bytes(str);
}
} // namespace glrage
} // namespace glrage

View file

@ -14,12 +14,10 @@ public:
static std::string format(std::string fmt, ...);
static std::string bytesToHex(const std::vector<uint8_t>& data);
static std::vector<uint8_t> hexToBytes(const std::string& str);
static std::wstring utf8ToWide(const std::string& str);
static std::string wideToUtf8(const std::wstring& str);
private:
static void formatResize(std::string& str, std::string& fmt, va_list& va);
static void formatImpl(std::string& str, std::string& fmt, va_list& va);
};
} // namespace glrage
} // namespace glrage

View file

@ -7,8 +7,8 @@ http://code.google.com/p/inih/
*/
#include <stdio.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "ini.h"
@ -60,9 +60,8 @@ static char* strncpy0(char* dest, const char* src, size_t size)
/* See documentation in header file. */
int ini_parse_file(FILE* file,
int (*handler)(void*, const char*, const char*,
const char*),
void* user)
int (*handler)(void*, const char*, const char*, const char*),
void* user)
{
/* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
@ -94,8 +93,8 @@ int ini_parse_file(FILE* file,
start = line;
#if INI_ALLOW_BOM
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
(unsigned char)start[1] == 0xBB &&
(unsigned char)start[2] == 0xBF) {
(unsigned char)start[1] == 0xBB &&
(unsigned char)start[2] == 0xBF) {
start += 3;
}
#endif
@ -119,13 +118,11 @@ int ini_parse_file(FILE* file,
*end = '\0';
strncpy0(section, start + 1, sizeof(section));
*prev_name = '\0';
}
else if (!error) {
} else if (!error) {
/* No ']' found on section line */
error = lineno;
}
}
else if (*start && *start != ';') {
} else if (*start && *start != ';') {
/* Not a comment, must be a name[=:]value pair */
end = find_char_or_comment(start, '=');
if (*end != '=') {
@ -144,8 +141,7 @@ int ini_parse_file(FILE* file,
strncpy0(prev_name, name, sizeof(prev_name));
if (!handler(user, section, name, value) && !error)
error = lineno;
}
else if (!error) {
} else if (!error) {
/* No '=' or ':' found on name[=:]value line */
error = lineno;
}
@ -166,8 +162,8 @@ int ini_parse_file(FILE* file,
/* See documentation in header file. */
int ini_parse(const char* filename,
int (*handler)(void*, const char*, const char*, const char*),
void* user)
int (*handler)(void*, const char*, const char*, const char*),
void* user)
{
FILE* file;
int error;

View file

@ -12,35 +12,40 @@ http://code.google.com/p/inih/
/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#include <stdio.h>
/* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
pairs are also supported as a concession to Python's ConfigParser.
/* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
pairs are also supported as a concession to Python's ConfigParser.
For each name=value pair parsed, call handler function with given user
pointer as well as section, name, and value (data only valid for duration
of handler call). Handler should return nonzero on success, zero on error.
For each name=value pair parsed, call handler function with given user
pointer as well as section, name, and value (data only valid for duration
of handler call). Handler should return nonzero on success, zero on error.
Returns 0 on success, line number of first error on parse error (doesn't
stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero).
*/
int ini_parse(const char* filename,
int (*handler)(void* user, const char* section,
const char* name, const char* value),
void* user);
Returns 0 on success, line number of first error on parse error (doesn't
stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero).
*/
int ini_parse(const char* filename,
int (*handler)(void* user,
const char* section,
const char* name,
const char* value),
void* user);
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
close the file when it's finished -- the caller must do that. */
int ini_parse_file(FILE* file,
int (*handler)(void* user, const char* section,
const char* name, const char* value),
void* user);
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
close the file when it's finished -- the caller must do that. */
int ini_parse_file(FILE* file,
int (*handler)(void* user,
const char* section,
const char* name,
const char* value),
void* user);
/* Nonzero to allow multi-line value parsing, in the style of Python's
ConfigParser. If allowed, ini_parse() will call the handler with the same

View file

@ -1,6 +1,7 @@
project('Tomb1Main', 'c',
project('Tomb1Main', ['c', 'cpp'],
default_options: [
'c_std=gnu11',
'c_std=c11',
'cpp_std=c++17',
'warning_level=2',
],
)
@ -17,28 +18,33 @@ if git.found()
endif
endif
compiler = meson.get_compiler('c')
c_compiler = meson.get_compiler('c')
cpp_compiler = meson.get_compiler('cpp')
is_mingw = compiler.get_id() == 'gcc' and host_machine.system() == 'windows'
is_mingw = c_compiler.get_id() == 'gcc' and host_machine.system() == 'windows'
if is_mingw
add_project_link_arguments('-municode', '-static-libgcc', language: 'c')
add_project_link_arguments(['-static-libgcc'], language: 'c')
add_project_link_arguments(['-static', '-static-libgcc', '-static-libstdc++'], language: 'cpp')
endif
build_opts = [
'-Wno-unused',
'-D_GNU_SOURCE',
]
c_opts = [
'-DVERSION="T1M ' + version_pretty + '"'
]
c_opts = []
cpp_opts = []
add_project_arguments(build_opts + c_opts, language: 'c')
add_project_arguments(build_opts + cpp_opts, language: 'cpp')
dep_ddraw = compiler.find_library('ddraw')
dep_dinput8 = compiler.find_library('dinput8')
dep_dsound = compiler.find_library('dsound')
dep_dxguid = compiler.find_library('dxguid')
dep_shlwapi = compiler.find_library('shlwapi')
dep_winmm = compiler.find_library('winmm')
dep_opengl32 = cpp_compiler.find_library('opengl32')
dep_ddraw = c_compiler.find_library('ddraw')
dep_dinput8 = c_compiler.find_library('dinput8')
dep_dsound = c_compiler.find_library('dsound')
dep_dxguid = c_compiler.find_library('dxguid')
dep_winmm = c_compiler.find_library('winmm')
dep_version = c_compiler.find_library('version')
dep_shlwapi = c_compiler.find_library('shlwapi')
# autogenerated files
version_res = []
@ -62,6 +68,67 @@ if python3.found()
endif
endif
glrage = shared_library(
'glrage',
[
'lib/ati3dcif/DllMain.cpp',
'lib/ati3dcif/Error.cpp',
'lib/ati3dcif/Renderer.cpp',
'lib/ati3dcif/State.cpp',
'lib/ati3dcif/StateVar.cpp',
'lib/ati3dcif/Texture.cpp',
'lib/ati3dcif/TransDelay.cpp',
'lib/ati3dcif/Utils.cpp',
'lib/ati3dcif/VertexStream.cpp',
'lib/ddraw/Blitter.cpp',
'lib/ddraw/DebugUtils.cpp',
'lib/ddraw/DirectDraw.cpp',
'lib/ddraw/DirectDrawClipper.cpp',
'lib/ddraw/DirectDrawSurface.cpp',
'lib/ddraw/DllMain.cpp',
'lib/ddraw/Renderer.cpp',
'lib/ddraw/Unknown.cpp',
'lib/glrage/ContextImpl.cpp',
'lib/glrage/DllMain.cpp',
'lib/glrage/GLRage.cpp',
'lib/glrage/Screenshot.cpp',
'lib/glrage_gl/Buffer.cpp',
'lib/glrage_gl/Program.cpp',
'lib/glrage_gl/Sampler.cpp',
'lib/glrage_gl/Screenshot.cpp',
'lib/glrage_gl/Shader.cpp',
'lib/glrage_gl/Texture.cpp',
'lib/glrage_gl/Utils.cpp',
'lib/glrage_gl/VertexArray.cpp',
'lib/glrage_gl/gl_core_3_3.c',
'lib/glrage_gl/wgl_ext.c',
'lib/glrage_patch/AssaultRigsPatch.cpp',
'lib/glrage_patch/Patch.cpp',
'lib/glrage_patch/RuntimePatcher.cpp',
'lib/glrage_patch/TombRaiderHooks.cpp',
'lib/glrage_patch/TombRaiderPatch.cpp',
'lib/glrage_patch/WipeoutPatch.cpp',
'lib/glrage_util/Config.cpp',
'lib/glrage_util/ErrorUtils.cpp',
'lib/glrage_util/Logger.cpp',
'lib/glrage_util/StringUtils.cpp',
'lib/glrage_util/ini.c',
],
name_prefix: '',
include_directories: ['lib/', 'lib/glm/'],
cpp_args: [
'-D_USE_MATH_DEFINES',
'-DGLR_EXPORTS',
'-DWIN32_LEAN_AND_MEAN',
],
dependencies: [
dep_winmm,
dep_version,
dep_shlwapi,
dep_opengl32,
],
)
sources = [
'src/3dsystem/3d_gen.c',
'src/3dsystem/phd_math.c',
@ -192,7 +259,6 @@ sources = [
'src/global/vars.c',
'src/global/vars_platform.c',
'src/init.c',
'src/inject.c',
'src/inject_util.c',
'src/json.c',
'src/log.c',