diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 6d95527a..d9cb580e 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -69,7 +69,7 @@ GraphicsHeight=0 ;Set to 0 to reset if the window position is incorrect WindowData=0 -;Uncomment the option to use a hardware shader (requires DX9 graphics mode 4 or 5) +;Uncomment the option to use a hardware shader (requires DX9 graphics mode) ;The shader file .fx must be placed in \\shaders\ and must contain one technique with one or more passes ;GlobalShaderFile=global.fx @@ -87,7 +87,7 @@ GPUBlt=0 Use32BitHeadGraphics=0 ;Set to 1 to automatically search for alternative avi video files when Fallout tries to play the game movies -;Requires DX9 graphics mode 4 or 5 +;Requires DX9 graphics mode AllowDShowMovies=0 ;Fade effect time percentage modifier @@ -160,7 +160,7 @@ SpeedKey7=0x00 SpeedKey8=0x00 SpeedKey9=0x00 -;A key to hold down to move the window around when using graphics mode 5 +;A key to hold down to move the window around when using DX9 graphics mode 5 ;Set to 0 if you don't want to use a modifier key, or a DX scancode otherwise ;Set to -1 for either ctrl key, -2 for either alt key or -3 for either shift key WindowScrollKey=0 diff --git a/sfall/BugFixes.cpp b/sfall/BugFixes.cpp index e9ecf244..2c68e289 100644 --- a/sfall/BugFixes.cpp +++ b/sfall/BugFixes.cpp @@ -3246,9 +3246,6 @@ void BugFixesInit() // Place the player on a nearby empty tile if the entrance tile is blocked by another object when entering a map HookCall(0x4836F8, map_check_state_hook); - // Remove duplicate code from intface_redraw_ engine function - BlockCall(0x45EBBF); - // Fix for critter_add/rm_trait functions ignoring the value of the "amount" argument // Note: pass negative amount values to critter_rm_trait to remove all ranks of the perk (vanilla behavior) HookCall(0x458CDB, op_critter_rm_trait_hook); diff --git a/sfall/DebugEditor.cpp b/sfall/DebugEditor.cpp index c9b6395d..f2431e60 100644 --- a/sfall/DebugEditor.cpp +++ b/sfall/DebugEditor.cpp @@ -343,16 +343,6 @@ static void __declspec(naked) debug_log_hack() { } } -static void __declspec(naked) op_display_msg_hook() { - __asm { - cmp dword ptr ds:_debug_func, 0; - jne debug; - retn; -debug: - jmp config_get_value_; - } -} - static void DebugModePatch() { int dbgMode = iniGetInt("Debugging", "DebugMode", 0, ddrawIniDef); if (dbgMode > 0) { @@ -393,8 +383,6 @@ static void DebugModePatch() { dlogr(" Done", DL_INIT); } - // Just for speeding up display_msg function (optional) - HookCall(0x455404, op_display_msg_hook); } static void DontDeleteProtosPatch() { diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index 54723c1d..ef5dcc7b 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -881,6 +881,10 @@ void __stdcall GsoundPlaySfxFile(const char* name) { WRAP_WATCOM_CALL1(gsound_play_sfx_file_, name) } +bool __stdcall ArtExists(long artFid) { + WRAP_WATCOM_CALL1(art_exists_, artFid) +} + // Returns the name of the critter const char* __stdcall CritterName(TGameObj* critter) { WRAP_WATCOM_CALL1(critter_name_, critter) @@ -1508,6 +1512,10 @@ long __stdcall ArtPtrUnlock(DWORD lockId) { WRAP_WATCOM_CALL1(art_ptr_unlock_, lockId) } +long __stdcall LightGetTile(long elevation, long tileNum) { + WRAP_WATCOM_CALL2(light_get_tile_, elevation, tileNum) +} + long __stdcall LoadFrame(const char* filename, FrmFile** frmPtr) { WRAP_WATCOM_CALL2(load_frame_, filename, frmPtr) } diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index 4dc9ebb6..6eb0dfe3 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -1073,6 +1073,8 @@ long __stdcall GetInputBtn(); // plays SFX sound with given name void __stdcall GsoundPlaySfxFile(const char* name); +bool __stdcall ArtExists(long artFid); + // Returns the name of the critter const char* __stdcall CritterName(TGameObj* critter); @@ -1325,6 +1327,9 @@ BYTE* __stdcall ArtLock(long frmId, DWORD* lockPtr, long* widthOut, long* height long __stdcall ArtPtrUnlock(DWORD lockId); +// returns light level at given tile +long __stdcall LightGetTile(long elevation, long tileNum); + long __stdcall LoadFrame(const char* filename, FrmFile** frmPtr); long __stdcall FMtextWidth(const char* text); diff --git a/sfall/PartyControl.cpp b/sfall/PartyControl.cpp index 75c62181..7614425d 100644 --- a/sfall/PartyControl.cpp +++ b/sfall/PartyControl.cpp @@ -260,14 +260,7 @@ int __fastcall PartyControl_SwitchHandHook(TGameObj* item) { int fId = *ptr_i_fid; //(*ptr_obj_dude)->artFid; char weaponCode = AnimCodeByWeapon(item); fId = (fId & 0xFFFF0FFF) | (weaponCode << 12); - // check if art with this weapon exists - int canUse; - __asm { - mov eax, fId; - call art_exists_; - mov canUse, eax; - } - if (!canUse) { + if (!ArtExists(fId)) { DisplayCantDoThat(); return 1; } @@ -313,8 +306,8 @@ gonormal: } // hack to exit from this function safely when you load game during NPC turn -static const DWORD CombatHack_add_noncoms_back = 0x422359; static void __declspec(naked) CombatHack_add_noncoms_() { + static const DWORD CombatHack_add_noncoms_back = 0x422359; __asm { call CombatWrapper_v2; cmp eax, -1; diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index 85ce9f68..55f99c8e 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -630,7 +630,7 @@ static void __declspec(naked) GetSfallArg() { call GetHSArg; mov edx, eax; mov eax, ebx; - _RET_VAL_INT2; + _RET_VAL_INT; mov ecx, esi; retn; } @@ -669,7 +669,7 @@ static void __declspec(naked) GetSfallArgs() { call GetSfallArgs2; mov edx, eax; mov eax, ebx; - _RET_VAL_INT2; + _RET_VAL_INT; mov ecx, esi; retn; } diff --git a/sfall/ScriptOps/AnimOps.hpp b/sfall/ScriptOps/AnimOps.hpp index 471dae2d..bcfce4a2 100644 --- a/sfall/ScriptOps/AnimOps.hpp +++ b/sfall/ScriptOps/AnimOps.hpp @@ -199,29 +199,27 @@ static void __declspec(naked) op_reg_anim_callback() { _WRAP_OPCODE(op_reg_anim_callback2, 1, 0) } +static void _stdcall op_explosions_metarule2() { + const ScriptValue &modeArg = opHandler.arg(0), + &arg1Arg = opHandler.arg(1), + &arg2Arg = opHandler.arg(2); + + if (modeArg.isInt() && arg1Arg.isInt() && arg2Arg.isInt()) { + int mode = modeArg.rawValue(), + result = ExplosionsMetaruleFunc(mode, arg1Arg.rawValue(), arg2Arg.rawValue()); + + if (result == -1) { + opHandler.printOpcodeError("metarule2_explosions() - mode (%d) is not supported for the function.", mode); + } + opHandler.setReturn(result); + } else { + OpcodeInvalidArgs("metarule2_explosions"); + opHandler.setReturn(-1); + } +} + static void __declspec(naked) op_explosions_metarule() { - _OP_BEGIN(ebp) - _GET_ARG_R32(ebp, ebx, esi) // arg3 - _GET_ARG_R32(ebp, ecx, edi) // arg2 - _GET_ARG_R32(ebp, edx, eax) // arg1 - // eax should not change until function call - _CHECK_ARG_INT(bx, fail) - _CHECK_ARG_INT(cx, fail) - _CHECK_ARG_INT(dx, fail) - __asm { - push esi - push edi - push eax - call ExplosionsMetaruleFunc; - jmp end; - } -fail: - __asm { - mov eax, -1 - } -end: - _RET_VAL_INT(ebp) - _OP_END + _WRAP_OPCODE(op_explosions_metarule2, 3, 1) } static void sf_art_cache_flush() { diff --git a/sfall/ScriptOps/AsmMacros.h b/sfall/ScriptOps/AsmMacros.h index 77afd35b..f5e025d4 100644 --- a/sfall/ScriptOps/AsmMacros.h +++ b/sfall/ScriptOps/AsmMacros.h @@ -113,7 +113,7 @@ __asm skipgetstr##num: \ notstring##num: // must be immediately after C function call -#define _RET_VAL_INT(rscript) __asm { \ +#define _RET_VAL_INT32(rscript) __asm { \ __asm mov edx, eax \ __asm mov eax, rscript \ __asm call interpretPushLong_ \ @@ -137,7 +137,7 @@ notstring##num: eax and ebx register must contain the script_ptr edx register must contain the returned value */ -#define _RET_VAL_INT2 __asm { \ +#define _RET_VAL_INT __asm { \ __asm call interpretPushLong_ \ __asm mov edx, VAR_TYPE_INT \ __asm mov eax, ebx \ diff --git a/sfall/ScriptOps/GraphicsOps.hpp b/sfall/ScriptOps/GraphicsOps.hpp index e494c1c8..db47b0f8 100644 --- a/sfall/ScriptOps/GraphicsOps.hpp +++ b/sfall/ScriptOps/GraphicsOps.hpp @@ -397,7 +397,7 @@ static void __declspec(naked) funcGetShaderVersion() { call GetShaderVersion; mov edx, eax; mov eax, ebx; - _RET_VAL_INT2; + _RET_VAL_INT; mov ecx, esi; retn; } diff --git a/sfall/ScriptOps/MemoryOps.hpp b/sfall/ScriptOps/MemoryOps.hpp index c107ef8b..7a097618 100644 --- a/sfall/ScriptOps/MemoryOps.hpp +++ b/sfall/ScriptOps/MemoryOps.hpp @@ -38,7 +38,7 @@ result: // retn; error: xor edx, edx; - jmp result; + jmp result; } } @@ -54,7 +54,7 @@ result: // retn; error: xor edx, edx; - jmp result; + jmp result; } } @@ -70,7 +70,7 @@ result: // retn; error: xor edx, edx; - jmp result; + jmp result; } } @@ -251,7 +251,7 @@ static void __fastcall CallOffsetInternal(TProgram* script, DWORD func) { mov eax, script; mov edx, args[0]; mov ebx, eax; - _RET_VAL_INT2; + _RET_VAL_INT; } } } diff --git a/sfall/ScriptOps/MiscOps.hpp b/sfall/ScriptOps/MiscOps.hpp index c77e6ba9..bad27da2 100644 --- a/sfall/ScriptOps/MiscOps.hpp +++ b/sfall/ScriptOps/MiscOps.hpp @@ -132,7 +132,7 @@ static void __declspec(naked) GameLoaded() { call ScriptHasLoaded; movzx edx, al; mov eax, ebx; - _RET_VAL_INT2; + _RET_VAL_INT; mov ecx, esi; retn; } @@ -170,7 +170,7 @@ skip: mov edx, ds:[_pc_kill_counts][eax * 4]; end: mov eax, ebx; // script - _RET_VAL_INT2; + _RET_VAL_INT; retn; fail: xor edx, edx; // return 0 @@ -588,7 +588,7 @@ static void __declspec(naked) funcGetTickCount() { call GetTickCount2; mov edx, eax; mov eax, ebx; - _RET_VAL_INT2; + _RET_VAL_INT; mov ecx, esi; retn; } @@ -943,7 +943,7 @@ static void __declspec(naked) get_tile_fid() { mov ebx, esi; // script end: mov eax, ebx; - _RET_VAL_INT2; + _RET_VAL_INT; pop ecx; retn; fail: @@ -1095,27 +1095,25 @@ static void __declspec(naked) op_sneak_success() { __asm { call is_pc_sneak_working_ } - _RET_VAL_INT(ebp) + _RET_VAL_INT32(ebp) _OP_END } -static void __declspec(naked) op_tile_light() { - _OP_BEGIN(ebp) - _GET_ARG_R32(ebp, ebx, edi) // arg2 - tile - _GET_ARG_R32(ebp, ecx, esi) // arg1 - elevation - _CHECK_ARG_INT(bx, fail) - _CHECK_ARG_INT(cx, fail) - __asm { - mov eax, esi - mov edx, edi - call light_get_tile_ - jmp end -fail: - mov eax, -1 -end: +static void _stdcall op_tile_light2() { + const ScriptValue &elevArg = opHandler.arg(0), + &tileArg = opHandler.arg(1); + + if (elevArg.isInt() && tileArg.isInt()) { + int lightLevel = LightGetTile(elevArg.rawValue(), tileArg.rawValue()); + opHandler.setReturn(lightLevel); + } else { + OpcodeInvalidArgs("tile_light"); + opHandler.setReturn(-1); } - _RET_VAL_INT(ebp) - _OP_END +} + +static void __declspec(naked) op_tile_light() { + _WRAP_OPCODE(op_tile_light2, 2, 1) } static void sf_exec_map_update_scripts() { diff --git a/sfall/ScriptOps/ObjectsOps.hpp b/sfall/ScriptOps/ObjectsOps.hpp index ea7ec616..8c017563 100644 --- a/sfall/ScriptOps/ObjectsOps.hpp +++ b/sfall/ScriptOps/ObjectsOps.hpp @@ -456,7 +456,7 @@ fail: xor eax, eax; end: } - _RET_VAL_INT(ebp) + _RET_VAL_INT32(ebp) _OP_END } diff --git a/sfall/ScriptOps/ScriptArrays.hpp b/sfall/ScriptOps/ScriptArrays.hpp index 3ba19287..e426e22f 100644 --- a/sfall/ScriptOps/ScriptArrays.hpp +++ b/sfall/ScriptOps/ScriptArrays.hpp @@ -432,7 +432,7 @@ static void __declspec(naked) op_load_array() { push ecx; // arg 1: key call LoadArray; } - _RET_VAL_INT(ebp) + _RET_VAL_INT32(ebp) _OP_END } @@ -457,7 +457,7 @@ static void __declspec(naked) op_get_array_key() { wrongarg: xor eax, eax; // return 0 on wrong arguments } - _RET_VAL_INT(ebp) + _RET_VAL_INT32(ebp) end: _OP_END } @@ -482,7 +482,7 @@ static void __declspec(naked) op_stack_array() { push edi // arg 1: key call StackArray } - _RET_VAL_INT(ebp) + _RET_VAL_INT32(ebp) _OP_END } diff --git a/sfall/ScriptOps/WorldmapOps.hpp b/sfall/ScriptOps/WorldmapOps.hpp index 41d52e62..90380305 100644 --- a/sfall/ScriptOps/WorldmapOps.hpp +++ b/sfall/ScriptOps/WorldmapOps.hpp @@ -122,7 +122,7 @@ static void __declspec(naked) funcInWorldMap() { call InWorldMap; mov edx, eax; mov eax, ebx; - _RET_VAL_INT2; + _RET_VAL_INT; mov ecx, esi; retn; } @@ -134,7 +134,7 @@ static void __declspec(naked) GetGameMode() { call GetLoopFlags; mov edx, eax; mov eax, ebx; - _RET_VAL_INT2; + _RET_VAL_INT; mov ecx, esi; retn; } diff --git a/sfall/main.cpp b/sfall/main.cpp index 280967cc..a0a9b01f 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -331,6 +331,16 @@ playWalkMovie: } } +static void __declspec(naked) op_display_msg_hook() { + __asm { + cmp dword ptr ds:_debug_func, 0; + jne debug; + retn; +debug: + jmp config_get_value_; + } +} + static void DllMain2() { long tmp; dlogr("In DllMain2", DL_MAIN); @@ -484,6 +494,27 @@ static void DllMain2() { dlogr("Running HeroAppearanceModInit().", DL_INIT); HeroAppearanceModInit(); + /////////////////// Engine Optimization Patches //////////////////// + + // Speed up display_msg script function + HookCall(0x455404, op_display_msg_hook); + + // Remove duplicate code from intface_redraw_ engine function + BlockCall(0x45EBBF); + + // Improve performance of the data conversion of script interpreter + // mov eax, [edx+eax]; bswap eax; ret; + SafeWrite32(0x4672A4, 0x0F02048B); + SafeWrite16(0x4672A8, 0xC3C8); + // mov eax, [edx+eax]; bswap eax; + SafeWrite32(0x4673E5, 0x0F02048B); + SafeWrite8(0x4673E9, 0xC8); + // mov ax, [eax]; rol ax, 8; ret; + SafeWrite32(0x467292, 0x66008B66); + SafeWrite32(0x467296, 0xC308C0C1); + + //////////////////////////////////////////////////////////////////// + if (GetConfigString("Misc", "StartingMap", "", mapName, 64)) { dlog("Applying starting map patch.", DL_INIT); SafeWrite32(0x480AAA, (DWORD)&mapName);