Tweaked the path to load global shaders in the previous commit

* although 3.8 doesn't have the path issue as 4.x due to the lack of
loading custom .dat, it's better to unify the path in this case.

Refactored the code for DataLoadOrderPatch in the same way as 4.x.
This commit is contained in:
NovaRain
2019-12-15 10:31:50 +08:00
parent d73859fa5f
commit a9ad1a62eb
6 changed files with 57 additions and 48 deletions
+1 -1
View File
@@ -65,7 +65,7 @@ GraphicsWidth=0
GraphicsHeight=0
;Uncomment the option to use a hardware shader (requires DX9 graphics mode 4 or 5)
;The shader file <name>.fx must be placed in data\shaders\ and must contain one technique with one or more passes
;The shader file <name>.fx must be placed in <GameRoot>\<master_patches>\shaders\ and must contain one technique with one or more passes
;GlobalShaderFile=global.fx
;Set to 1 to do the palette conversion on the GPU
+1 -1
View File
@@ -24,7 +24,7 @@ The input functions are only available if the user has the input hook turned on
The graphics functions are only available if the user is using graphics mode 4 or 5. Use graphics_funcs_available to check; it returns 1 if you can use them or 0 if you can't. Calling graphics functions when graphics_funcs_available returns 0 will do nothing.
load_shader takes a path relative to the data\shaders\ directory as an argument and returns a shader ID. That ID should be passed as the first argument to all other shader functions, and is valid until free_shader is called on the ID, the player loads a saved game or the player quits to the main menu.
load_shader takes a path relative to the <GameRoot>\<master_patches>\shaders\ directory as an argument and returns a shader ID. That ID should be passed as the first argument to all other shader functions, and is valid until free_shader is called on the ID, the player loads a saved game or the player quits to the main menu.
get_shader_version gives you the highest shader version supported by the player's graphics cards. Possible return values are 11, 12, 13, 14, 20, 21 and 30.
+2 -2
View File
@@ -46,7 +46,7 @@ DWORD* ptr_combat_state = reinterpret_cast<DWORD*>(_combat_state);
DWORD* ptr_combat_turn_running = reinterpret_cast<DWORD*>(_combat_turn_running);
DWORD* ptr_combatNumTurns = reinterpret_cast<DWORD*>(_combatNumTurns);
DWORD* ptr_crit_succ_eff = reinterpret_cast<DWORD*>(_crit_succ_eff);
DWORD* ptr_critter_db_handle = reinterpret_cast<DWORD*>(_critter_db_handle);
PathNode** ptr_critter_db_handle = reinterpret_cast<PathNode**>(_critter_db_handle);
DWORD* ptr_critterClearObj = reinterpret_cast<DWORD*>(_critterClearObj);
DWORD* ptr_crnt_func = reinterpret_cast<DWORD*>(_crnt_func);
DWORD* ptr_curr_font_num = reinterpret_cast<DWORD*>(_curr_font_num);
@@ -123,7 +123,7 @@ DWORD* ptr_main_ctd = reinterpret_cast<DWORD*>(_main_ctd);
DWORD* ptr_main_window = reinterpret_cast<DWORD*>(_main_window);
DWORD* ptr_map_elevation = reinterpret_cast<DWORD*>(_map_elevation);
DWORD* ptr_map_global_vars = reinterpret_cast<DWORD*>(_map_global_vars);
DWORD* ptr_master_db_handle = reinterpret_cast<DWORD*>(_master_db_handle);
PathNode** ptr_master_db_handle = reinterpret_cast<PathNode**>(_master_db_handle);
DWORD* ptr_max = reinterpret_cast<DWORD*>(_max);
long* ptr_maxScriptNum = reinterpret_cast<long*>(_maxScriptNum);
DWORD* ptr_Meet_Frank_Horrigan = reinterpret_cast<DWORD*>(_Meet_Frank_Horrigan);
+3 -2
View File
@@ -94,6 +94,7 @@
#define _game_global_vars 0x5186C0
#define _game_ui_disabled 0x5186B4
#define _game_user_wants_to_quit 0x5186CC
#define _gconfig_file_name 0x58E978
#define _gcsd 0x51094C
#define _gdBarterMod 0x51873C
#define _gDialogMusicVol 0x5187D8
@@ -300,7 +301,7 @@ extern DWORD* ptr_combat_state;
extern DWORD* ptr_combat_turn_running;
extern DWORD* ptr_combatNumTurns;
extern DWORD* ptr_crit_succ_eff;
extern DWORD* ptr_critter_db_handle;
extern PathNode** ptr_critter_db_handle;
extern DWORD* ptr_critterClearObj;
extern DWORD* ptr_crnt_func;
extern DWORD* ptr_curr_font_num;
@@ -377,7 +378,7 @@ extern DWORD* ptr_main_ctd;
extern DWORD* ptr_main_window;
extern DWORD* ptr_map_elevation;
extern DWORD* ptr_map_global_vars;
extern DWORD* ptr_master_db_handle;
extern PathNode** ptr_master_db_handle;
extern DWORD* ptr_max;
extern long* ptr_maxScriptNum;
extern DWORD* ptr_Meet_Frank_Horrigan;
+4 -4
View File
@@ -196,8 +196,8 @@ void _stdcall SetShaderMode(DWORD d, DWORD mode) {
int _stdcall LoadShader(const char* file) {
if (!GraphicsMode || strstr(file, "..") || strstr(file, ":")) return -1;
char buf[MAX_PATH];
PathNode* pathsPtr = *ptr_paths;
sprintf_s(buf, "%s\\shaders\\%s", pathsPtr->path, file);
PathNode* masterPtr = *ptr_master_db_handle;
sprintf_s(buf, "%s\\shaders\\%s", masterPtr->path, file); // *ptr_patches
for (DWORD d = 0; d < shadersSize; d++) {
if (!shaders[d].Effect) {
if (FAILED(D3DXCreateEffectFromFile(d3d9Device, buf, 0, 0, 0, 0, &shaders[d].Effect, 0))) {
@@ -218,7 +218,7 @@ int _stdcall LoadShader(const char* file) {
sprintf(buf, "texname%d", i);
if (FAILED(shader.Effect->GetString(buf, &name))) break;
sprintf_s(buf, "%s\\art\\stex\\%s", *ptr_patches, name);
sprintf_s(buf, "%s\\art\\stex\\%s", masterPtr->path, name); // *ptr_patches
if (FAILED(D3DXCreateTextureFromFileA(d3d9Device, buf, &tex))) continue;
sprintf(buf, "tex%d", i);
shader.Effect->SetTexture(buf, tex);
@@ -1123,11 +1123,11 @@ void GraphicsInit() {
if (!h) {
MessageBoxA(0, "You have selected graphics mode 4 or 5, but " _DLL_NAME " is missing.\n"
"Switch back to mode 0, or install an up to date version of DirectX.", "Error", MB_TASKMODAL | MB_ICONERROR);
#undef _DLL_NAME
ExitProcess(-1);
} else {
FreeLibrary(h);
}
#undef _DLL_NAME
SafeWrite8(0x50FB6B, '2'); // Set call DirectDrawCreate2
HookCall(0x44260C, game_init_hook);
dlogr(" Done", DL_INIT);
+46 -38
View File
@@ -21,37 +21,34 @@
static std::vector<int> savPrototypes;
static void __declspec(naked) RemoveDatabase() {
__asm {
cmp eax, -1;
je end;
mov ebx, ds:[_paths];
mov ecx, ebx;
nextPath:
mov edx, [esp + 0x104 + 4 + 4]; // path_patches
mov eax, [ebx]; // database.path
call stricmp_;
test eax, eax; // found path?
jz skip; // Yes
mov ecx, ebx;
mov ebx, [ebx + 0xC]; // database.next
jmp nextPath;
skip:
mov eax, [ebx + 0xC]; // database.next
mov [ecx + 0xC], eax; // database.next
xchg ebx, eax;
cmp eax, ecx;
jne end;
mov ds:[_paths], ebx;
end:
retn;
static PathNode* __fastcall RemoveDatabase(const char* pathPatches) {
PathNode* paths = *ptr_paths; // curr.node (beginning of the chain of paths)
PathNode* pPaths = paths; // prev.node
while (paths) {
if (_stricmp(paths->path, pathPatches) == 0) { // found path
PathNode* nextPaths = paths->next; // pointer to the node of the next path
// TODO: need to check if this condition is used correctly
if (paths != pPaths)
pPaths->next = nextPaths; // replace the pointer in the previous node, removing the current(found) path from the chain
else // if the current node is equal to the previous node
*ptr_paths = nextPaths; // set the next node at the beginning of the chain
return paths; // return the pointer of the current removed node (save the pointer)
}
pPaths = paths; // prev.node <- curr.node
paths = paths->next; // take a pointer to the next path from the current node
}
return nullptr; // it's possible that this will create an exceptional situation for the game, although such a situation should not arise
}
// Remove master_patches from the chain
static void __declspec(naked) game_init_databases_hack1() {
__asm {
cmp eax, -1;
je skip;
mov ecx, [esp + 0x104 + 4]; // path_patches
call RemoveDatabase;
skip:
mov ds:[_master_db_handle], eax; // the pointer of master_patches node will be saved here
retn;
}
@@ -67,7 +64,7 @@ static void __declspec(naked) game_init_databases_hack2() {
call xremovepath_;
dec eax; // remove path (critter_patches == master_patches)?
jz end; // Yes (jump if 0)
inc eax;
mov ecx, [esp + 0x104 + 4]; // path_patches
call RemoveDatabase;
end:
mov ds:[_critter_db_handle], eax; // the pointer of critter_patches node will be saved here
@@ -75,20 +72,29 @@ end:
}
}
static void __declspec(naked) game_init_databases_hook() {
// eax = _master_db_handle
__asm {
mov ecx, ds:[_critter_db_handle];
mov edx, ds:[_paths];
test ecx, ecx;
jz skip;
mov [ecx + 0xC], edx; // critter_patches.next->_paths
mov edx, ecx;
skip:
mov [eax + 0xC], edx; // master_patches.next
mov ds:[_paths], eax;
retn;
static void __fastcall game_init_databases_hook() { // eax = _master_db_handle
PathNode* master_patches = *ptr_master_db_handle;
PathNode* critter_patches = *ptr_critter_db_handle;
PathNode* paths = *ptr_paths; // beginning of the chain of paths
// insert master_patches/critter_patches at the beginning of the chain of paths
if (critter_patches) {
critter_patches->next = paths; // critter_patches.next -> paths
paths = critter_patches;
}
master_patches->next = paths; // master_patches.next -> paths
*ptr_paths = master_patches; // set master_patches node at the beginning of the chain of paths
}
static void __fastcall game_init_databases_hook1() {
char masterPatch[MAX_PATH];
iniGetString("system", "master_patches", "", masterPatch, MAX_PATH - 1, (const char*)_gconfig_file_name);
PathNode* node = *ptr_paths;
while (node->next) {
if (!_stricmp(node->path, masterPatch)) break;
node = node->next;
}
*ptr_master_db_handle = node; // set pointer to master_patches node
}
static void MultiPatchesPatch() {
@@ -251,6 +257,8 @@ void LoadOrderInit() {
HookCall(0x44436D, game_init_databases_hook);
SafeWrite8(0x4DFAEC, 0x1D); // error correction (ecx > ebx)
dlogr(" Done", DL_INIT);
} else {
HookCall(0x44436D, game_init_databases_hook1);
}
dlog("Applying party member protos save/load patch.", DL_INIT);