Improvements for the windowed game mode

Some changes in the implementation of HRP code.
This commit is contained in:
NovaRain
2021-10-31 09:57:18 +08:00
parent 4385807cd3
commit e35745353c
13 changed files with 235 additions and 77 deletions
+1
View File
@@ -126,6 +126,7 @@
#define FO_VAR_gmovie_played_list 0x596C78
#define FO_VAR_GNW_win_init_flag 0x51E3E0
#define FO_VAR_GNW95_isActive 0x51E444
#define FO_VAR_GNW95_hwnd 0x51E434 // main hwnd window
#define FO_VAR_GNW95_repeat_delay 0x51E240
#define FO_VAR_GNW95_repeat_rate 0x51E23C
#define FO_VAR_GNWWin 0x5195B8
+33 -2
View File
@@ -4,6 +4,8 @@
*
*/
#include <psapi.h>
#include "..\main.h"
#include "..\FalloutEngine\Fallout2.h"
#include "..\Modules\LoadOrder.h"
@@ -27,6 +29,31 @@ bool HRP::Enabled;
long HRP::ScreenWidth() { return SCR_WIDTH; }
long HRP::ScreenHeight() { return SCR_HEIGHT; }
DWORD HRP::hrpDLLBaseAddr = 0x10000000;
static void LoadHRPModule() {
static const DWORD loadFunc = 0x4FE1D0;
HMODULE dll;
__asm call loadFunc; // get HRP loading address
__asm mov dll, eax;
if (dll != NULL) HRP::hrpDLLBaseAddr = (DWORD)dll;
dlog_f("Loaded f2_res.dll library at the memory address: 0x%x\n", DL_MAIN, dll);
}
bool HRP::CheckExternalPatch() {
bool isEnabled = (*(DWORD*)0x4E4480 != 0x278805C7); // check if Mash's HRP is enabled
if (isEnabled) {
LoadHRPModule();
MODULEINFO info;
if (GetModuleInformation(GetCurrentProcess(), (HMODULE)HRP::hrpDLLBaseAddr, &info, sizeof(info)) && info.SizeOfImage >= 0x39940 + 7) {
if (GetByteHRPValue(HRP_VAR_VERSION_STR + 7) == 0 && std::strncmp((const char*)HRPAddress(HRP_VAR_VERSION_STR), "4.1.8", 5) == 0) {
hrpVersionValid = true;
}
}
}
return isEnabled;
}
void HRP::init() {
if (!hrpIsEnabled && IniReader::GetIntDefaultConfig("Main", "HiResMode", 1) == 0) return; // vanilla game mode
@@ -37,8 +64,8 @@ void HRP::init() {
if (SCR_HEIGHT < 480) SCR_HEIGHT = 480;
if (hrpIsEnabled) { // external
//MessageBoxA(0, "", "Error", MB_TASKMODAL | MB_ICONERROR);
//ExitProcess(-1);
// You have both the built-in and external HRP enabled at the same time. It is recommended to turn off the external HRP by Mash.
// To continue using the external HRP, disable the HiResMode option in ddraw.ini
return;
}
Enabled = true;
@@ -67,6 +94,10 @@ void HRP::init() {
ViewMap::SCROLL_DIST_X = (x == "HALF_SCRN") ? (SCR_WIDTH / 2) + 32 : std::atol(x.c_str());
ViewMap::SCROLL_DIST_Y = (y == "HALF_SCRN") ? (SCR_HEIGHT / 2) + 24 : std::atol(y.c_str());
ViewMap::IGNORE_PLAYER_SCROLL_LIMITS = (IniReader::GetInt("MAPS", "IGNORE_PLAYER_SCROLL_LIMITS", 0, f2ResIni) != 0);
ViewMap::IGNORE_MAP_EDGES = (IniReader::GetInt("MAPS", "IGNORE_MAP_EDGES", 0, f2ResIni) != 0);
ViewMap::EDGE_CLIPPING_ON = (IniReader::GetInt("MAPS", "EDGE_CLIPPING_ON", 1, f2ResIni) != 0);
// add before sfall.dat and after critter.dat
LoadOrder::AddResourcePatches(
IniReader::GetString("Main", "f2_res_dat", "f2_res.dat", MAX_PATH, f2ResIni),
+3
View File
@@ -13,6 +13,9 @@ class HRP {
public:
static void init();
static DWORD hrpDLLBaseAddr;
static bool CheckExternalPatch();
// Built-in high resolution patch
static bool Enabled;
+23 -42
View File
@@ -6,6 +6,7 @@
#include "..\..\main.h"
#include "..\..\FalloutEngine\Fallout2.h"
#include "..\..\Modules\LoadGameHook.h"
#include "ViewMap.h"
@@ -22,7 +23,7 @@ static struct Edge {
RECT tileRect_3;
RECT rect_4;
long field_48;
Edge* prevEdgeData_4C; // unused? (used in 3.06)
Edge* prevEdgeData; // unused? (used in 3.06)
Edge* nextEdgeData_50;
void Release() {
@@ -43,12 +44,12 @@ static struct Edge {
Edge* CurrentMapEdge;
long EdgeVersion;
long isLoadingMapEdge;
bool isLoadingMapEdge;
bool isDefaultSetEdge;
// Implementation from HRP by Mash
static void CalcEdgeData(Edge* edgeData, long w, long h) {
long x = 0, y = 0;
long x, y;
ViewMap::GetTileCoordOffset(edgeData->tileRect_3.left, x, y);
edgeData->rect_1.left = x;
@@ -119,7 +120,7 @@ static void CalcEdgeData(Edge* edgeData, long w, long h) {
}
static void SetDefaultEdgeData() {
long w = 0, h = 0;
long w, h;
ViewMap::GetMapWindowSize(w, h);
if (MapEdgeData == nullptr) MapEdgeData = new Edge[3];
@@ -131,7 +132,7 @@ static void SetDefaultEdgeData() {
edge->tileRect_3.top = 0;
edge->tileRect_3.right = 39800;
edge->tileRect_3.bottom = 39999;
edge->prevEdgeData_4C = nullptr;
edge->prevEdgeData = nullptr;
CalcEdgeData(edge, w, h);
@@ -149,11 +150,11 @@ static void SetDefaultEdgeData() {
// Implementation from HRP by Mash
static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
char edgPath[32];
char edgPath[33];
char* posDot = std::strchr(mapName, '.');
*posDot = '\0';
std::sprintf(edgPath, "%s.edg", mapName); //maps
std::sprintf(edgPath, "maps\\%s.edg", mapName);
*posDot = '.';
fo::DbFile* file = fo::func::db_fopen(edgPath, "rb");
@@ -177,7 +178,7 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
getValue = 0;
if (fo::func::db_freadInt(file, &getValue) || getValue) return file; // unknown for now
long w = 0, h = 0;
long w, h;
ViewMap::GetMapWindowSize(w, h);
if (MapEdgeData) {
@@ -193,7 +194,7 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
Edge* edgeData = &MapEdgeData[mapLevel];
if (EdgeVersion) {
// load a rectangle?
// load rectangle data (version 1)
if (fo::func::db_freadIntCount(file, (DWORD*)&edgeData->rect_4, 4) || fo::func::db_freadInt(file, (DWORD*)&edgeData->field_48)) {
return file; // read error
}
@@ -207,28 +208,25 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
if (getValue == mapLevel) {
while (true) {
long result = fo::func::db_freadIntCount(file, (DWORD*)&edgeData->tileRect_3, 4); // load the rectangle
long result = fo::func::db_freadIntCount(file, (DWORD*)&edgeData->tileRect_3, 4); // load rectangle data
if (result != 0) return file; // read error
CalcEdgeData(edgeData, w, h);
if (fo::func::db_freadInt(file, &getValue)) {
if (fo::func::db_freadInt(file, &getValue)) { // are there more rectangles on the current map level?
// the end of file is reached (read error)
if (mapLevel != 2) return file;
getValue = -1;
break; // next level
}
if (getValue != mapLevel) break; // next level
if (getValue == mapLevel) { // there are more rectangles for the current map level
Edge *edge = new Edge;
edge->nextEdgeData_50 = nullptr;
edge->rect_4 = edgeData->rect_4; // rect copy
edgeData->nextEdgeData_50 = edge;
edgeData = edge;
continue; // next read
}
break; // next level
Edge *edge = new Edge;
edge->nextEdgeData_50 = nullptr;
edge->rect_4 = edgeData->rect_4; // rect copy
edgeData->nextEdgeData_50 = edge;
edgeData = edge;
}
}
} while (++mapLevel < 3);
@@ -237,38 +235,21 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
return 0;
}
static void __fastcall LoadMapEdgeFile(char* mapName) {
isLoadingMapEdge = 0;
static void __fastcall LoadMapEdgeFile() {
//isLoadingMapEdge = 0;
fo::DbFile* file = LoadMapEdgeFileSub(mapName);
fo::DbFile* file = LoadMapEdgeFileSub(LoadGameHook::mapLoadingName);
if (file) { // load error
fo::func::db_fclose(file);
SetDefaultEdgeData();
}
}
// open map file
static void __declspec(naked) map_load_hook_db_fopen() {
__asm {
push ecx;
mov ecx, eax; // mapName
call fo::funcoffs::db_fopen_;
test eax, eax;
jz fail;
push eax;
call LoadMapEdgeFile;
pop eax;
fail:
pop ecx;
retn;
}
}
// Implementation from HRP by Mash
long EdgeBorder::GetCenterTile(long tile, long mapLevel) {
if (!isDefaultSetEdge) SetDefaultEdgeData(); // needed at game initialization
long x = 0, y = 0;
long x, y;
ViewMap::GetTileCoordOffset(tile, x, y);
Edge* edgeData = &MapEdgeData[mapLevel];
@@ -381,7 +362,7 @@ long EdgeBorder::CheckBorder(long tile) {
}
void EdgeBorder::init() {
HookCall(0x482AE1, map_load_hook_db_fopen);
LoadGameHook::OnBeforeMapLoad() += LoadMapEdgeFile;
}
}
+15 -5
View File
@@ -6,6 +6,7 @@
#include "..\..\main.h"
#include "..\..\FalloutEngine\Fallout2.h"
#include "..\..\Modules\LoadGameHook.h"
#include "EdgeBorder.h"
@@ -16,6 +17,9 @@ namespace sfall
long ViewMap::SCROLL_DIST_X;
long ViewMap::SCROLL_DIST_Y;
bool ViewMap::IGNORE_PLAYER_SCROLL_LIMITS;
bool ViewMap::IGNORE_MAP_EDGES;
bool ViewMap::EDGE_CLIPPING_ON;
static long mapDisplayWinWidthMod;
static long mapDisplayWinHeightMod;
@@ -71,17 +75,17 @@ static long __fastcall tile_set_center(long tile, long modeFlags) {
if (modeFlags) tile = EdgeBorder::GetCenterTile(tile, mapElevation);
if (!(modeFlags & 2) && fo::var::getInt(FO_VAR_scroll_limiting_on)) {
long x = 0, y = 0;
long x, y;
ViewMap::GetTileCoord(tile, x, y);
long dudeX = 0, dudeY = 0;
long dudeX, dudeY;
ViewMap::GetTileCoord(fo::var::obj_dude->tile, dudeX, dudeY);
long distanceX = 16 * std::abs(x - dudeX);
long distanceY = 12 * std::abs(y - dudeY);
if (distanceX >= ViewMap::SCROLL_DIST_X || distanceY >= ViewMap::SCROLL_DIST_Y) { // doesn't seem to work
long centerX = 0, centerY = 0;
long centerX, centerY;
ViewMap::GetTileCoord(fo::var::getInt(FO_VAR_tile_center_tile), centerX, centerY);
if ((16 * std::abs(centerX - tile)) < distanceX || (12 * std::abs(centerY - dudeY)) < distanceY) {
@@ -158,10 +162,16 @@ void ViewMap::init() {
MakeJump(fo::funcoffs::tile_set_center_, tile_set_center_hack_replacement); // 0x4B12F8
MakeJump(fo::funcoffs::tile_scroll_to_, tile_set_center_hack_replacement);
// Dev block tile_set_border_
//BlockCall(0x4B11A3); // tile_init_
EdgeBorder::init();
LoadGameHook::OnAfterGameInit() += []() {
if (IGNORE_PLAYER_SCROLL_LIMITS) fo::var::setInt(FO_VAR_scroll_limiting_on) = 0;
if (IGNORE_MAP_EDGES) fo::var::setInt(FO_VAR_scroll_blocking_on) = 0;
};
// Dev block tile_set_border_
//BlockCall(0x4B11A3); // tile_init_
}
}
+3
View File
@@ -15,6 +15,9 @@ public:
static long SCROLL_DIST_X;
static long SCROLL_DIST_Y;
static bool IGNORE_PLAYER_SCROLL_LIMITS;
static bool IGNORE_MAP_EDGES;
static bool EDGE_CLIPPING_ON;
static long MapDisplayWinHalfWidth;
static long MapDisplayWinHalfHeight;
+14 -3
View File
@@ -19,6 +19,7 @@
#include "..\main.h"
#include "..\FalloutEngine\Fallout2.h"
#include "..\InputFuncs.h"
#include "..\version.h"
#include "LoadGameHook.h"
#include "ScriptShaders.h"
@@ -50,6 +51,7 @@ static DWORD ResHeight;
DWORD Graphics::GPUBlt;
DWORD Graphics::mode;
bool Graphics::IsWindowMode;
bool Graphics::PlayAviMovie = false;
bool Graphics::AviMovieWidthFit = false;
@@ -96,7 +98,7 @@ static bool windowInit = false;
static long windowLeft = 0;
static long windowTop = 0;
static HWND window;
static DWORD windowStyle = WS_CAPTION | WS_BORDER | WS_MINIMIZEBOX;
static DWORD windowStyle = WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
static int windowData;
@@ -1056,6 +1058,7 @@ public:
HRESULT __stdcall RestoreDisplayMode() { return DD_OK; }
HRESULT __stdcall SetCooperativeLevel(HWND a, DWORD b) { // called 0x4CB005 GNW95_init_DirectDraw_
char captionText[128];
window = a;
if (!d3d9Device) {
@@ -1065,7 +1068,14 @@ public:
dlog("Creating D3D9 Device window...", DL_MAIN);
if (Graphics::mode >= 5) {
SetWindowLong(a, GWL_STYLE, windowStyle);
if (ResWidth != gWidth || ResHeight != gHeight) {
std::sprintf(captionText, "%s @sfall " VERSION_STRING " %ix%i >> %ix%i", (const char*)0x50AF08, ResWidth, ResHeight, gWidth, gHeight);
} else {
std::sprintf(captionText, "%s @sfall " VERSION_STRING, (const char*)0x50AF08);
}
SetWindowTextA(a, captionText);
SetWindowLongA(a, GWL_STYLE, windowStyle);
RECT r;
r.left = 0;
r.right = gWidth;
@@ -1074,7 +1084,7 @@ public:
AdjustWindowRect(&r, windowStyle, false);
r.right -= r.left;
r.bottom -= r.top;
SetWindowPos(a, HWND_NOTOPMOST, windowLeft, windowTop, r.right, r.bottom, SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
SetWindowPos(a, HWND_NOTOPMOST, windowLeft, windowTop, r.right, r.bottom, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
}
dlogr(" Done", DL_MAIN);
@@ -1255,6 +1265,7 @@ void Graphics::init() {
} else if (Graphics::mode != 4 && Graphics::mode != 5) {
Graphics::mode = 0;
}
IsWindowMode = (mode == 5 || mode == 6);
if (Graphics::mode) {
dlog("Applying DX9 graphics patch.", DL_INIT);
+1
View File
@@ -58,6 +58,7 @@ public:
static DWORD mode;
static DWORD GPUBlt;
static bool IsWindowMode;
static HWND GetFalloutWindowInfo(RECT* rect);
static long GetGameWidthRes();
+108
View File
@@ -0,0 +1,108 @@
/*
* sfall
* Copyright (C) 2008-2021 The sfall team
*
*/
#include "main.h"
#include "FalloutEngine\Fallout2.h"
#include "WinProc.h"
namespace sfall
{
static bool cCursorShow = true;
static int __stdcall WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
RECT rect;
//POINT point;
switch (msg) {
case WM_DESTROY:
__asm xor eax, eax;
__asm call fo::funcoffs::exit_;
case WM_ERASEBKGND:
return 1;
case WM_PAINT:
if (GetUpdateRect(hWnd, &rect, 0) == 1) {
rect.right -= 1;
rect.bottom -= 1;
__asm {
//lea eax, rect;
//call fo::funcoffs::win_refresh_all_;
}
}
break;
case WM_ACTIVATE:
if (!cCursorShow && wParam == WA_INACTIVE) {
cCursorShow = true;
ShowCursor(1);
}
break;
case WM_SETCURSOR: {
short type = LOWORD(lParam);
/*if (type == HTCAPTION || type == HTBORDER || type == HTMINBUTTON || type == HTCLOSE || type == HTMAXBUTTON) {
if (!cCursorShow) {
cCursorShow = true;
ShowCursor(1);
}
}
else*/ if (type == HTCLIENT && fo::var::getInt(FO_VAR_GNW95_isActive)) {
if (cCursorShow) {
cCursorShow = false;
ShowCursor(0);
}
}
return 1;
//break;
}
case WM_SYSCOMMAND:
if ((wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER) return 0;
break;
case WM_ACTIVATEAPP:
fo::var::setInt(FO_VAR_GNW95_isActive) = wParam;
if (wParam) { // active
/*point.x = 0;
point.y = 0;
ClientToScreen(hWnd, &point);
GetClientRect(hWnd, &rect);
rect.left += point.x;
rect.right += point.x;
rect.top += point.y;
rect.bottom += point.y;
ClipCursor(&rect);*/
__asm {
mov eax, 1;
call fo::funcoffs::GNW95_hook_input_;
//mov eax, FO_VAR_scr_size;
//call fo::funcoffs::win_refresh_all_;
}
} else{
// ClipCursor(0);
__asm xor eax, eax;
__asm call fo::funcoffs::GNW95_hook_input_;
}
return 0;
case WM_CLOSE:
break;
}
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
void WinProc::SetWindowProc() {
SetWindowLongA((HWND)fo::var::getInt(FO_VAR_GNW95_hwnd), GWL_WNDPROC, (LONG)WindowProc);
}
void WinProc::init() {
MakeJump(0x4DE9FC, WindowProc); // WindowProc_
//SafeWrite8(0x4DEB0D, 1); // for test
}
}
+19
View File
@@ -0,0 +1,19 @@
/*
* sfall
* Copyright (C) 2008-2021 The sfall team
*
*/
#pragma once
namespace sfall
{
class WinProc {
public:
static void init();
static void SetWindowProc();
};
}
+2
View File
@@ -415,6 +415,7 @@
<ClInclude Include="Logging.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Modules\ExtraSaveSlots.h" />
<ClInclude Include="WinProc.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="CheckAddress.cpp" />
@@ -539,6 +540,7 @@
</ClCompile>
<ClCompile Include="Translate.cpp" />
<ClCompile Include="Utils.cpp" />
<ClCompile Include="WinProc.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="exports.def" />
+2
View File
@@ -394,6 +394,7 @@
<ClInclude Include="HRP\ViewMap\ViewMap.h">
<Filter>HRP\ViewMap</Filter>
</ClInclude>
<ClInclude Include="WinProc.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
@@ -723,6 +724,7 @@
<ClCompile Include="HRP\ViewMap\ViewMap.cpp">
<Filter>HRP\ViewMap</Filter>
</ClCompile>
<ClCompile Include="WinProc.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />
+11 -25
View File
@@ -18,8 +18,6 @@
#pragma comment(lib, "psapi.lib")
#include <psapi.h>
#include "main.h"
#include "FalloutEngine\Fallout2.h"
@@ -84,6 +82,7 @@
#include "ReplacementFuncs.h"
#include "Translate.h"
#include "version.h"
#include "WinProc.h"
#include "HRP\Init.h"
@@ -97,10 +96,8 @@ bool isDebug = false;
bool hrpIsEnabled = false;
bool hrpVersionValid = false; // HRP 4.1.8 version validation
static DWORD hrpDLLBaseAddr = 0x10000000;
DWORD HRPAddress(DWORD addr) {
return (hrpDLLBaseAddr + (addr & 0xFFFFF));
return (HRP::hrpDLLBaseAddr + (addr & 0xFFFFF));
}
char falloutConfigName[65];
@@ -180,15 +177,6 @@ static void InitModules() {
dlogr("Leave InitModules", DL_MAIN);
}
static void LoadHRPModule() {
static const DWORD loadFunc = 0x4FE1D0;
HMODULE dll;
__asm call loadFunc; // get HRP loading address
__asm mov dll, eax;
if (dll != NULL) hrpDLLBaseAddr = (DWORD)dll;
dlog_f("Loaded f2_res.dll library at the memory address: 0x%x\n", DL_MAIN, dll);
}
static void CompatModeCheck(HKEY root, const char* filepath, int extra) {
HKEY key;
char buf[MAX_PATH];
@@ -223,11 +211,20 @@ static void SfallInit() {
char filepath[MAX_PATH];
GetModuleFileName(0, filepath, MAX_PATH);
SetCursor(LoadCursorA(0, IDC_ARROW));
ShowCursor(1);
if (!CRC(filepath)) return;
LoggingInit();
if (!ddraw.dll) dlog("Error: Cannot load the original ddraw.dll library.\n");
hrpIsEnabled = HRP::CheckExternalPatch();
if (!hrpIsEnabled)
WinProc::init();
else
ShowCursor(0);
// enabling debugging features
isDebug = (IniReader::GetIntDefaultConfig("Debugging", "Enable", 0) != 0);
if (!isDebug || !IniReader::GetIntDefaultConfig("Debugging", "SkipCompatModeCheck", 0)) {
@@ -284,17 +281,6 @@ static void SfallInit() {
defaultIni:
IniReader::SetDefaultConfigFile();
}
hrpIsEnabled = (*(DWORD*)0x4E4480 != 0x278805C7); // check if HRP is enabled
if (hrpIsEnabled) {
LoadHRPModule();
MODULEINFO info;
if (GetModuleInformation(GetCurrentProcess(), (HMODULE)hrpDLLBaseAddr, &info, sizeof(info)) && info.SizeOfImage >= 0x39940 + 7) {
if (GetByteHRPValue(HRP_VAR_VERSION_STR + 7) == 0 && std::strncmp((const char*)HRPAddress(HRP_VAR_VERSION_STR), "4.1.8", 5) == 0) {
hrpVersionValid = true;
}
}
}
std::srand(GetTickCount());
IniReader::init();