Fixed the root cause of crash in PrepareGlobalScriptsListByMask

* Calling convention violation - v141_xp uses ebx to store reference,
but db_get_file_list does not preserve it.
* v140_xp uses esi instead, which is preserved by the engine function.
* Reverted some code changes in ScriptExtender.cpp.
This commit is contained in:
NovaRain
2026-03-12 21:32:04 +08:00
parent 2db7492648
commit f5bc53d780
5 changed files with 19 additions and 12 deletions
+1 -1
View File
@@ -847,7 +847,7 @@ DivisionOperatorFix=1
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Scripts]
;Comma-separated list of masked paths to load global scripts from
;Only use single backslash \ as the directory separator
;Use only a single backslash \ as the directory separator
;Paths outside of scripts folder are supported
GlobalScriptPaths=scripts\gl*.int,scripts\sfall\gl*.int
+7
View File
@@ -167,6 +167,13 @@ long __fastcall db_init(const char* path_dat, const char* path_patches) {
WRAP_WATCOM_FCALL2(db_init_, path_dat, path_patches);
}
// Searches files in DB by given path/filename mask and stores result in fileList
// fileList is a pointer to a variable, that will be assigned with an address of an array of char* strings
long __fastcall db_get_file_list(const char* searchMask, char*** fileList) {
__asm xor ebx, ebx; // don't delete (bug in db_get_file_list_)
WRAP_WATCOM_FCALL2(db_get_file_list_, searchMask, fileList);
}
long __fastcall tile_num(long x, long y) {
__asm xor ebx, ebx; // don't delete (bug in tile_num_)
WRAP_WATCOM_FCALL2(tile_num_, x, y);
+4
View File
@@ -54,6 +54,10 @@ void interpretError(const char* fmt, ...);
long __fastcall db_init(const char* path_dat, const char* path_patches);
// Searches files in DB by given path/filename mask and stores result in fileList
// fileList is a pointer to a variable, that will be assigned with an address of an array of char* strings
long __fastcall db_get_file_list(const char* searchMask, char*** fileList); // Returns number of elements in *fileList
long __fastcall tile_num(long x, long y);
void __fastcall square_xy(long x, long y, long* outSX, long* outSY);
+1 -4
View File
@@ -307,7 +307,7 @@ WRAP_WATCOM_FUNC2(fo::DbFile*, db_fopen, const char*, path, const char*, mode)
WRAP_WATCOM_FUNC3(char*, db_fgets, char*, buf, long, max_count, fo::DbFile*, file)
WRAP_WATCOM_FFUNC4(long, db_fread, void*, buf, long, elsize, long, count, fo::DbFile*, file)
WRAP_WATCOM_FFUNC3(long, db_fseek, fo::DbFile*, file, long, pos, long, origin)
WRAP_WATCOM_FUNC2(void, db_free_file_list, char const***, fileList, DWORD, arg2) // Destroys filelist array created by db_get_file_list
WRAP_WATCOM_FUNC2(void, db_free_file_list, char***, fileList, DWORD, arg2) // Destroys filelist array created by db_get_file_list
WRAP_WATCOM_FUNC2(long, db_freadByte, fo::DbFile*, file, BYTE*, _out)
WRAP_WATCOM_FUNC2(long, db_freadShort, fo::DbFile*, file, WORD*, _out)
WRAP_WATCOM_FUNC2(long, db_freadInt, fo::DbFile*, file, DWORD*, _out)
@@ -320,9 +320,6 @@ WRAP_WATCOM_FUNC2(long, db_fwriteInt, fo::DbFile*, file, long, value)
WRAP_WATCOM_FFUNC3(long, db_fwriteByteCount, fo::DbFile*, file, const BYTE*, cptr, long, count)
//WRAP_WATCOM_FFUNC3(long, db_fwriteLongCount, fo::DbFile*, file, DWORD*, dest, long, count)
WRAP_WATCOM_FUNC2(long, db_dir_entry, const char*, fileName, DWORD*, sizeOut) // Check fallout file and get file size (result 0 - file exists)
// Searches files in DB by given path/filename mask and stores result in fileList
// fileList is a pointer to a variable, that will be assigned with an address of an array of char* strings
WRAP_WATCOM_FUNC2(long, db_get_file_list, const char*, searchMask, char const***, fileList) // Returns number of elements in *fileList
WRAP_WATCOM_FUNC1(void*, dbase_open, const char*, fileName)
WRAP_WATCOM_FUNC1(void, dbase_close, void*, dbPtr)
+6 -7
View File
@@ -25,8 +25,8 @@
#include "..\FalloutEngine\Fallout2.h"
#include "..\InputFuncs.h"
#include "..\Logging.h"
#include "..\Version.h"
#include "..\Utils.h"
#include "..\version.h"
#include "HookScripts.h"
#include "LoadGameHook.h"
#include "MainLoopHook.h"
@@ -505,7 +505,7 @@ static void LoadGlobalScriptsList() {
dlogr("Running global scripts...", DL_SCRIPT);
ScriptProgram prog;
for (auto& item : globalScriptFilesList) {
for (const auto& item : globalScriptFilesList) {
auto &scriptFile = item.second;
dlog("> " + scriptFile, DL_SCRIPT);
InitScriptProgram(prog, scriptFile.c_str(), true);
@@ -538,14 +538,13 @@ static void InitGlobalScripts() {
static void PrepareGlobalScriptsListByMask() {
globalScriptFilesList.clear();
for (const std::string fileMask : globalScriptPathList) {
char const** filenames;
for (const auto& fileMask : globalScriptPathList) {
char** filenames;
auto basePath = fileMask.substr(0, fileMask.find_last_of("\\/") + 1); // path to scripts without mask
int count = fo::func::db_get_file_list(fileMask.c_str(), &filenames);
for (int i = 0; i < count; i++) {
std::string name(filenames[i]);
ToLowerCase(name);
char* name = _strlwr(filenames[i]); // name of the script in lower case
if (name[0] != 'g' || name[1] != 'l') continue; // fix bug in db_get_file_list fuction (if the script name begins with a non-Latin character)
std::string baseName(name);
@@ -554,7 +553,7 @@ static void PrepareGlobalScriptsListByMask() {
baseName = baseName.substr(0, lastDot); // script name without extension
if (basePath != fo::var::script_path_base || !IsGameScript(baseName.c_str())) {
dlog_f("Found global script: %s\n", DL_SCRIPT, name.c_str());
dlog_f("Found global script: %s\n", DL_SCRIPT, name);
std::string fullPath(basePath);
fullPath += name;
// prevent loading global scripts with the same name from different directories