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_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_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_is_hidden sfall_func0("intface_is_hidden")
#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_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_destroy(winType) sfall_func2("interface_overlay", winType, 0)
#define real_dude_obj sfall_func0("real_dude_obj")
#define remove_all_timer_events sfall_func0("remove_timer_event")
#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
> 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
- 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")
- 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)
- 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 -------
------------------------
@@ -365,6 +365,4 @@
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
+10 -10
View File
@@ -702,16 +702,16 @@ namespace Fields {
namespace WinFlags {
enum WinButtonFlags : long
{
OwnerFlag = 0x1,
DontMoveTop = 0x2,
MoveOnTop = 0x4,
Hidden = 0x8,
Exclusive = 0x10,
Transparent = 0x20,
UnknownFlag40 = 0x40,
UnknownFlag80 = 0x80,
ScriptWindow = 0x100,
itsButton = 0x10000,
OwnerFlag = 0x000001, // sfall Render flag, indicates that the window surface is used for rendering the game scene
DontMoveTop = 0x000002, // does not move the window to top when the mouse is clicked in the window area or when it is showing
MoveOnTop = 0x000004, // places the window on top when it is created
Hidden = 0x000008,
Exclusive = 0x000010,
Transparent = 0x000020,
UnknownFlag40 = 0x000040,
UnknownFlag80 = 0x000080,
ScriptWindow = 0x000100,
itsButton = 0x010000,
};
}
+4 -3
View File
@@ -1707,10 +1707,11 @@ void RedrawObject(TGameObj* obj) {
TileRefreshRect(&rect, obj->elevation);
}
// Redraws all interface windows
void RefreshGNW(size_t from) {
// Redraws all windows
void RefreshGNW(bool skipOwner) {
*(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);
}
*(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)
void RedrawObject(TGameObj* obj);
// Redraws all interface windows
void RefreshGNW(size_t from = 0);
// Redraws all windows
void RefreshGNW(bool skipOwner = false);
UNLSTDfrm *LoadUnlistedFrm(char *frmName, unsigned int folderRef);
+7
View File
@@ -20,6 +20,13 @@
#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 */
/******************************************************************************/
+39 -28
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
{
private:
@@ -1338,14 +1340,14 @@ private:
BYTE* surface;
public:
//long winType = -1;
long winType;
OverlaySurface() : size(0), surface(nullptr) {}
OverlaySurface() : size(0), surface(nullptr), winType(-1) {}
BYTE* Surface() { return surface; }
void CreateSurface(WINinfo* win, long winType) {
//this->winType = winType;
this->winType = winType;
this->surfWidth = win->width;
this->size = win->height * win->width;
@@ -1372,26 +1374,28 @@ public:
size_t sizeD = rect.width >> 2;
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;
while (height--) {
if (sizeD) {
__stosd((DWORD*)surf, 0, sizeD);
surf += stride;
surf += strideD;
}
if (sizeB) {
__stosb(surf, 0, sizeB);
surf += sizeB;
}
surf += stride;
};
}
}
/*void DestroySurface() {
void DestroySurface() {
delete[] surface;
surface = nullptr;
}*/
}
~OverlaySurface() {
delete[] surface;
@@ -1401,32 +1405,45 @@ public:
static long indexPosition = 0;
void GameRender_CreateOverlaySurface(WINinfo* win, long winType) {
overlaySurfaces[indexPosition].CreateSurface(win, winType);
win->randY = reinterpret_cast<long*>(&overlaySurfaces[indexPosition]);
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]);
}
BYTE* GameRender_GetOverlaySurface(WINinfo* win) {
return reinterpret_cast<OverlaySurface*>(win->randY)->Surface();
};
}
void GameRender_ClearOverlay(WINinfo* win) {
if (win->randY) reinterpret_cast<OverlaySurface*>(win->randY)->ClearSurface();
};
}
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() };
updateRect.x += win->rect.x;
updateRect.y += win->rect.y;
updateRect.offx += win->rect.x;
updateRect.offy += win->rect.y;
sf_GNW_win_refresh(win, reinterpret_cast<RECT*>(&updateRect), 0);
}
}
/*void GameRender_DestroyOverlaySurface(long winType) {
for (size_t i = 0; i < 5; i++) {
if (overlaySurfaces[i].winType == winType) {
overlaySurfaces[i].DestroySurface();
overlaySurfaces[i].winType = -1;
//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() {
return (BYTE*)*(DWORD*)_screen_buffer;
@@ -1664,18 +1681,12 @@ void Graphics_Init() {
0x4D75E6 // win_clip_ (remove _buffering checking)
};
SafeWriteBatch<WORD>(0x9090, winBufferAddr);
SafeWrite8(0x42F869, WinFlags::MoveOnTop | WinFlags::OwnerFlag); // addWindow_ (remove Transparent flag)
// Custom implementation of the GNW_win_refresh function
MakeJump(0x4D6FD9, GNW_win_refresh_hack, 1);
// Replace _screendump_buf with _screen_buffer for creating screenshots
const DWORD scrdumpBufAddr[] = {0x4C8FD1, 0x4C900D};
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() {
+1 -1
View File
@@ -52,7 +52,7 @@ void Gfx_ReleaseMovieTexture();
void Gfx_RefreshGraphics();
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, sRectangle &rect);
BYTE* GameRender_GetOverlaySurface(WINinfo* win);
+1
View File
@@ -528,6 +528,7 @@ static void SpeedInterfaceCounterAnimsPatch() {
}
static bool IFACE_BAR_MODE = false;
static long gmouse_handle_event_hook() {
long countWin = *ptr_num_windows;
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)) {
const DWORD windowRoundingAddr[] = {0x4D6EDD, 0x4D6F12};
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() {
@@ -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() {
int distance = GetConfigInt("Misc", "UseWalkDistance", 3) + 2;
if (distance > 1 && distance < 5) {
@@ -790,7 +802,7 @@ void MiscPatches_Init() {
PlayIdleAnimOnReloadPatch();
SkilldexImagesPatch();
RemoveWindowRoundingPatch();
InterfaceWindowPatch();
ScienceOnCrittersPatch();
InventoryCharacterRotationSpeedPatch();
@@ -814,7 +826,6 @@ void MiscPatches_Init() {
KeepWeaponSelectModePatch();
SkipLoadingGameSettingsPatch();
InterfaceDontMoveOnTopPatch();
UseWalkDistancePatch();
}
+14 -9
View File
@@ -341,10 +341,17 @@ static void __declspec(naked) op_is_iface_tag_active() {
}
static void mf_intface_redraw() {
if (opHandler.arg(0).rawValue() == 0) {
if (opHandler.numArgs() == 0) {
IntfaceRedraw();
} 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
);
if (!(opHandler.arg(0).rawValue() & 0x1000000)) {
if (!(opHandler.arg(0).rawValue() & 0x1000000)) { // is set to "Don't redraw"
GNWWinRefresh(ifaceWin, &ifaceWin->rect, 0);
}
@@ -893,15 +900,15 @@ static void mf_win_fill_color() {
}
static void mf_interface_overlay() {
WINinfo* win = nullptr;
long winType = opHandler.arg(0).rawValue();
if (opHandler.arg(1).rawValue()) {
win = Interface_GetWindow(winType);
WINinfo* win = Interface_GetWindow(winType);
if (!win || (int)win == -1) return;
}
switch (opHandler.arg(1).rawValue()) {
case 0:
GameRender_DestroyOverlaySurface(win);
break;
case 1:
GameRender_CreateOverlaySurface(win, winType);
break;
@@ -921,7 +928,5 @@ static void mf_interface_overlay() {
GameRender_ClearOverlay(win);
}
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 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.
int iniGetInt(const char* section, const char* setting, int defaultValue, const char* iniFile);