From 2bc94e8036d45297aac2714b511a9bbcc0a5027e Mon Sep 17 00:00:00 2001 From: NovaRain Date: Tue, 22 Dec 2020 15:40:42 +0800 Subject: [PATCH] Added sfall_func7 and sfall_func8 new opcodes Added 3 new attrType values to "get_window_attribute" function. Minor code edits. --- artifacts/scripting/compiler/sslc_readme.txt | 4 ++++ artifacts/scripting/headers/sfall.h | 3 +++ artifacts/scripting/sfall function notes.txt | 5 ++++- artifacts/scripting/sfall opcode list.txt | 3 +++ sfall/FalloutEngine/EngineUtils.cpp | 8 ++----- sfall/FalloutEngine/Functions.cpp | 16 +++++++------- .../Modules/Scripting/Handlers/Interface.cpp | 21 +++++++++++++++---- sfall/Modules/Scripting/Opcodes.cpp | 5 ++++- sfall/Modules/SubModules/GameRender.cpp | 11 +++++++--- 9 files changed, 53 insertions(+), 23 deletions(-) diff --git a/artifacts/scripting/compiler/sslc_readme.txt b/artifacts/scripting/compiler/sslc_readme.txt index f5de9bfc..db9cf304 100644 --- a/artifacts/scripting/compiler/sslc_readme.txt +++ b/artifacts/scripting/compiler/sslc_readme.txt @@ -340,6 +340,10 @@ There are several changes in this version of sslc which may result in problems f === Changelog === ================= +> sfall 4.2.9 +- added support for additional universal opcodes sfall_func7 and sfall_func8 +- fixed a compilation error when the script has a UTF-8 BOM + > sfall 4.2.7 - added ability to declare local variables anywhere in the procedure body diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 61cd9060..c7ae0cf8 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -312,8 +312,11 @@ #define get_flags(obj) sfall_func1("get_flags", obj) #define get_ini_section(file, sect) sfall_func2("get_ini_section", file, sect) #define get_ini_sections(file) sfall_func1("get_ini_sections", file) +#define get_interface_rect(winType) sfall_func2("get_window_attribute", winType, -1) #define get_interface_x(winType) sfall_func2("get_window_attribute", winType, 1) #define get_interface_y(winType) sfall_func2("get_window_attribute", winType, 2) +#define get_interface_width(winType) sfall_func2("get_window_attribute", winType, 3) +#define get_interface_height(winType) sfall_func2("get_window_attribute", winType, 4) #define get_inven_ap_cost sfall_func0("get_inven_ap_cost") #define get_map_enter_position sfall_func0("get_map_enter_position") #define get_metarule_table sfall_func0("get_metarule_table") diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index b3ab45af..b456951b 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -381,7 +381,7 @@ Some utility/math functions are available: > any sfall_funcX(string funcName, ...) - these opcodes allows to use additional scripting functions, that do not require new opcode - first argument is always function name (string) -- there are 7 versions of this opcode for different number of additional arguments (for convenience) +- there are 9 versions of this opcode for different number of additional arguments (for convenience) - opcodes have return value, but it is not necessary to use it @@ -720,6 +720,9 @@ optional argument: - winType: the type number of the interface window (see WINTYPE_* constants in sfall.h) - attrType: 0 - checks and returns a value of 1 if the specified interface window is created by the game (same as without the argument) 1 - X position, 2 - Y position (relative to the top-left corner of the game screen) + 3 - interface width size, 4 - interface height size + -1 - returns an associative array of keys (left, top, right, bottom) and values that define the position of the window rectangle + (use standard syntax to access array values, e.g. winRect.top, winRect.bottom) - returns -1 if the specified attribute cannot be obtained > void sfall_func2("set_town_title", int areaID, string title) diff --git a/artifacts/scripting/sfall opcode list.txt b/artifacts/scripting/sfall opcode list.txt index f1013645..60e3cf00 100644 --- a/artifacts/scripting/sfall opcode list.txt +++ b/artifacts/scripting/sfall opcode list.txt @@ -362,6 +362,9 @@ 0x827f - div operator (unsigned integer division) +0x8280 - any sfall_func7(string funcName, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +0x8281 - any sfall_func8(string funcName, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + * These functions require AllowUnsafeScripting to be enabled in ddraw.ini diff --git a/sfall/FalloutEngine/EngineUtils.cpp b/sfall/FalloutEngine/EngineUtils.cpp index 7fec3827..2db7fb05 100644 --- a/sfall/FalloutEngine/EngineUtils.cpp +++ b/sfall/FalloutEngine/EngineUtils.cpp @@ -381,13 +381,9 @@ void WinFillRect(long winID, long x, long y, long width, long height, BYTE index // Fills the specified interface window with index color 0 (black color) void ClearWindow(long winID, bool refresh) { fo::Window* win = fo::func::GNW_find(winID); - BYTE* surf = win->surface; - for (long i = 0; i < win->height; i++) { - std::memset(surf, 0, win->width); - surf += win->width; - } + std::memset(win->surface, 0, win->width * win->height); if (refresh) { - fo::func::GNW_win_refresh(win, &win->rect, 0); + fo::func::GNW_win_refresh(win, &win->rect, nullptr); } } diff --git a/sfall/FalloutEngine/Functions.cpp b/sfall/FalloutEngine/Functions.cpp index 13ec9981..408b6a65 100644 --- a/sfall/FalloutEngine/Functions.cpp +++ b/sfall/FalloutEngine/Functions.cpp @@ -287,8 +287,8 @@ void __cdecl buf_to_buf(BYTE* src, long width, long height, long src_width, BYTE size_t blockCount = width / 64; // 64 bytes size_t remainder = width % 64; - size_t remainderD = remainder / 4; - size_t remainderB = remainder % 4; + size_t sizeD = remainder >> 2; + size_t sizeB = remainder & 3; size_t s_pitch = src_width - width; size_t d_pitch = dst_width - width; @@ -324,9 +324,9 @@ void __cdecl buf_to_buf(BYTE* src, long width, long height, long src_width, BYTE dec ecx; // blockCount jnz copyBlock; // copies the remaining bytes - mov ecx, remainderD; + mov ecx, sizeD; rep movsd; - mov ecx, remainderB; + mov ecx, sizeB; rep movsb; add esi, ebx; // s_pitch add edi, edx; // d_pitch @@ -335,9 +335,9 @@ void __cdecl buf_to_buf(BYTE* src, long width, long height, long src_width, BYTE emms; jmp end; copySmall: // copies the small size data - mov ecx, remainderD; + mov ecx, sizeD; rep movsd; - mov ecx, remainderB; + mov ecx, sizeB; rep movsb; add esi, ebx; // s_pitch add edi, edx; // d_pitch @@ -351,8 +351,8 @@ end: void __cdecl trans_buf_to_buf(BYTE* src, long width, long height, long src_width, BYTE* dst, long dst_width) { if (height <= 0 || width <= 0) return; - size_t blockCount = width / 8; - size_t lastBytes = width % 8; + size_t blockCount = width >> 3; + size_t lastBytes = width & 7; size_t s_pitch = src_width - width; size_t d_pitch = dst_width - width; diff --git a/sfall/Modules/Scripting/Handlers/Interface.cpp b/sfall/Modules/Scripting/Handlers/Interface.cpp index ece0bcb8..4253f16a 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.cpp +++ b/sfall/Modules/Scripting/Handlers/Interface.cpp @@ -646,7 +646,7 @@ void mf_interface_art_draw(OpcodeContext& ctx) { if (win && (int)win != -1) { result = InterfaceDrawImage(ctx, win); } else { - ctx.printOpcodeError("%s() - the game interface window is not created or invalid value for the interface.", ctx.getMetaruleName()); + ctx.printOpcodeError("%s() - the game interface window is not created or invalid window type number.", ctx.getMetaruleName()); } ctx.setReturn(result); } @@ -729,15 +729,28 @@ void mf_get_window_attribute(OpcodeContext& ctx) { } long result = 0; switch (ctx.arg(1).rawValue()) { + case -1: // rectangle map.left map.top map.right map.bottom + result = CreateTempArray(-1, 0); // associative + setArray(result, ScriptValue("left"), ScriptValue(win->rect.x), false); + setArray(result, ScriptValue("top"), ScriptValue(win->rect.y), false); + setArray(result, ScriptValue("right"), ScriptValue(win->rect.offx), false); + setArray(result, ScriptValue("bottom"), ScriptValue(win->rect.offy), false); + break; case 0: // check if window exists result = 1; break; - case 1: // x + case 1: result = win->rect.x; break; - case 2: // y + case 2: result = win->rect.y; break; + case 3: + result = win->width; + break; + case 4: + result = win->height; + break; } ctx.setReturn(result); } @@ -745,7 +758,7 @@ void mf_get_window_attribute(OpcodeContext& ctx) { void mf_interface_print(OpcodeContext& ctx) { // same as vanilla PrintRect fo::Window* win = Interface::GetWindow(ctx.arg(1).rawValue()); if (win == nullptr || (int)win == -1) { - ctx.printOpcodeError("%s() - the game interface window is not created or invalid value for the interface.", ctx.getMetaruleName()); + ctx.printOpcodeError("%s() - the game interface window is not created or invalid window type number.", ctx.getMetaruleName()); ctx.setReturn(-1); return; } diff --git a/sfall/Modules/Scripting/Opcodes.cpp b/sfall/Modules/Scripting/Opcodes.cpp index 230e2855..80c89d3d 100644 --- a/sfall/Modules/Scripting/Opcodes.cpp +++ b/sfall/Modules/Scripting/Opcodes.cpp @@ -228,11 +228,14 @@ static SfallOpcodeInfo opcodeInfoArray[] = { {0x279, "sfall_func3", HandleMetarule, 4, true}, {0x27a, "sfall_func4", HandleMetarule, 5, true}, {0x27b, "sfall_func5", HandleMetarule, 6, true}, - {0x27c, "sfall_func6", HandleMetarule, 7, true}, // if you need more arguments - use arrays + {0x27c, "sfall_func6", HandleMetarule, 7, true}, {0x27d, "register_hook_proc_spec", op_register_hook, 2, false, 0, {ARG_INT, ARG_INT}}, {0x27e, "reg_anim_callback", op_reg_anim_callback, 1, false, 0, {ARG_INT}}, {0x27f, "div", op_div, 2, true, 0, {ARG_NUMBER, ARG_NUMBER}}, // div operator + + {0x280, "sfall_func7", HandleMetarule, 8, true}, + {0x281, "sfall_func8", HandleMetarule, 9, true}, // if you need more arguments - use arrays }; // An array for opcode info, indexed by opcode. diff --git a/sfall/Modules/SubModules/GameRender.cpp b/sfall/Modules/SubModules/GameRender.cpp index fca20a90..f33f8e42 100644 --- a/sfall/Modules/SubModules/GameRender.cpp +++ b/sfall/Modules/SubModules/GameRender.cpp @@ -39,7 +39,7 @@ static void __fastcall sf_GNW_win_refresh(fo::Window* win, RECT* updateRect, BYT mov edx, ds:[FO_VAR_screen_buffer]; call fo::funcoffs::refresh_all_; } - int w = updateRect->right - updateRect->left + 1; + int w = (updateRect->right - updateRect->left) + 1; if (fo::var::mouse_is_hidden || !fo::func::mouse_in(updateRect->left, updateRect->top, updateRect->right, updateRect->bottom)) { /*__asm { @@ -48,7 +48,9 @@ static void __fastcall sf_GNW_win_refresh(fo::Window* win, RECT* updateRect, BYT call fo::funcoffs::GNW_button_refresh_; }*/ int h = (updateRect->bottom - updateRect->top) + 1; + Graphics::UpdateDDSurface(GetBuffer(), w, h, w, updateRect); // update the entire rectangle area + } else { fo::func::mouse_show(); // for updating background cursor area RECT mouseRect; @@ -66,8 +68,10 @@ static void __fastcall sf_GNW_win_refresh(fo::Window* win, RECT* updateRect, BYT mov edx, rects; call fo::funcoffs::GNW_button_refresh_; }*/ + int wRect = (rects->wRect.right - rects->wRect.left) + 1; int hRect = (rects->wRect.bottom - rects->wRect.top) + 1; + Graphics::UpdateDDSurface(&GetBuffer()[rects->wRect.left - updateRect->left] + (rects->wRect.top - updateRect->top) * w, wRect, hRect, w, &rects->wRect); fo::RectList* next = rects->nextRect; @@ -102,7 +106,7 @@ static void __fastcall sf_GNW_win_refresh(fo::Window* win, RECT* updateRect, BYT } int widthFrom = win->width; - int toWidth = (toBuffer) ? updateRect->right - updateRect->left + 1 : Graphics::GetGameWidthRes(); + int toWidth = (toBuffer) ? (updateRect->right - updateRect->left) + 1 : Graphics::GetGameWidthRes(); fo::func::win_clip(win, &rects, toBuffer); @@ -113,7 +117,7 @@ static void __fastcall sf_GNW_win_refresh(fo::Window* win, RECT* updateRect, BYT int height = (crect.bottom - crect.top) + 1;; // for current rectangle BYTE* surface; - if (win->wID) { + if (win->wID > 0) { __asm { mov eax, win; mov edx, currRect; @@ -144,6 +148,7 @@ static void __fastcall sf_GNW_win_refresh(fo::Window* win, RECT* updateRect, BYT int width = (rects->rect.offx - rects->rect.x) + 1; int height = (rects->rect.offy - rects->rect.y) + 1; int widthFrom = toWidth; + Graphics::UpdateDDSurface(&GetBuffer()[rects->rect.x] + (rects->rect.y * widthFrom), width, height, widthFrom, &rects->wRect); } fo::RectList* next = rects->nextRect;