Modified some of the mechanics of "interface_overlay" function

Changed "intface_redraw" with one argument to redraw the specified
interface window.
This commit is contained in:
NovaRain
2020-12-25 14:51:31 +08:00
parent 26a2338038
commit 43a2fc93cc
13 changed files with 117 additions and 80 deletions
+3 -1
View File
@@ -308,7 +308,8 @@
#define interface_art_draw_ex(winID, artID, x, y, frame, param) sfall_func6("interface_art_draw", winID, artID, x, y, frame, param) #define interface_art_draw_ex(winID, artID, x, y, frame, param) sfall_func6("interface_art_draw", winID, artID, x, y, frame, param)
#define interface_print(text, winType, x, y, color) sfall_func5("interface_print", text, winType, x, y, color) #define interface_print(text, winType, x, y, color) sfall_func5("interface_print", text, winType, x, y, color)
#define interface_print_width(text, winType, x, y, color, w) sfall_func6("interface_print", text, winType, x, y, color, w) #define interface_print_width(text, winType, x, y, color, w) sfall_func6("interface_print", text, winType, x, y, color, w)
#define interface_redraw_all sfall_func1("intface_redraw", 1) #define interface_redraw_all sfall_func1("intface_redraw", -1)
#define interface_redraw_win(winType) sfall_func1("intface_redraw", winType)
#define intface_hide sfall_func0("intface_hide") #define intface_hide sfall_func0("intface_hide")
#define intface_is_hidden sfall_func0("intface_is_hidden") #define intface_is_hidden sfall_func0("intface_is_hidden")
#define intface_is_shown(winType) sfall_func1("get_window_attribute", winType) #define intface_is_shown(winType) sfall_func1("get_window_attribute", winType)
@@ -327,6 +328,7 @@
#define overlay_create(winType) sfall_func2("interface_overlay", winType, 1) #define overlay_create(winType) sfall_func2("interface_overlay", winType, 1)
#define overlay_clear(winType) sfall_func2("interface_overlay", winType, 2) #define overlay_clear(winType) sfall_func2("interface_overlay", winType, 2)
#define overlay_clear_rectangle(winType, x, y, w, h) sfall_func6("interface_overlay", winType, 2, x, y, w, h) #define overlay_clear_rectangle(winType, x, y, w, h) sfall_func6("interface_overlay", winType, 2, x, y, w, h)
#define overlay_destroy(winType) sfall_func2("interface_overlay", winType, 0)
#define real_dude_obj sfall_func0("real_dude_obj") #define real_dude_obj sfall_func0("real_dude_obj")
#define remove_all_timer_events sfall_func0("remove_timer_event") #define remove_all_timer_events sfall_func0("remove_timer_event")
#define remove_timer_event(fixedParam) sfall_func1("remove_timer_event", fixedParam) #define remove_timer_event(fixedParam) sfall_func1("remove_timer_event", fixedParam)
+10 -2
View File
@@ -402,9 +402,9 @@ Some utility/math functions are available:
- works just like vanilla critter_inven_obj, but correctly reports item in player's inactive hand slot - works just like vanilla critter_inven_obj, but correctly reports item in player's inactive hand slot
> void sfall_func0("intface_redraw") > void sfall_func0("intface_redraw")
> void sfall_func1("intface_redraw", bool eachWin) > void sfall_func1("intface_redraw", int winType)
- redraws main game interface, useful to reflect changes after directly changing current player weapons or stats - redraws main game interface, useful to reflect changes after directly changing current player weapons or stats
- eachWin: pass True to redraw all interface windows - winType: the type number of the interface window (see WINTYPE_* constants in sfall.h). Pass -1 to redraw all interface windows
> void sfall_func0("intface_hide") > void sfall_func0("intface_hide")
- hides main interface - hides main interface
@@ -728,6 +728,14 @@ optional arguments:
- fills the rectangle area of the currently selected script window with the specified color, or clears the window with transparent (index 0) color (call the function without arguments) - fills the rectangle area of the currently selected script window with the specified color, or clears the window with transparent (index 0) color (call the function without arguments)
- color: the color index in the game palette (from 0 to 255) - color: the color index in the game palette (from 0 to 255)
> int sfall_func2("interface_overlay", int winType, int mode)
> int sfall_func6("interface_overlay", int winType, 2, int x, int y, int width, int height)
- creates an additional drawing surface above the graphic layer of the specified interface window. All subsequent calls of interface_art_draw and interface_print functions will draw on it
- winType: the type number of the interface window (see WINTYPE_* constants in sfall.h)
- mode: 1 - creates a new overlay surface
2 - clears the overlay area or the specified rectangle defined by the x, y, width, height arguments
0 - destroys the created overlay surface (frees up the memory allocated to the surface)
------------------------ ------------------------
------ MORE INFO ------- ------ MORE INFO -------
------------------------ ------------------------
@@ -365,6 +365,4 @@
0x8280 - any sfall_func7(string funcName, arg1, arg2, arg3, arg4, arg5, arg6, arg7) 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) 0x8281 - any sfall_func8(string funcName, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
* These functions require AllowUnsafeScripting to be enabled in ddraw.ini * These functions require AllowUnsafeScripting to be enabled in ddraw.ini
+10 -10
View File
@@ -702,16 +702,16 @@ namespace Fields {
namespace WinFlags { namespace WinFlags {
enum WinButtonFlags : long enum WinButtonFlags : long
{ {
OwnerFlag = 0x1, OwnerFlag = 0x000001, // sfall Render flag, indicates that the window surface is used for rendering the game scene
DontMoveTop = 0x2, DontMoveTop = 0x000002, // does not move the window to top when the mouse is clicked in the window area or when it is showing
MoveOnTop = 0x4, MoveOnTop = 0x000004, // places the window on top when it is created
Hidden = 0x8, Hidden = 0x000008,
Exclusive = 0x10, Exclusive = 0x000010,
Transparent = 0x20, Transparent = 0x000020,
UnknownFlag40 = 0x40, UnknownFlag40 = 0x000040,
UnknownFlag80 = 0x80, UnknownFlag80 = 0x000080,
ScriptWindow = 0x100, ScriptWindow = 0x000100,
itsButton = 0x10000, itsButton = 0x010000,
}; };
} }
+4 -3
View File
@@ -1707,10 +1707,11 @@ void RedrawObject(TGameObj* obj) {
TileRefreshRect(&rect, obj->elevation); TileRefreshRect(&rect, obj->elevation);
} }
// Redraws all interface windows // Redraws all windows
void RefreshGNW(size_t from) { void RefreshGNW(bool skipOwner) {
*(DWORD*)_doing_refresh_all = 1; *(DWORD*)_doing_refresh_all = 1;
for (size_t i = from; i < *ptr_num_windows; i++) { for (size_t i = 0; i < *ptr_num_windows; i++) {
if (skipOwner && ptr_window[i]->flags & WinFlags::OwnerFlag) continue;
GNWWinRefresh(ptr_window[i], ptr_scr_size, 0); GNWWinRefresh(ptr_window[i], ptr_scr_size, 0);
} }
*(DWORD*)_doing_refresh_all = 0; *(DWORD*)_doing_refresh_all = 0;
+2 -2
View File
@@ -1376,7 +1376,7 @@ DWORD __stdcall GetMaxCharWidth();
// Redraw the given object on screen (does not always redraws the whole object) // Redraw the given object on screen (does not always redraws the whole object)
void RedrawObject(TGameObj* obj); void RedrawObject(TGameObj* obj);
// Redraws all interface windows // Redraws all windows
void RefreshGNW(size_t from = 0); void RefreshGNW(bool skipOwner = false);
UNLSTDfrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef); UNLSTDfrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef);
+7
View File
@@ -20,6 +20,13 @@
#include <Windows.h> #include <Windows.h>
struct sRectangle {
long x, y, width, height;
long right() { return x + (width - 1); }
long bottom() { return y + (height - 1); }
};
/******************************************************************************/ /******************************************************************************/
/* FALLOUT2.EXE structs should be placed here */ /* FALLOUT2.EXE structs should be placed here */
/******************************************************************************/ /******************************************************************************/
+40 -29
View File
@@ -1329,6 +1329,8 @@ static __forceinline void UpdateDDSurface(BYTE* surface, int width, int height,
} }
} }
static void __fastcall sf_GNW_win_refresh(WINinfo* win, RECT* updateRect, BYTE* toBuffer);
class OverlaySurface class OverlaySurface
{ {
private: private:
@@ -1338,14 +1340,14 @@ private:
BYTE* surface; BYTE* surface;
public: public:
//long winType = -1; long winType;
OverlaySurface() : size(0), surface(nullptr) {} OverlaySurface() : size(0), surface(nullptr), winType(-1) {}
BYTE* Surface() { return surface; } BYTE* Surface() { return surface; }
void CreateSurface(WINinfo* win, long winType) { void CreateSurface(WINinfo* win, long winType) {
//this->winType = winType; this->winType = winType;
this->surfWidth = win->width; this->surfWidth = win->width;
this->size = win->height * win->width; this->size = win->height * win->width;
@@ -1372,26 +1374,28 @@ public:
size_t sizeD = rect.width >> 2; size_t sizeD = rect.width >> 2;
size_t sizeB = rect.width & 3; size_t sizeB = rect.width & 3;
size_t stride = sizeD << 2; size_t strideD = sizeD << 2;
size_t stride = surfWidth - rect.width;
long height = rect.height; long height = rect.height;
while (height--) { while (height--) {
if (sizeD) { if (sizeD) {
__stosd((DWORD*)surf, 0, sizeD); __stosd((DWORD*)surf, 0, sizeD);
surf += stride; surf += strideD;
} }
if (sizeB) { if (sizeB) {
__stosb(surf, 0, sizeB); __stosb(surf, 0, sizeB);
surf += sizeB; surf += sizeB;
} }
surf += stride;
}; };
} }
} }
/*void DestroySurface() { void DestroySurface() {
delete[] surface; delete[] surface;
surface = nullptr; surface = nullptr;
}*/ }
~OverlaySurface() { ~OverlaySurface() {
delete[] surface; delete[] surface;
@@ -1401,32 +1405,45 @@ public:
static long indexPosition = 0; static long indexPosition = 0;
void GameRender_CreateOverlaySurface(WINinfo* win, long winType) { void GameRender_CreateOverlaySurface(WINinfo* win, long winType) {
overlaySurfaces[indexPosition].CreateSurface(win, winType); if (win->randY) return;
if (overlaySurfaces[indexPosition].winType == winType) {
overlaySurfaces[indexPosition].ClearSurface();
} else {
if (++indexPosition == 5) indexPosition = 0;
overlaySurfaces[indexPosition].CreateSurface(win, winType);
}
win->randY = reinterpret_cast<long*>(&overlaySurfaces[indexPosition]); win->randY = reinterpret_cast<long*>(&overlaySurfaces[indexPosition]);
if (++indexPosition == 5) indexPosition = 0; }
};
BYTE* GameRender_GetOverlaySurface(WINinfo* win) { BYTE* GameRender_GetOverlaySurface(WINinfo* win) {
return reinterpret_cast<OverlaySurface*>(win->randY)->Surface(); return reinterpret_cast<OverlaySurface*>(win->randY)->Surface();
}; }
void GameRender_ClearOverlay(WINinfo* win) { void GameRender_ClearOverlay(WINinfo* win) {
if (win->randY) reinterpret_cast<OverlaySurface*>(win->randY)->ClearSurface(); if (win->randY) reinterpret_cast<OverlaySurface*>(win->randY)->ClearSurface();
}; }
void GameRender_ClearOverlay(WINinfo* win, sRectangle &rect) { void GameRender_ClearOverlay(WINinfo* win, sRectangle &rect) {
if (win->randY) reinterpret_cast<OverlaySurface*>(win->randY)->ClearSurface(rect); if (win->randY) {
}; reinterpret_cast<OverlaySurface*>(win->randY)->ClearSurface(rect);
BoundRect updateRect = { rect.x, rect.y, rect.right(), rect.bottom() };
/*void GameRender_DestroyOverlaySurface(long winType) { updateRect.x += win->rect.x;
for (size_t i = 0; i < 5; i++) { updateRect.y += win->rect.y;
if (overlaySurfaces[i].winType == winType) { updateRect.offx += win->rect.x;
overlaySurfaces[i].DestroySurface(); updateRect.offy += win->rect.y;
overlaySurfaces[i].winType = -1; sf_GNW_win_refresh(win, reinterpret_cast<RECT*>(&updateRect), 0);
//break;
}
} }
};*/ }
void GameRender_DestroyOverlaySurface(WINinfo* win) {
if (win->randY) {
OverlaySurface* overlay = reinterpret_cast<OverlaySurface*>(win->randY);
win->randY = nullptr;
overlay->winType = -1;
overlay->DestroySurface();
sf_GNW_win_refresh(win, &win->wRect, 0);
}
}
static BYTE* GetBuffer() { static BYTE* GetBuffer() {
return (BYTE*)*(DWORD*)_screen_buffer; return (BYTE*)*(DWORD*)_screen_buffer;
@@ -1664,18 +1681,12 @@ void Graphics_Init() {
0x4D75E6 // win_clip_ (remove _buffering checking) 0x4D75E6 // win_clip_ (remove _buffering checking)
}; };
SafeWriteBatch<WORD>(0x9090, winBufferAddr); SafeWriteBatch<WORD>(0x9090, winBufferAddr);
SafeWrite8(0x42F869, WinFlags::MoveOnTop | WinFlags::OwnerFlag); // addWindow_ (remove Transparent flag)
// Custom implementation of the GNW_win_refresh function // Custom implementation of the GNW_win_refresh function
MakeJump(0x4D6FD9, GNW_win_refresh_hack, 1); MakeJump(0x4D6FD9, GNW_win_refresh_hack, 1);
// Replace _screendump_buf with _screen_buffer for creating screenshots // Replace _screendump_buf with _screen_buffer for creating screenshots
const DWORD scrdumpBufAddr[] = {0x4C8FD1, 0x4C900D}; const DWORD scrdumpBufAddr[] = {0x4C8FD1, 0x4C900D};
SafeWriteBatch<DWORD>(_screen_buffer, scrdumpBufAddr); SafeWriteBatch<DWORD>(_screen_buffer, scrdumpBufAddr);
// Disable unused code for the RandX and RandY window structure fields (these fields can now be used for other purposes)
SafeWrite32(0x4D630C, 0x9090C031); // xor eax, eax
SafeWrite8(0x4D6310, 0x90);
BlockCall(0x4D6319);
} }
void Graphics_Exit() { void Graphics_Exit() {
+1 -1
View File
@@ -52,7 +52,7 @@ void Gfx_ReleaseMovieTexture();
void Gfx_RefreshGraphics(); void Gfx_RefreshGraphics();
void GameRender_CreateOverlaySurface(WINinfo* win, long winType); void GameRender_CreateOverlaySurface(WINinfo* win, long winType);
//void GameRender_DestroyOverlaySurface(long winType); void GameRender_DestroyOverlaySurface(WINinfo* win);
void GameRender_ClearOverlay(WINinfo* win); void GameRender_ClearOverlay(WINinfo* win);
void GameRender_ClearOverlay(WINinfo* win, sRectangle &rect); void GameRender_ClearOverlay(WINinfo* win, sRectangle &rect);
BYTE* GameRender_GetOverlaySurface(WINinfo* win); BYTE* GameRender_GetOverlaySurface(WINinfo* win);
+1
View File
@@ -528,6 +528,7 @@ static void SpeedInterfaceCounterAnimsPatch() {
} }
static bool IFACE_BAR_MODE = false; static bool IFACE_BAR_MODE = false;
static long gmouse_handle_event_hook() { static long gmouse_handle_event_hook() {
long countWin = *ptr_num_windows; long countWin = *ptr_num_windows;
long ifaceWin = *ptr_interfaceWindow; long ifaceWin = *ptr_interfaceWindow;
+24 -13
View File
@@ -551,12 +551,33 @@ static void AlwaysReloadMsgs() {
} }
} }
static void RemoveWindowRoundingPatch() { static void InterfaceWindowPatch() {
if (GetConfigInt("Misc", "RemoveWindowRounding", 1)) { if (GetConfigInt("Misc", "RemoveWindowRounding", 1)) {
const DWORD windowRoundingAddr[] = {0x4D6EDD, 0x4D6F12}; const DWORD windowRoundingAddr[] = {0x4D6EDD, 0x4D6F12};
SafeWriteBatch<BYTE>(CODETYPE_JumpShort, windowRoundingAddr); SafeWriteBatch<BYTE>(CODETYPE_JumpShort, windowRoundingAddr);
//SafeWrite16(0x4B8090, 0x04EB); // jmps 0x4B8096 (old)
} }
dlog("Applying flags patch for interface windows.", DL_INIT);
// Remove MoveOnTop flag for interfaces
SafeWrite8(0x46ECE9, (*(BYTE*)0x46ECE9) ^ WinFlags::MoveOnTop); // Player Inventory/Loot/UseOn
SafeWrite8(0x41B966, (*(BYTE*)0x41B966) ^ WinFlags::MoveOnTop); // Automap
// Set OwnerFlag flag
SafeWrite8(0x481CEC, (*(BYTE*)0x481CEC) | WinFlags::OwnerFlag); // _display_win (map win)
SafeWrite8(0x44E7D2, (*(BYTE*)0x44E7D2) | WinFlags::OwnerFlag); // gmovie_play_ (movie win)
// Remove OwnerFlag flag
SafeWrite8(0x4B801B, (*(BYTE*)0x4B801B) ^ WinFlags::OwnerFlag); // createWindow_
// Remove OwnerFlag and Transparent flags
SafeWrite8(0x42F869, (*(BYTE*)0x42F869) ^ (WinFlags::Transparent | WinFlags::OwnerFlag)); // addWindow_
dlogr(" Done", DL_INIT);
// Disable unused code for the RandX and RandY window structure fields (these fields can now be used for other purposes)
SafeWrite32(0x4D630C, 0x9090C031); // xor eax, eax
SafeWrite8(0x4D6310, 0x90);
BlockCall(0x4D6319);
} }
static void InventoryCharacterRotationSpeedPatch() { static void InventoryCharacterRotationSpeedPatch() {
@@ -635,15 +656,6 @@ static void SkipLoadingGameSettingsPatch() {
} }
} }
static void InterfaceDontMoveOnTopPatch() {
//if (GetConfigInt("Misc", "InterfaceDontMoveOnTop", 0)) {
dlog("Applying no MoveOnTop flag for interface patch.", DL_INIT);
SafeWrite8(0x46ECE9, WinFlags::Exclusive); // Player Inventory/Loot/UseOn
SafeWrite8(0x41B966, WinFlags::Exclusive); // Automap
dlogr(" Done", DL_INIT);
//}
}
static void UseWalkDistancePatch() { static void UseWalkDistancePatch() {
int distance = GetConfigInt("Misc", "UseWalkDistance", 3) + 2; int distance = GetConfigInt("Misc", "UseWalkDistance", 3) + 2;
if (distance > 1 && distance < 5) { if (distance > 1 && distance < 5) {
@@ -790,7 +802,7 @@ void MiscPatches_Init() {
PlayIdleAnimOnReloadPatch(); PlayIdleAnimOnReloadPatch();
SkilldexImagesPatch(); SkilldexImagesPatch();
RemoveWindowRoundingPatch(); InterfaceWindowPatch();
ScienceOnCrittersPatch(); ScienceOnCrittersPatch();
InventoryCharacterRotationSpeedPatch(); InventoryCharacterRotationSpeedPatch();
@@ -814,7 +826,6 @@ void MiscPatches_Init() {
KeepWeaponSelectModePatch(); KeepWeaponSelectModePatch();
SkipLoadingGameSettingsPatch(); SkipLoadingGameSettingsPatch();
InterfaceDontMoveOnTopPatch();
UseWalkDistancePatch(); UseWalkDistancePatch();
} }
+15 -10
View File
@@ -341,10 +341,17 @@ static void __declspec(naked) op_is_iface_tag_active() {
} }
static void mf_intface_redraw() { static void mf_intface_redraw() {
if (opHandler.arg(0).rawValue() == 0) { if (opHandler.numArgs() == 0) {
IntfaceRedraw(); IntfaceRedraw();
} else { } else {
RefreshGNW(2); // fake redraw all interfaces (TODO: need a real redraw of interfaces) // fake redraw interfaces (TODO: need a real redraw of interface?)
long winType = opHandler.arg(0).rawValue();
if (winType == -1) {
RefreshGNW(true);
} else {
WINinfo* win = Interface_GetWindow(winType);
if (win && (int)win != -1) GNWWinRefresh(win, &win->rect, 0);
}
} }
} }
@@ -701,7 +708,7 @@ static long __stdcall InterfaceDrawImage(OpcodeHandler& opHandler, WINinfo* ifac
surface + (y * ifaceWin->width) + x, width, height, ifaceWin->width surface + (y * ifaceWin->width) + x, width, height, ifaceWin->width
); );
if (!(opHandler.arg(0).rawValue() & 0x1000000)) { if (!(opHandler.arg(0).rawValue() & 0x1000000)) { // is set to "Don't redraw"
GNWWinRefresh(ifaceWin, &ifaceWin->rect, 0); GNWWinRefresh(ifaceWin, &ifaceWin->rect, 0);
} }
@@ -893,15 +900,15 @@ static void mf_win_fill_color() {
} }
static void mf_interface_overlay() { static void mf_interface_overlay() {
WINinfo* win = nullptr;
long winType = opHandler.arg(0).rawValue(); long winType = opHandler.arg(0).rawValue();
if (opHandler.arg(1).rawValue()) { WINinfo* win = Interface_GetWindow(winType);
win = Interface_GetWindow(winType); if (!win || (int)win == -1) return;
if (!win || (int)win == -1) return;
}
switch (opHandler.arg(1).rawValue()) { switch (opHandler.arg(1).rawValue()) {
case 0:
GameRender_DestroyOverlaySurface(win);
break;
case 1: case 1:
GameRender_CreateOverlaySurface(win, winType); GameRender_CreateOverlaySurface(win, winType);
break; break;
@@ -921,7 +928,5 @@ static void mf_interface_overlay() {
GameRender_ClearOverlay(win); GameRender_ClearOverlay(win);
} }
break; break;
//case 0: // unused (reserved)
// GameRender_DestroyOverlaySurface(winType);
} }
} }
-7
View File
@@ -76,13 +76,6 @@ struct ddrawDll {
#define pushadc __asm push eax __asm push edx __asm push ecx #define pushadc __asm push eax __asm push edx __asm push ecx
#define popadc __asm pop ecx __asm pop edx __asm pop eax #define popadc __asm pop ecx __asm pop edx __asm pop eax
struct sRectangle {
long x, y, width, height;
long right() { return x + width; }
long bottom() { return y + height; }
};
// Gets the integer value from given INI file. // Gets the integer value from given INI file.
int iniGetInt(const char* section, const char* setting, int defaultValue, const char* iniFile); int iniGetInt(const char* section, const char* setting, int defaultValue, const char* iniFile);