mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 12:47:58 +03:00
l/glrage: add mingw fixes; build
This commit is contained in:
parent
7a2adfd4b9
commit
146e32ee94
63 changed files with 14347 additions and 6831 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "lib/glm"]
|
||||
path = lib/glm
|
||||
url = https://github.com/g-truc/glm
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
485
lib/ati3dcif/ATI3DCIF.h
Normal 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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
1
lib/glm
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 8f39bb8730d45570384f3156eb0126b835024d69
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,4 +17,4 @@ GLRAPI Config& GLRage::getConfig()
|
|||
return Config::instance();
|
||||
}
|
||||
|
||||
} // namespace glrage
|
||||
} // namespace glrage
|
|
@ -1,6 +0,0 @@
|
|||
#include "MoviePlayerImpl.hpp"
|
||||
|
||||
MoviePlayer *MoviePlayer::GetPlayer()
|
||||
{
|
||||
return new MoviePlayerImpl();
|
||||
}
|
|
@ -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();
|
||||
};
|
|
@ -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");
|
||||
}
|
|
@ -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);
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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%
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -15,7 +15,6 @@ private:
|
|||
void applyCrashPatches();
|
||||
void applyGraphicPatches();
|
||||
void applySoundPatches();
|
||||
void applyFMVPatches();
|
||||
void applyKeyboardPatches();
|
||||
void applyLogicPatches();
|
||||
void applyLocalePatches();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
94
meson.build
94
meson.build
|
@ -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',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue