Fixed and improved Use32BitHeadGraphics option:

* Fixed the position of the talking head texture when the game res is
larger than 640x480.

* Added the support to use textures without the need of patching
talking head FRM files.
This commit is contained in:
NovaRain
2019-04-23 07:35:18 +08:00
parent cbe31e845c
commit 2df1dfbadc
7 changed files with 340 additions and 207 deletions
+3 -1
View File
@@ -70,7 +70,9 @@ GraphicsHeight=0
;GPU is faster, but requires v2.0 pixel shader support
GPUBlt=0
;Set to 1 to allow using 32 bit graphics for talking heads
;Set to 1 to allow using 32-bit .png textures for talking heads
;The texture files should be placed in art/heads/<name of the talking head FRM file>/ (w/o extension)
;The files in the folder should be numbered according to the number of frames in the talking head FRM file (e.g. 0.png - 10.png)
;Requires DX9 graphics mode and v2.0 pixel shader support (see GPUBlt option)
Use32BitHeadGraphics=0
+124 -56
View File
@@ -27,9 +27,6 @@
#endif
#endif
#include <d3d9.h>
#include <d3dx9.h>
#include <ddraw.h>
#include <math.h>
#include <stdio.h>
#include <vector>
@@ -51,7 +48,9 @@ typedef IDirect3D9* (_stdcall *D3DCreateProc)(UINT version);
static DWORD ResWidth;
static DWORD ResHeight;
static DWORD GPUBlt;
DWORD GPUBlt;
DWORD GraphicsMode;
static BYTE* titlesBuffer = nullptr;
static DWORD movieHeight = 0;
@@ -91,40 +90,42 @@ static IDirect3DTexture9* movieTex = 0;
static ID3DXEffect* gpuBltEffect;
static const char* gpuEffect=
"texture image;\n"
"texture palette;\n"
"texture head;\n"
"sampler s0 = sampler_state { texture=<image>; MAGFILTER=POINT; MINFILTER=POINT; };\n"
"sampler s1 = sampler_state { texture=<palette>; MAGFILTER=POINT; MINFILTER=POINT; };\n"
"sampler s2 = sampler_state { texture=<head>; MAGFILTER=POINT; MINFILTER=POINT; };\n"
"float2 size;\n"
"float2 corner;\n"
"float4 P0( in float2 Tex : TEXCOORD0 ) : COLOR0 {\n"
" float3 result = tex1D(s1, tex2D(s0, Tex).a);\n"
" return float4(result.b, result.g, result.r, 1);\n"
"}\n"
"float4 P1( in float2 Tex : TEXCOORD0 ) : COLOR0 {\n"
" float backdrop = tex2D(s0, Tex).a;\n"
" float3 result;\n"
" if(abs(backdrop-(48.0/255.0))<0.001) {\n"
//" float2 size = float2(388.0/640.0, 200.0/480.0);\n"
//" float2 corner = float2(126.0/640.0, 14.0/480.0);\n"
" result = tex2D(s2, saturate((Tex-corner)/size));\n"
" } else {\n"
" result = tex1D(s1, backdrop);\n"
" result = float3(result.b, result.g, result.r);\n"
" }\n"
" return float4(result.r, result.g, result.b, 1);\n"
"}\n"
"technique T0\n"
"{\n"
" pass p0 { PixelShader = compile ps_2_0 P0(); }\n"
"}\n"
"technique T1\n"
"{\n"
" pass p1 { PixelShader = compile ps_2_0 P1(); }\n"
"}\n"
;
"texture image;"
"texture palette;"
"texture head;"
"sampler s0 = sampler_state { texture=<image>; };"
"sampler s1 = sampler_state { texture=<palette>; };"
"sampler s2 = sampler_state { texture=<head>; minFilter=linear; magFilter=linear; addressU=clamp; addressV=clamp; };"
"float2 size;"
"float2 corner;"
// shader for displaying head textures
"float4 P1( in float2 Tex : TEXCOORD0 ) : COLOR0 {"
" float backdrop = tex2D(s0, Tex).a;"
" float3 result;"
" if(abs(backdrop - 1.0) < 0.001) {" // (48.0 / 255.0) // 48 - key index color
" result = tex2D(s2, saturate((Tex - corner) / size));"
" } else {"
" result = tex1D(s1, backdrop);"
" result = float3(result.b, result.g, result.r);"
" }"
" return float4(result.r, result.g, result.b, 1);"
"}"
"technique T1"
"{"
" pass p1 { PixelShader = compile ps_2_0 P1(); }"
"}"
"float4 P0( in float2 Tex : TEXCOORD0 ) : COLOR0 {"
" float3 result = tex1D(s1, tex2D(s0, Tex).a);"
" return float4(result.b, result.g, result.r, 1);"
"}"
"technique T0"
"{"
" pass p0 { PixelShader = compile ps_2_0 P0(); }"
"}";
static D3DXHANDLE gpuBltBuf;
static D3DXHANDLE gpuBltPalette;
@@ -134,8 +135,6 @@ static D3DXHANDLE gpuBltHeadCorner;
static float rcpres[2];
DWORD GraphicsMode;
struct sShader {
ID3DXEffect* Effect;
bool Active;
@@ -173,10 +172,23 @@ void GetFalloutWindowInfo(DWORD* width, DWORD* height, HWND* wnd) {
*wnd = window;
}
long Gfx_GetGameWidthRes() {
return ptr_scr_size->offx - (ptr_scr_size->x + 1);
}
long Gfx_GetGameHeightRes() {
return ptr_scr_size->offy - (ptr_scr_size->y + 1);
}
int _stdcall GetShaderVersion() {
return ShaderVersion;
}
void rcpresInit() {
rcpres[0] = 1.0f / (float)Gfx_GetGameWidthRes();
rcpres[1] = 1.0f / (float)Gfx_GetGameHeightRes();
}
void _stdcall SetShaderMode(DWORD d, DWORD mode) {
if (d >= shaders.size() || !shaders[d].Effect) return;
if (mode & 0x80000000) {
@@ -187,7 +199,7 @@ void _stdcall SetShaderMode(DWORD d, DWORD mode) {
}
int _stdcall LoadShader(const char* path) {
if ((GraphicsMode < 4) || (strstr(path, "..")) || (strstr(path, ":"))) return -1;
if (!GraphicsMode || strstr(path, "..") || strstr(path, ":")) return -1;
char buf[MAX_PATH];
sprintf(buf, "%s\\shaders\\%s", *(char**)_patches, path);
for (DWORD d = 0; d < shaders.size(); d++) {
@@ -301,9 +313,12 @@ static void ResetDevice(bool CreateNew) {
D3DXCreateEffect(d3d9Device, gpuEffect, strlen(gpuEffect), 0, 0, 0, 0, &gpuBltEffect, 0);
gpuBltBuf = gpuBltEffect->GetParameterByName(0, "image");
gpuBltPalette = gpuBltEffect->GetParameterByName(0, "palette");
// for head textures
gpuBltHead = gpuBltEffect->GetParameterByName(0, "head");
gpuBltHeadSize = gpuBltEffect->GetParameterByName(0, "size");
gpuBltHeadCorner = gpuBltEffect->GetParameterByName(0, "corner");
Gfx_SetDefaultTechnique();
}
} else {
d3d9Device->Reset(&params);
@@ -548,18 +563,31 @@ void _stdcall PlayMovieFrame() {
Present();
}
void _stdcall SetHeadTex(IDirect3DTexture9* tex, int width, int height, int xoff, int yoff) {
if (tex) {
void Gfx_SetHeadTex(IDirect3DTexture9* tex, int width, int height, int xoff, int yoff) {
gpuBltEffect->SetTexture(gpuBltHead, tex);
float size[2];
size[0] = ((float)width)*rcpres[0];
size[1] = ((float)height)*rcpres[1];
size[0] = (float)width * rcpres[0];
size[1] = (float)height * rcpres[1];
gpuBltEffect->SetFloatArray(gpuBltHeadSize, size, 2);
size[0] = (126.0f + xoff + (388 - width) / 2)*rcpres[0];
size[1] = (14.0f + yoff + (200 - height) / 2)*rcpres[1];
// adjust head texture position for HRP 4.1.8
int h = Gfx_GetGameHeightRes();
if (h > 480) yoff += ((h - 480) / 2) - 47;
xoff += ((Gfx_GetGameWidthRes() - 640) / 2);
size[0] = (126.0f + xoff + ((388 - width) / 2)) * rcpres[0];
size[1] = (14.0f + yoff + ((200 - height) / 2)) * rcpres[1];
gpuBltEffect->SetFloatArray(gpuBltHeadCorner, size, 2);
Gfx_SetHeadTechnique();
}
void Gfx_SetHeadTechnique() {
gpuBltEffect->SetTechnique("T1");
} else
}
void Gfx_SetDefaultTechnique() {
gpuBltEffect->SetTechnique("T0");
}
@@ -959,8 +987,6 @@ public:
if (!d3d9Device) {
ResetDevice(true);
CoInitialize(0);
if (GPUBlt) HeadsInit();
}
dlog("Creating D3D9 Device window...", DL_MAIN);
@@ -990,8 +1016,8 @@ public:
HRESULT _stdcall FakeDirectDrawCreate2(void*, IDirectDraw** b, void*) {
dlog("Initializing Direct3D...", DL_MAIN);
ResWidth = *(DWORD*)0x4CAD6B;
ResHeight = *(DWORD*)0x4CAD66;
ResWidth = *(DWORD*)0x4CAD6B; // 640
ResHeight = *(DWORD*)0x4CAD66; // 480
if (!d3d9) {
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
@@ -1023,21 +1049,63 @@ HRESULT _stdcall FakeDirectDrawCreate2(void*, IDirectDraw** b, void*) {
}
GPUBlt = GetPrivateProfileIntA("Graphics", "GPUBlt", 0, ini);
if (!GPUBlt || GPUBlt > 2) GPUBlt = 2; // Swap them around to keep compatibility with old ddraw.ini's
else if (GPUBlt == 2) GPUBlt = 0;
else if (GPUBlt == 2) GPUBlt = 0; // Use CPU
if (GraphicsMode == 5) {
ScrollWindowKey = GetPrivateProfileInt("Input", "WindowScrollKey", 0, ini);
} else ScrollWindowKey = 0;
rcpres[0] = 1.0f / (float)gWidth;
rcpres[1] = 1.0f / (float)gHeight;
*b = (IDirectDraw*)new FakeDirectDraw2();
dlogr(" Done.", DL_MAIN);
return DD_OK;
}
static double fadeMulti;
static __declspec(naked) void palette_fade_to_hook() {
__asm {
push ebx; // _fade_steps
fild [esp];
fmul fadeMulti;
fistp [esp];
pop ebx;
jmp fadeSystemPalette_;
}
}
void GraphicsInit() {
GraphicsMode = GetPrivateProfileIntA("Graphics", "Mode", 0, ini);
if (GraphicsMode != 4 && GraphicsMode != 5) {
GraphicsMode = 0;
}
if (GraphicsMode == 4 || GraphicsMode == 5) {
dlog("Applying DX9 graphics patch.", DL_INIT);
#ifdef WIN2K
#define _DLL_NAME "d3dx9_42.dll"
#else
#define _DLL_NAME "d3dx9_43.dll"
#endif
HMODULE h = LoadLibraryEx(_DLL_NAME, 0, LOAD_LIBRARY_AS_DATAFILE);
if (!h) {
MessageBoxA(0, "You have selected graphics mode 4 or 5, but " _DLL_NAME " is missing\nSwitch back to mode 0, or install an up to date version of DirectX", "Error", 0);
ExitProcess(-1);
} else {
FreeLibrary(h);
}
#undef _DLL_NAME
SafeWrite8(0x50FB6B, '2'); // Set call DirectDrawCreate2
dlogr(" Done", DL_INIT);
}
fadeMulti = GetPrivateProfileIntA("Graphics", "FadeMultiplier", 100, ini);
if (fadeMulti != 100) {
dlog("Applying fade patch.", DL_INIT);
HookCall(0x493B16, palette_fade_to_hook);
fadeMulti = ((double)fadeMulti) / 100.0;
dlogr(" Done", DL_INIT);
}
}
void GraphicsExit() {
if (GraphicsMode != 0) {
if (titlesBuffer) delete[] titlesBuffer;
+14
View File
@@ -18,10 +18,24 @@
#pragma once
#include <d3d9.h>
#include <d3dx9.h>
#include <ddraw.h>
extern DWORD GraphicsMode;
extern DWORD GPUBlt;
void GraphicsResetOnGameLoad();
void GraphicsInit();
void GraphicsExit();
long Gfx_GetGameWidthRes();
long Gfx_GetGameHeightRes();
void Gfx_SetHeadTex(IDirect3DTexture9* tex, int width, int height, int xoff, int yoff);
void Gfx_SetHeadTechnique();
void Gfx_SetDefaultTechnique();
void rcpresInit();
int _stdcall GetShaderVersion();
int _stdcall LoadShader(const char*);
void _stdcall ActivateShader(DWORD);
+11 -2
View File
@@ -258,16 +258,25 @@ static void __declspec(naked) EndLoadHook() {
}
}
static void _stdcall GameInitialized() {
static void __stdcall GameInitialization() {
MusicVolInitialization();
}
static void __stdcall GameInitialized() {
rcpresInit();
if (Use32BitTalkingHeads) TalkingHeadsSetup();
}
static void __declspec(naked) GameInitHook() {
__asm {
pushadc;
call GameInitialization;
popadc;
call main_init_system_;
pushadc;
call GameInitialized;
popadc;
jmp main_init_system_;
retn;
}
}
+149 -76
View File
@@ -16,21 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include <d3d9.h>
#include <d3dx9.h>
#include <stdio.h>
#include <hash_map>
#include "FalloutEngine.h"
void _stdcall SetHeadTex(IDirect3DTexture9* tex, int width, int height, int xoff, int yoff);
#include "main.h"
#include "FalloutEngine.h"
#include "Graphics.h"
#include "TalkingHeads.h"
extern IDirect3DDevice9* d3d9Device;
static stdext::hash_map<__int64, IDirect3DTexture9**> texMap;
typedef stdext::hash_map<__int64, IDirect3DTexture9**> :: iterator tex_itr;
typedef stdext::hash_map<__int64, IDirect3DTexture9**> :: const_iterator tex_citr;
static BYTE overridden=0;
#pragma pack(push, 1)
struct Frm {
@@ -61,82 +57,130 @@ struct Frm {
};
};
};
struct Frame {
WORD width;
WORD height;
DWORD size;
WORD xoffset;
WORD yoffset;
BYTE data[1];
};
#pragma pack(pop)
static Frame* FramePointer(const Frm* frm, int frameno) {
Frame* result;
__asm {
mov eax, frm;
mov edx, frameno;
xor ebx, ebx;
call frame_ptr_;
mov result, eax;
}
return result;
struct TextureData {
IDirect3DTexture9** textures;
BYTE showHighlights;
BYTE bakedBackground;
int frames;
TextureData(IDirect3DTexture9** tex, BYTE show, BYTE baked, int frames)
: textures(tex), showHighlights(show), bakedBackground(baked), frames(frames) {}
};
typedef stdext::hash_map<__int64, TextureData> :: iterator tex_itr;
typedef stdext::hash_map<__int64, TextureData> :: const_iterator tex_citr;
static stdext::hash_map<__int64, TextureData> texMap;
static const char* headSuffix[] = { "gv", "gf", "gn", "ng", "nf", "nb", "bn", "bf", "bv", "gp", "np", "bp" };
static BYTE showHighlights;
static long reactionID;
bool Use32BitTalkingHeads = false;
/* Head FID
0-000-1000-00000000-0000-000000000000
ID3 Type ID2 ID1 .lst index
*/
static bool GetHeadFrmName(char* name) {
int headFid = (*(DWORD*)_lips_draw_head)
? *ptr_lipsFID
: *ptr_fidgetFID;
int index = headFid & 0xFFF;
if (index >= ptr_art[8].total) return true; // OBJ_TYPE_HEAD
int ID2 = (*(DWORD*)_fidgetFp) ? (headFid & 0xFF0000) >> 16 : reactionID;
if (ID2 > 11) return true;
int ID1 = (ID2 == 1 || ID2 == 4 || ID2 == 7) ? (headFid & 0xF000) >> 12 : -1;
//if (ID1 > 3) ID1 = 3;
const char* headLst = ptr_art[8].names; // OBJ_TYPE_HEAD
char* fmt = (ID1 != -1) ? "%s%s%d" : "%s%s";
_snprintf(name, 8, fmt, &headLst[13 * index], headSuffix[ID2], ID1);
return false;
}
static void LoadFrm(Frm* frm) {
static void StrAppend(char* buf, const char* str, int pos) {
int i = 0;
while (pos < MAX_PATH && str[i]) buf[pos++] = str[i++];
buf[pos] = str[i]; // copy '\0'
}
static bool LoadFrm(Frm* frm) { // backporting WIP
if (!frm->key && GetHeadFrmName(frm->path)) {
frm->broken = 1;
return false;
}
tex_citr itr = texMap.find(frm->key);
if (itr == texMap.end()) {
//Load textures
// Loading head frames textures
*(DWORD*)_bk_disabled = 1;
char buf[MAX_PATH];
int pathLen = sprintf_s(buf, "%s\\art\\heads\\%s\\", *(char**)_patches, frm->path);
if (pathLen > 250) return false;
IDirect3DTexture9** textures = new IDirect3DTexture9*[frm->frames];
for (int i = 0; i < frm->frames; i++) {
sprintf(buf, "%s\\art\\heads\\%s\\%d.png", *(char**)_patches, frm->path, i);
sprintf(&buf[pathLen], "%d.png", i);
if (FAILED(D3DXCreateTextureFromFileExA(d3d9Device, buf, 0, 0, 1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, 0, 0, &textures[i]))) {
for (int j = 0; j < i; j++) textures[j]->Release();
delete[] textures;
frm->broken = 1;
return;
*(DWORD*)_bk_disabled = 0;
return false;
}
ProcessBk(); // eliminate lag when loading textures
}
if (frm->magic != 0xABCD) { // frm file not patched
StrAppend(buf, "highlight.off", pathLen);
if (GetFileAttributes(buf) != INVALID_FILE_ATTRIBUTES) frm->showHighlights = 1; // disable highlights
StrAppend(buf, "background.off", pathLen);
if (GetFileAttributes(buf) != INVALID_FILE_ATTRIBUTES) frm->bakedBackground = 1; // fills entire frame surface with a key-color
}
frm->textures = textures;
texMap[frm->key]=textures;
texMap.insert(std::make_pair(frm->key, TextureData(textures, frm->showHighlights, frm->bakedBackground, frm->frames)));
*(DWORD*)_bk_disabled = 0;
} else {
// Use preloaded textures
frm->textures=itr->second;
frm->textures = itr->second.textures;
frm->showHighlights = itr->second.showHighlights;
frm->bakedBackground = itr->second.bakedBackground;
}
//mask image
// make mask image
for (int i = 0; i < frm->frames; i++) {
Frame* frame=FramePointer(frm, i);
FrmSubframeData* frame = FramePtr((FrmFrameData*)frm, i, 0);
if (frm->bakedBackground) {
memset(frame->data, 0x30, frame->size);
memset(frame->data, 255, frame->size);
} else {
for (DWORD j = 0; j < frame->size; j++) {
if(frame->data[j]) frame->data[j]=0x30;
if (frame->data[j]) frame->data[j] = 255; // set index color
}
}
}
frm->loaded = 1;
return true;
}
static void _stdcall DrawFrmHookInternal(Frm* frm, int frameno) {
if(!frm) return;
if(frm->magic==0xabcd&&!frm->broken) {
if(!frm->loaded) LoadFrm(frm);
if(frm->broken) return;
Frame* frame=FramePointer(frm, frameno);
SetHeadTex(frm->textures[frameno], frame->width, frame->height, frame->xoffset+frm->xshift, frame->yoffset+frm->yshift);
overridden=!frm->showHighlights;
} else overridden=0;
static void __fastcall DrawHeadFrame(Frm* frm, int frameno) {
if (frm && !frm->broken) {
if (!frm->loaded && !LoadFrm(frm)) goto loadFail;
FrmSubframeData* frame = FramePtr((FrmFrameData*)frm, frameno, 0);
Gfx_SetHeadTex(frm->textures[frameno], frame->width, frame->height, frame->x + frm->xshift, frame->y + frm->yshift/*, (frm->showHighlights == 2)*/);
showHighlights = frm->showHighlights;
return;
}
loadFail:
showHighlights = 0; // show vanilla highlights
Gfx_SetDefaultTechnique();
}
static const DWORD gdDisplayFrameRet = 0x44AD06;
static void __declspec(naked) DrawFrmHook() {
static void __declspec(naked) gdDisplayFrame_hack() {
__asm {
push edx;
push eax;
push edx;
push eax;
call DrawFrmHookInternal;
mov ecx, eax; // frm file
call DrawHeadFrame; // edx - frameno
pop eax;
pop edx;
sub esp, 0x38;
@@ -145,43 +189,72 @@ static void __declspec(naked) DrawFrmHook() {
}
}
static const DWORD EndSpeechHookRet=0x447299;
void __declspec(naked) EndSpeechHook() {
void __declspec(naked) gdDestroyHeadWindow_hack() {
__asm {
push label;
push ebx;
push ecx;
push edx;
push edi;
push ebp;
jmp EndSpeechHookRet;
label:
xor eax, eax;
push eax;
push eax;
push eax;
push eax;
push eax;
call SetHeadTex;
call Gfx_SetDefaultTechnique;
mov showHighlights, 0;
pop ebp;
pop edi;
pop edx;
pop ecx;
pop ebx;
retn;
}
}
static void __declspec(naked) TransTalkHook() {
__asm {
cmp overridden, 0;
jne skip;
test showHighlights, 0xFF;
jnz skip;
jmp talk_to_translucent_trans_buf_to_buf_;
skip:
retn 0x18;
}
}
void HeadsInit() {
if (GetPrivateProfileInt("Graphics", "Use32BitHeadGraphics", 0, ini)) {
HookCall(0x44AFB4, &TransTalkHook);
HookCall(0x44B00B, &TransTalkHook);
MakeJump(0x44AD01, DrawFrmHook);
MakeJump(0x447294, EndSpeechHook);
static void __declspec(naked) gdPlayTransition_hook() {
__asm {
mov reactionID, ebx;
jmp art_id_;
}
}
static void __declspec(naked) gdialogInitFromScript_hook() {
__asm {
cmp dword ptr ds:[_dialogue_head], -1;
jnz noScroll;
jmp tile_scroll_to_;
noScroll:
retn;
}
}
void TalkingHeadsSetup() {
if (!GPUBlt) return;
HookCall(0x44AFB4, TransTalkHook);
HookCall(0x44B00B, TransTalkHook);
MakeJump(0x44AD01, gdDisplayFrame_hack); // Draw Frm
MakeJump(0x4472F8, gdDestroyHeadWindow_hack);
HookCall(0x44768B, gdPlayTransition_hook);
}
void TalkingHeadsInit() {
// Disable centering the screen if NPC has talking head
HookCall(0x445224, gdialogInitFromScript_hook);
if (GraphicsMode && GetPrivateProfileInt("Graphics", "Use32BitHeadGraphics", 0, ini)) {
Use32BitTalkingHeads = true;
}
}
void TalkingHeadsExit() {
if (!texMap.empty()) {
for (tex_citr it = texMap.begin(); it != texMap.end(); ++it) {
for (int i = 0; i < it->second.frames; i++) {
it->second.textures[i]->Release();
}
delete[] it->second.textures;
}
}
}
+5 -1
View File
@@ -1 +1,5 @@
void HeadsInit();
extern bool Use32BitTalkingHeads;
void TalkingHeadsSetup();
void TalkingHeadsInit();
void TalkingHeadsExit();
+7 -44
View File
@@ -228,20 +228,6 @@ static __declspec(naked) void PathfinderFix() {
}
}
static double FadeMulti;
static __declspec(naked) void palette_fade_to_hook() {
__asm {
//pushf;
push ebx;
fild [esp];
fmul FadeMulti;
fistp [esp];
pop ebx;
//popf;
jmp fadeSystemPalette_;
}
}
static int mapSlotsScrollMax = 27 * (17 - 7);
static __declspec(naked) void ScrollCityListFix() {
__asm {
@@ -875,6 +861,12 @@ static void DllMain2() {
dlogr("Running SpeedPatchInit().", DL_INIT);
SpeedPatchInit();
dlogr("Running GraphicsInit().", DL_INIT);
GraphicsInit();
dlogr("Running TalkingHeadsInit().", DL_INIT);
TalkingHeadsInit();
//if (GetPrivateProfileIntA("Input", "Enable", 0, ini)) {
dlog("Applying input patch.", DL_INIT);
SafeWriteStr(0x50FB70, "ddraw.dll");
@@ -882,36 +874,6 @@ static void DllMain2() {
dlogr(" Done", DL_INIT);
//}
GraphicsMode = GetPrivateProfileIntA("Graphics", "Mode", 0, ini);
if (GraphicsMode != 4 && GraphicsMode != 5) {
GraphicsMode = 0;
}
if (GraphicsMode == 4 || GraphicsMode == 5) {
dlog("Applying DX9 graphics patch.", DL_INIT);
#ifdef WIN2K
#define _DLL_NAME "d3dx9_42.dll"
#else
#define _DLL_NAME "d3dx9_43.dll"
#endif
HMODULE h = LoadLibraryEx(_DLL_NAME, 0, LOAD_LIBRARY_AS_DATAFILE);
if (!h) {
MessageBoxA(0, "You have selected graphics mode 4 or 5, but " _DLL_NAME " is missing\nSwitch back to mode 0, or install an up to date version of DirectX", "Error", 0);
ExitProcess(-1);
} else {
FreeLibrary(h);
}
#undef _DLL_NAME
SafeWrite8(0x50FB6B, '2'); // Set call DirectDrawCreate2
dlogr(" Done", DL_INIT);
}
FadeMulti = GetPrivateProfileIntA("Graphics", "FadeMultiplier", 100, ini);
if (FadeMulti != 100) {
dlog("Applying fade patch.", DL_INIT);
HookCall(0x493B16, palette_fade_to_hook);
FadeMulti = ((double)FadeMulti) / 100.0;
dlogr(" Done", DL_INIT);
}
dlogr("Running DamageModInit().", DL_INIT);
DamageModInit();
@@ -1606,6 +1568,7 @@ static void _stdcall OnExit() {
HeroAppearanceModExit();
MoviesExit();
GraphicsExit();
TalkingHeadsExit();
//SoundExit();
}