diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index fd2e80cf..734829e0 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -584,6 +584,9 @@ StartGDialogFix=0 ;attacker_results - unused, must be 0 or not equal to the target_results argument when specifying result flags for the target AttackComplexFix=0 +;Set to 1 to fix the issue with the division operator treating negative integers as unsigned +DivisionOperatorFix=1 + ;Set to 1 to enable the balanced bullet distribution formula for burst attacks ComputeSprayMod=0 diff --git a/artifacts/mods/main.h b/artifacts/mods/main.h index 13140aaa..16223ad9 100644 --- a/artifacts/mods/main.h +++ b/artifacts/mods/main.h @@ -1,3 +1,5 @@ +#ifndef MAIN_H +#define MAIN_H #include "..\scripting\headers\sfall.h" #include "..\scripting\headers\define_lite.h" @@ -71,3 +73,5 @@ end procedure InitConfigs begin translationIni := GetIniConfigStr("Main", "TranslationsINI", "Translations.ini", "ddraw.ini"); end + +#endif diff --git a/artifacts/scripting/compiler/sslc_readme.txt b/artifacts/scripting/compiler/sslc_readme.txt index 829a0041..745ef0e2 100644 --- a/artifacts/scripting/compiler/sslc_readme.txt +++ b/artifacts/scripting/compiler/sslc_readme.txt @@ -344,6 +344,7 @@ There are several changes in this version of sslc which may result in problems f - fixed compiler giving "assignment operator expected" error when a variable-like macro is not being defined properly - added new logical operators "AndAlso", "OrElse" for short-circuit evaluation of logical expressions - added an alternative (C/Java-style) assignment operator "=" +- added support for new "div" operator (unsigned integer division) > sfall 4.2.2 - added support for new opcode "reg_anim_callback" diff --git a/artifacts/scripting/headers/define_extra.h b/artifacts/scripting/headers/define_extra.h index eb8c4886..96438ede 100644 --- a/artifacts/scripting/headers/define_extra.h +++ b/artifacts/scripting/headers/define_extra.h @@ -112,7 +112,7 @@ #define MSGBOX_SMALL (0x2) #define MSGBOX_ALIGN_LEFT (0x4) // text aligned to left #define MSGBOX_ALIGN_TOP (0x8) // text aligned to top -#define MSGBOX_YESNO (0x10) // uses YES/NO buttons instead of DONE +#define MSGBOX_YESNO (0x10) // use YES/NO buttons instead of DONE #define MSGBOX_CLEAN (0x20) // no buttons //remove inven obj defines diff --git a/artifacts/scripting/headers/lib.math.h b/artifacts/scripting/headers/lib.math.h index 1ef8a7d4..f649c4fd 100644 --- a/artifacts/scripting/headers/lib.math.h +++ b/artifacts/scripting/headers/lib.math.h @@ -10,10 +10,10 @@ #define below(a, b) (unsigned_comp(a, b) < 0) #define below_equal(a, b) (unsigned_comp(a, b) <= 0) -procedure unsigned_comp(variable a, variable b) begin +// for sfall 4.2.3/3.8.23 +pure procedure unsigned_comp(variable a, variable b) begin if ((a bwxor b) == 0) then return 0; // a == b - if (b == 0) then return 1; - return 1 if (a / b) else -1; + return 1 if ((b == 0) orElse a div b) else -1; end #define MAX(x, y) ((x > y) * x + (x <= y) * y) diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 5d521e3d..f18965c5 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -1,3 +1,6 @@ +#ifndef SFALL_H +#define SFALL_H + //Recognised modes for set_shader_mode and get_game_mode #define WORLDMAP (0x1) #define DIALOG (0x4) @@ -354,3 +357,5 @@ #define set_fake_perk_npc(npc, perk, level, image, desc) sfall_func5("set_fake_perk_npc", npc, perk, level, image, desc) #define set_fake_trait_npc(npc, trait, active, image, desc) sfall_func5("set_fake_trait_npc", npc, trait, active, image, desc) #define set_selectable_perk_npc(npc, perk, active, image, desc) sfall_func5("set_selectable_perk_npc", npc, perk, active, image, desc) + +#endif diff --git a/artifacts/scripting/sfall opcode list.txt b/artifacts/scripting/sfall opcode list.txt index 7aedf936..6b34f703 100644 --- a/artifacts/scripting/sfall opcode list.txt +++ b/artifacts/scripting/sfall opcode list.txt @@ -360,6 +360,8 @@ 0x827d - void register_hook_proc_spec(int hook, procedure proc) 0x827e - void reg_anim_callback(procedure proc) +0x827f - div operator (unsigned integer division) + * These functions require AllowUnsafeScripting to be enabled in ddraw.ini diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index e5139cfe..beb27b66 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -2505,7 +2505,7 @@ void BugFixes::init() // Missing game initialization LoadGameHook::OnBeforeGameInit() += Initialization; - // Fix vanilla negate operator on float values + // Fix vanilla negate operator for float values MakeCall(0x46AB68, NegateFixHack); // Fix incorrect int-to-float conversion // op_mult: @@ -2514,6 +2514,12 @@ void BugFixes::init() // op_div: SafeWrite16(0x46A566, 0x04DB); SafeWrite16(0x46A4E7, 0x04DB); + // Fix for vanilla division operator treating negative integers as unsigned + if (GetConfigInt("Misc", "DivisionOperatorFix", 1)) { + dlog("Applying division operator fix.", DL_INIT); + SafeWrite32(0x46A51D, 0xFBF79990); // xor edx, edx; div ebx > cdq; idiv ebx + dlogr(" Done", DL_INIT); + } //if (GetConfigInt("Misc", "SpecialUnarmedAttacksFix", 1)) { dlog("Applying Special Unarmed Attacks fix.", DL_INIT); diff --git a/sfall/Modules/Scripting/Handlers/Core.cpp b/sfall/Modules/Scripting/Handlers/Core.cpp index a1c595fb..249c2d26 100644 --- a/sfall/Modules/Scripting/Handlers/Core.cpp +++ b/sfall/Modules/Scripting/Handlers/Core.cpp @@ -17,9 +17,7 @@ */ #include "..\..\..\FalloutEngine\Fallout2.h" -#include "..\..\..\SafeWrite.h" #include "..\..\..\Version.h" -#include "..\..\KillCounter.h" #include "..\..\HookScripts.h" #include "..\..\ScriptExtender.h" #include "..\Arrays.h" @@ -32,6 +30,10 @@ namespace sfall namespace script { +void sf_typeof(OpcodeContext& ctx) { + ctx.setReturn(static_cast(ctx.arg(0).type())); +} + void __declspec(naked) op_set_global_script_repeat() { __asm { mov esi, ecx; diff --git a/sfall/Modules/Scripting/Handlers/Core.h b/sfall/Modules/Scripting/Handlers/Core.h index 4289138a..6e1615be 100644 --- a/sfall/Modules/Scripting/Handlers/Core.h +++ b/sfall/Modules/Scripting/Handlers/Core.h @@ -18,15 +18,15 @@ #pragma once -/* - Opcodes for core sfall features. - */ +/* Opcodes for core sfall features. */ namespace sfall { namespace script { +void sf_typeof(OpcodeContext&); + void __declspec() op_set_global_script_repeat(); void __declspec() op_set_global_script_type(); diff --git a/sfall/Modules/Scripting/Handlers/Math.cpp b/sfall/Modules/Scripting/Handlers/Math.cpp new file mode 100644 index 00000000..e2308f45 --- /dev/null +++ b/sfall/Modules/Scripting/Handlers/Math.cpp @@ -0,0 +1,112 @@ +/* + * sfall + * Copyright (C) 2008-2020 The sfall team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "..\OpcodeContext.h" + +#include "Math.h" + +namespace sfall +{ +namespace script +{ + +void sf_div(OpcodeContext& ctx) { + if (ctx.arg(1).rawValue() == 0) { + ctx.printOpcodeError("%s - division by zero.", ctx.getOpcodeName()); + return; + } + if (ctx.arg(0).isFloat() || ctx.arg(1).isFloat()) { + ctx.setReturn(ctx.arg(0).asFloat() / ctx.arg(1).asFloat()); + } else { + ctx.setReturn(ctx.arg(0).rawValue() / ctx.arg(1).rawValue()); // unsigned division + } +} + +void sf_sqrt(OpcodeContext& ctx) { + ctx.setReturn(sqrt(ctx.arg(0).asFloat())); +} + +void sf_abs(OpcodeContext& ctx) { + if (ctx.arg(0).isInt()) { + ctx.setReturn(abs((int)ctx.arg(0).rawValue())); + } else { + ctx.setReturn(abs(ctx.arg(0).asFloat())); + } +} + +void sf_sin(OpcodeContext& ctx) { + ctx.setReturn(sin(ctx.arg(0).asFloat())); +} + +void sf_cos(OpcodeContext& ctx) { + ctx.setReturn(cos(ctx.arg(0).asFloat())); +} + +void sf_tan(OpcodeContext& ctx) { + ctx.setReturn(tan(ctx.arg(0).asFloat())); +} + +void sf_arctan(OpcodeContext& ctx) { + ctx.setReturn(atan2(ctx.arg(0).asFloat(), ctx.arg(1).asFloat())); +} + +void sf_power(OpcodeContext& ctx) { + const ScriptValue &base = ctx.arg(0), + &power = ctx.arg(1); + float result = 0.0; + if (power.isFloat()) + result = pow(base.asFloat(), power.floatValue()); + else + result = pow(base.asFloat(), (int)power.rawValue()); + + if (base.isInt() && power.isInt()) { + ctx.setReturn(static_cast(result)); + } else { + ctx.setReturn(result); + } +} + +void sf_log(OpcodeContext& ctx) { + ctx.setReturn(log(ctx.arg(0).asFloat())); +} + +void sf_exponent(OpcodeContext& ctx) { + ctx.setReturn(exp(ctx.arg(0).asFloat())); +} + +void sf_ceil(OpcodeContext& ctx) { + ctx.setReturn(static_cast(ceil(ctx.arg(0).asFloat()))); +} + +void sf_round(OpcodeContext& ctx) { + float arg = ctx.arg(0).asFloat(); + + int argI = static_cast(arg); + float mod = arg - static_cast(argI); + if (abs(mod) >= 0.5) argI += (mod > 0 ? 1 : -1); + ctx.setReturn(argI); +} + +void sf_floor2(OpcodeContext& ctx) { + ctx.setReturn(static_cast(floor(ctx.arg(0).asFloat()))); +} + +} +} diff --git a/sfall/Modules/Scripting/Handlers/Math.h b/sfall/Modules/Scripting/Handlers/Math.h new file mode 100644 index 00000000..7beef79b --- /dev/null +++ b/sfall/Modules/Scripting/Handlers/Math.h @@ -0,0 +1,55 @@ +/* + * sfall + * Copyright (C) 2008-2020 The sfall team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +namespace sfall +{ +namespace script +{ + +class OpcodeContext; + +void sf_div(OpcodeContext&); + +void sf_sqrt(OpcodeContext&); + +void sf_abs(OpcodeContext&); + +void sf_sin(OpcodeContext&); + +void sf_cos(OpcodeContext&); + +void sf_tan(OpcodeContext&); + +void sf_arctan(OpcodeContext&); + +void sf_power(OpcodeContext&); + +void sf_log(OpcodeContext&); + +void sf_exponent(OpcodeContext&); + +void sf_ceil(OpcodeContext&); + +void sf_round(OpcodeContext&); + +void sf_floor2(OpcodeContext&); + +} +} diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp index 28c23ffa..e240048f 100644 --- a/sfall/Modules/Scripting/Handlers/Metarule.cpp +++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp @@ -23,6 +23,7 @@ #include "Anims.h" #include "Core.h" #include "Interface.h" +#include "Math.h" #include "Misc.h" #include "Objects.h" #include "Perks.h" diff --git a/sfall/Modules/Scripting/Handlers/Utils.cpp b/sfall/Modules/Scripting/Handlers/Utils.cpp index 856e1070..6aaf2cf4 100644 --- a/sfall/Modules/Scripting/Handlers/Utils.cpp +++ b/sfall/Modules/Scripting/Handlers/Utils.cpp @@ -16,16 +16,12 @@ * along with this program. If not, see . */ -#include - #include "..\..\..\FalloutEngine\Fallout2.h" #include "..\..\..\FalloutEngine\EngineUtils.h" #include "..\..\ScriptExtender.h" -#include "..\..\FileSystem.h" #include "..\..\Message.h" #include "..\Arrays.h" #include "..\OpcodeContext.h" -#include "..\ScriptValue.h" #include "Utils.h" @@ -99,34 +95,6 @@ static bool FalloutStringCompare(const char* str1, const char* str2, long codePa } } -void sf_sqrt(OpcodeContext& ctx) { - ctx.setReturn(sqrt(ctx.arg(0).asFloat())); -} - -void sf_abs(OpcodeContext& ctx) { - if (ctx.arg(0).isInt()) { - ctx.setReturn(abs((int)ctx.arg(0).rawValue())); - } else { - ctx.setReturn(abs(ctx.arg(0).asFloat())); - } -} - -void sf_sin(OpcodeContext& ctx) { - ctx.setReturn(sin(ctx.arg(0).asFloat())); -} - -void sf_cos(OpcodeContext& ctx) { - ctx.setReturn(cos(ctx.arg(0).asFloat())); -} - -void sf_tan(OpcodeContext& ctx) { - ctx.setReturn(tan(ctx.arg(0).asFloat())); -} - -void sf_arctan(OpcodeContext& ctx) { - ctx.setReturn(atan2(ctx.arg(0).asFloat(), ctx.arg(1).asFloat())); -} - void sf_strlen(OpcodeContext& ctx) { ctx.setReturn( static_cast(strlen(ctx.arg(0).strValue())) @@ -152,10 +120,6 @@ void sf_ord(OpcodeContext& ctx) { ctx.setReturn(static_cast(firstChar)); } -void sf_typeof(OpcodeContext& ctx) { - ctx.setReturn(static_cast(ctx.arg(0).type())); -} - static int _stdcall StringSplit(const char* str, const char* split) { int id; size_t count, splitLen = strlen(split); @@ -380,44 +344,6 @@ void sf_string_format(OpcodeContext& ctx) { } } -void sf_power(OpcodeContext& ctx) { - const ScriptValue &base = ctx.arg(0), - &power = ctx.arg(1); - float result = 0.0; - if (power.isFloat()) - result = pow(base.asFloat(), power.floatValue()); - else - result = pow(base.asFloat(), (int)power.rawValue()); - - if (base.isInt() && power.isInt()) { - ctx.setReturn(static_cast(result)); - } else { - ctx.setReturn(result); - } -} - -void sf_log(OpcodeContext& ctx) { - ctx.setReturn(log(ctx.arg(0).asFloat())); -} - -void sf_exponent(OpcodeContext& ctx) { - ctx.setReturn(exp(ctx.arg(0).asFloat())); -} - -void sf_ceil(OpcodeContext& ctx) { - ctx.setReturn(static_cast(ceil(ctx.arg(0).asFloat()))); -} - -void sf_round(OpcodeContext& ctx) { - float arg = ctx.arg(0).asFloat(); - int argI = static_cast(arg); - float mod = arg - static_cast(argI); - if (abs(mod) >= 0.5) { - argI += (mod > 0 ? 1 : -1); - } - ctx.setReturn(argI); -} - void sf_message_str_game(OpcodeContext& ctx) { const char* msg = nullptr; @@ -454,10 +380,6 @@ void sf_add_extra_msg_file(OpcodeContext& ctx) { ctx.setReturn(result); } -void sf_floor2(OpcodeContext& ctx) { - ctx.setReturn(static_cast(floor(ctx.arg(0).asFloat()))); -} - void sf_get_string_pointer(OpcodeContext& ctx) { ctx.setReturn(reinterpret_cast(ctx.arg(0).strValue()), DataType::INT); } diff --git a/sfall/Modules/Scripting/Handlers/Utils.h b/sfall/Modules/Scripting/Handlers/Utils.h index d9b238da..76b2853e 100644 --- a/sfall/Modules/Scripting/Handlers/Utils.h +++ b/sfall/Modules/Scripting/Handlers/Utils.h @@ -25,18 +25,6 @@ namespace script class OpcodeContext; -void sf_sqrt(OpcodeContext&); - -void sf_abs(OpcodeContext&); - -void sf_sin(OpcodeContext&); - -void sf_cos(OpcodeContext&); - -void sf_tan(OpcodeContext&); - -void sf_arctan(OpcodeContext&); - void sf_string_split(OpcodeContext&); void sf_atoi(OpcodeContext&); @@ -55,24 +43,10 @@ void sf_string_format(OpcodeContext&); void sf_ord(OpcodeContext&); -void sf_typeof(OpcodeContext&); - -void sf_power(OpcodeContext&); - -void sf_log(OpcodeContext&); - -void sf_exponent(OpcodeContext&); - -void sf_ceil(OpcodeContext&); - -void sf_round(OpcodeContext&); - void sf_message_str_game(OpcodeContext&); void sf_add_extra_msg_file(OpcodeContext&); -void sf_floor2(OpcodeContext&); - void sf_get_string_pointer(OpcodeContext&); void sf_get_text_width(OpcodeContext&); diff --git a/sfall/Modules/Scripting/Opcodes.cpp b/sfall/Modules/Scripting/Opcodes.cpp index 69966fcc..ac916221 100644 --- a/sfall/Modules/Scripting/Opcodes.cpp +++ b/sfall/Modules/Scripting/Opcodes.cpp @@ -26,6 +26,7 @@ #include "Handlers\FileSystem.h" #include "Handlers\Graphics.h" #include "Handlers\Interface.h" +#include "Handlers\Math.h" #include "Handlers\Memory.h" #include "Handlers\Misc.h" #include "Handlers\Objects.h" @@ -189,7 +190,7 @@ static SfallOpcodeInfo opcodeInfoArray[] = { {0x260, "reg_anim_turn_towards", sf_reg_anim_turn_towards, 3, false, 0, {ARG_OBJECT, ARG_INT, ARG_INT}}, {0x261, "metarule2_explosions", sf_explosions_metarule, 3, true, -1, {ARG_INT, ARG_INT, ARG_INT}}, {0x262, "register_hook_proc", sf_register_hook, 2, false, 0, {ARG_INT, ARG_INT}}, - {0x263, "power", sf_power, 2, true, 0, {ARG_NUMBER, ARG_NUMBER}}, + {0x263, "power", sf_power, 2, true, 0, {ARG_NUMBER, ARG_NUMBER}}, // '^' operator {0x264, "log", sf_log, 1, true, 0, {ARG_NUMBER}}, {0x265, "exponent", sf_exponent, 1, true, 0, {ARG_NUMBER}}, {0x266, "ceil", sf_ceil, 1, true, 0, {ARG_NUMBER}}, @@ -219,6 +220,7 @@ static SfallOpcodeInfo opcodeInfoArray[] = { {0x27d, "register_hook_proc_spec", sf_register_hook, 2, false, 0, {ARG_INT, ARG_INT}}, {0x27e, "reg_anim_callback", sf_reg_anim_callback, 1, false, 0, {ARG_INT}}, + {0x27f, "div", sf_div, 2, true, 0, {ARG_NUMBER, ARG_NUMBER}}, // div operator }; // An array for opcode info, indexed by opcode. diff --git a/sfall/ddraw.vcxproj b/sfall/ddraw.vcxproj index 999e7649..a1dc496f 100644 --- a/sfall/ddraw.vcxproj +++ b/sfall/ddraw.vcxproj @@ -312,6 +312,7 @@ + @@ -405,6 +406,7 @@ + diff --git a/sfall/ddraw.vcxproj.filters b/sfall/ddraw.vcxproj.filters index 59c628d9..581df50e 100644 --- a/sfall/ddraw.vcxproj.filters +++ b/sfall/ddraw.vcxproj.filters @@ -298,6 +298,9 @@ Modules\Features + + Modules\Scripting\Handlers + @@ -496,6 +499,9 @@ + + Modules\SubModules + Modules\SimplePatches @@ -544,8 +550,8 @@ Modules\Features - - Modules\SubModules + + Modules\Scripting\Handlers