(WIP) Added DirectDraw graphics mode for built-in HRP

Moved some code from Graphics.cpp to WinProc.cpp
This commit is contained in:
NovaRain
2021-12-05 09:29:48 +08:00
parent 70da19e49b
commit 6ca5644e99
17 changed files with 651 additions and 216 deletions
-5
View File
@@ -46,11 +46,6 @@ static void __cdecl main_death_scene_hook_buf_to_buf(fo::FrmData* frm, long w, l
long x = 0;
long y = 0;
Image::GetAspectSize(width, height, &x, &y, w, h);
//if (x >= w) { // extract x/y image position
// y = x / w;
// x -= y * w;
//}
if (x || y) {
dst += x + (y * Setting::ScreenWidth());
}
+14 -6
View File
@@ -8,9 +8,10 @@
#include "..\main.h"
#include "..\FalloutEngine\Fallout2.h"
#include "..\Utils.h"
#include "..\Modules\LoadOrder.h"
#include "..\Translate.h"
#include "..\Utils.h"
#include "..\Modules\Graphics.h"
#include "..\Modules\LoadOrder.h"
#include "viewmap\ViewMap.h"
#include "SplashScreen.h"
@@ -45,6 +46,8 @@ static bool SCALE_2X;
static long SCR_WIDTH = 640;
static long SCR_HEIGHT = 480;
static long GRAPHICS_MODE = 2;
bool Setting::IsEnabled() { return enabled; }
long Setting::ScreenWidth() { return SCR_WIDTH; }
long Setting::ScreenHeight() { return SCR_HEIGHT; }
@@ -110,7 +113,7 @@ static bool DisableExtHRP(const char* runFileName, std::string &cmdline) {
DWORD restore1[10] = {0};
_fwrite_nolock(restore1, 4, sizeof(restore1), ft);
fclose(ft);
std::fclose(ft);
cmdline.append(" -restart");
MessageBoxA(0, "High Resolution Patch has been successfully deactivated.", "sfall", MB_TASKMODAL | MB_ICONINFORMATION);
@@ -223,8 +226,6 @@ void Setting::init(const char* exeFileName, std::string &cmdline) {
// Read High Resolution config
// = IniReader::GetInt("Main", "WINDOWED", 0, f2ResIni);
// = IniReader::GetInt("Main", "WINDOWED_FULLSCREEN", 0, f2ResIni);
/*
if (IniReader::GetInt("Main", "SCALE_2X", 0, f2ResIni)) {
SCR_WIDTH /= 2;
@@ -236,7 +237,14 @@ void Setting::init(const char* exeFileName, std::string &cmdline) {
SCALE_2X = true;
};
*/
//gDirectDrawMode = IniReader::GetInt("Main", "GRAPHICS_MODE", 2, f2ResIni) == 1;
int windowed = (sf::IniReader::GetInt("Main", "WINDOWED", 0, f2ResIni) != 0) ? 1 : 0;
if (windowed && sf::IniReader::GetInt("Main", "WINDOWED_FULLSCREEN", 0, f2ResIni)) windowed += 1;
int gMode = sf::IniReader::GetInt("Main", "GRAPHICS_MODE", 2, f2ResIni);
if (gMode < 0 || gMode > 2) gMode = 2;
if (gMode <= 1) sf::Graphics::mode = 1 + windowed; // DD7: 1 or 2/3 (vanilla 16(24) bit)
if (gMode == 2) sf::Graphics::mode = 4 + windowed; // DX9: 4 or 5/6 (sfall)
MainMenuScreen::SCALE_BUTTONS_AND_TEXT_MENU = (sf::IniReader::GetInt("MAINMENU", "SCALE_BUTTONS_AND_TEXT_MENU", 0, f2ResIni) != 0);
MainMenuScreen::USE_HIRES_IMAGES = (sf::IniReader::GetInt("MAINMENU", "USE_HIRES_IMAGES", 1, f2ResIni) != 0);
+36 -11
View File
@@ -21,6 +21,7 @@ namespace sf = sfall;
long MoviesScreen::MOVIE_SIZE;
static RECT movieToSize;
//static bool useDDraw = false;
static void __fastcall SetMovieSize() {
long sWidth = Setting::ScreenWidth();
@@ -68,7 +69,7 @@ static void __declspec(naked) nfConfig_hack() {
}
// surface: _nf_mve_buf1
static long __cdecl movie_MVE_ShowFrame(IDirectDrawSurface* surface, int bW, int bH, int x, int y, int w, int h) {
static void __cdecl movie_MVE_ShowFrame(IDirectDrawSurface* surface, int bW, int bH, int x, int y, int w, int h) {
RECT movieSize;
movieSize.left = x;
movieSize.right = x + bW;
@@ -82,7 +83,27 @@ static long __cdecl movie_MVE_ShowFrame(IDirectDrawSurface* surface, int bW, int
//FO_VAR_lastMovieBW = bW
//FO_VAR_lastMovieBH = bH
return surface->Blt(&movieToSize, surface, &movieSize, MoviesScreen::MOVIE_SIZE, 0); // for sfall DX9
surface->Blt(&movieToSize, surface, &movieSize, MoviesScreen::MOVIE_SIZE, 0); // for sfall DX9
}
// surface: _nf_mve_buf1
static void __cdecl movieShowFrame(IDirectDrawSurface* surface, int bW, int bH, int x, int y, int w, int h) {
//if (fo::var::getInt(FO_VAR_GNWWin) == -1) return;
RECT movieSize;
movieSize.left = x;
movieSize.right = x + bW;
movieSize.top = y;
movieSize.bottom = y + bH;
fo::var::setInt(FO_VAR_lastMovieX) = movieToSize.left;
fo::var::setInt(FO_VAR_lastMovieY) = movieToSize.top;
fo::var::setInt(FO_VAR_lastMovieW) = movieToSize.right - movieToSize.left;
fo::var::setInt(FO_VAR_lastMovieH) = movieToSize.bottom - movieToSize.top;
//FO_VAR_lastMovieBW = bW
//FO_VAR_lastMovieBH = bH
//surface->Blt(&movieToSize, surface, &movieSize, MoviesScreen::MOVIE_SIZE, 0);
}
// Adjust Y position
@@ -146,6 +167,17 @@ skip:
}
}
// Direct output to texture is used for DirectX9, and buffered method (output to GNWWin window) is used for DirectDraw
void MoviesScreen::SetDrawMode(bool mode) {
//useDDraw = mode;
// movieStart_ hack
if (mode) {
sf::SafeWrite8(0x487781, sf::CodeType::JumpShort); // force Buffered
} else {
sf::SafeWrite16(0x487781, 0x9090); // force Direct
}
}
void MoviesScreen::init() {
if (MOVIE_SIZE < 0) MOVIE_SIZE = 0;
@@ -158,20 +190,13 @@ void MoviesScreen::init() {
//sf::SafeWrite8(0x44E7DE, 55); // for debugging
// movieStart_
// Direct output to texture is used for DirectX9, and buffered method (output to GNWWin window) is used for DirectDraw
if (0) {
sf::SafeWrite8(0x487781, sf::CodeType::JumpShort); // force Buffered
} else {
sf::SafeWrite16(0x487781, 0x9090); // force Direct
}
sf::SafeWrite32(0x4877D0, (DWORD)&movie_MVE_ShowFrame); // replace movie_MVE_ShowFrame_ with sfall function
sf::SafeWrite32(0x4877D0, (DWORD)&movie_MVE_ShowFrame); // replace engine movie_MVE_ShowFrame_ with sfall function (for DX9)
sf::SafeWrite32(0x487813, (DWORD)&movieShowFrame); // replace engine movieShowFrame_ with sfall function (for DD7)
sf::MakeCall(0x4F5D40, nfConfig_hack);
// openSubtitle_
sf::HookCall(0x48738E, Setting::ScreenWidth); // replace windowGetXres_
// doSubtitle_ hacks
sf::SafeWrite32(0x487580, Setting::ScreenHeight());
sf::HookCall(0x4875BE, doSubtitle_hook);
+3 -1
View File
@@ -12,8 +12,10 @@ namespace HRP
class MoviesScreen {
public:
static void init();
static long MOVIE_SIZE;
static void SetDrawMode(bool mode);
};
}
+62 -171
View File
@@ -18,14 +18,16 @@
#include "..\main.h"
#include "..\FalloutEngine\Fallout2.h"
#include "..\InputFuncs.h"
#include "..\version.h"
//#include "..\InputFuncs.h"
#include "..\WinProc.h"
#include "LoadGameHook.h"
#include "ScriptShaders.h"
#include "SubModules\DirectDraw.h"
#include "SubModules\WindowRender.h"
#include "..\HRP\Init.h"
#include "..\HRP\MoviesScreen.h"
#include "Graphics.h"
@@ -49,6 +51,9 @@ IDirectDrawPalette* primaryPalette = nullptr; // aka _GNW95_DDPrimaryPalette
static DWORD ResWidth;
static DWORD ResHeight;
static DWORD gWidth;
static DWORD gHeight;
DWORD Graphics::GPUBlt;
DWORD Graphics::mode;
bool Graphics::IsWindowMode;
@@ -56,9 +61,6 @@ bool Graphics::IsWindowMode;
bool Graphics::PlayAviMovie = false;
bool Graphics::AviMovieWidthFit = false;
//static DWORD yoffset;
//static DWORD xoffset;
bool DeviceLost = false;
//static bool mainTexLock = false; // for preventing a crash during the locked state of the texture
static char textureFilter; // 1 - auto, 2 - force
@@ -67,34 +69,10 @@ static DDSURFACEDESC surfaceDesc;
static DDSURFACEDESC mveDesc;
static D3DSURFACE_DESC movieDesc;
#pragma pack(push, 1)
static struct PALCOLOR {
union {
DWORD xRGB;
struct {
BYTE R;
BYTE G;
BYTE B;
BYTE x;
};
};
} *palette;
#pragma pack(pop)
//static bool paletteInit = false;
static DWORD gWidth;
static DWORD gHeight;
static long moveWindowKey[2];
static DirectDraw::PALCOLOR* palette;
static bool windowInit = false;
static long windowLeft = 0;
static long windowTop = 0;
static HWND window;
static DWORD windowStyle = WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
static int windowData;
static DWORD ShaderVersion;
@@ -146,16 +124,6 @@ static VertexFormat ShaderVertices[] = {
{639.5, 479.5, 0, 1, 1, 1} // 3 - bottom right
};
HWND Graphics::GetFalloutWindowInfo(RECT* rect) {
if (rect) {
rect->left = windowLeft;
rect->top = windowTop;
rect->right = gWidth;
rect->bottom = gHeight;
}
return window;
}
long Graphics::GetGameWidthRes() {
return (fo::var::scr_size.offx - fo::var::scr_size.x) + 1;
}
@@ -175,14 +143,6 @@ static void WindowInit() {
ScriptShaders::LoadGlobalShader();
}
static void SetWindowToCenter() {
RECT desktop;
GetWindowRect(GetDesktopWindow(), &desktop);
windowLeft = (desktop.right / 2) - (gWidth / 2);
windowTop = (desktop.bottom / 2) - (gHeight / 2);
}
// pixel size for the current game resolution
const float* Graphics::rcpresGet() {
return rcpres;
@@ -264,7 +224,7 @@ static void ResetDevice(bool create) {
"Texture format error", MB_TASKMODAL | MB_ICONWARNING);
Graphics::GPUBlt = 0;
}
if (Graphics::GPUBlt == 0) palette = new PALCOLOR[256];
if (Graphics::GPUBlt == 0) palette = new DirectDraw::PALCOLOR[256];
#if !(NDEBUG) && !(_DEBUG)
D3DXCreateFontA(d3d9Device, 24, 0, 500, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial", &font); // create a font
@@ -379,48 +339,7 @@ static void DrawFPS() {}
#endif
static void Present() {
if ((moveWindowKey[0] != 0 && KeyDown(moveWindowKey[0])) ||
(moveWindowKey[1] != 0 && KeyDown(moveWindowKey[1])))
{
int winX, winY;
GetMouse(&winX, &winY);
windowLeft += winX;
windowTop += winY;
RECT r, r2;
r.left = windowLeft;
r.right = windowLeft + gWidth;
r.top = windowTop;
r.bottom = windowTop + gHeight;
AdjustWindowRect(&r, WS_CAPTION | WS_BORDER, false);
r.right -= (r.left - windowLeft);
r.left = windowLeft;
r.bottom -= (r.top - windowTop);
r.top = windowTop;
if (GetWindowRect(GetShellWindow(), &r2)) {
if (r.right > r2.right) {
DWORD move = r.right - r2.right;
windowLeft -= move;
r.right -= move;
} else if (r.left < r2.left) {
DWORD move = r2.left - r.left;
windowLeft += move;
r.right += move;
}
if (r.bottom > r2.bottom) {
DWORD move = r.bottom - r2.bottom;
windowTop -= move;
r.bottom -= move;
} else if (r.top < r2.top) {
DWORD move = r2.top - r.top;
windowTop += move;
r.bottom += move;
}
}
MoveWindow(window, windowLeft, windowTop, r.right - windowLeft, r.bottom - windowTop, true);
}
WinProc::Moving();
if (d3d9Device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) {
#ifndef NDEBUG
@@ -969,9 +888,9 @@ public:
}
// copy and swap color B <> R
do {
((PALCOLOR*)pal.pBits)[b].R = destPal->R << 2;
((PALCOLOR*)pal.pBits)[b].G = destPal->G << 2;
((PALCOLOR*)pal.pBits)[b].B = destPal->B << 2;
((DirectDraw::PALCOLOR*)pal.pBits)[b].R = destPal->R << 2;
((DirectDraw::PALCOLOR*)pal.pBits)[b].G = destPal->G << 2;
((DirectDraw::PALCOLOR*)pal.pBits)[b].B = destPal->B << 2;
destPal++;
b++;
} while (--c);
@@ -1074,36 +993,23 @@ public:
HRESULT __stdcall RestoreDisplayMode() { return DD_OK; }
HRESULT __stdcall SetCooperativeLevel(HWND a, DWORD b) { // called 0x4CB005 GNW95_init_DirectDraw_
char windowTitle[128];
window = a;
WinProc::SetHWND(window);
if (!d3d9Device) {
CoInitialize(0);
ResetDevice(true); // create
}
dlog("Creating D3D9 Device window...", DL_MAIN);
if (d3d9Device) return DD_OK;
if (ResWidth != gWidth || ResHeight != gHeight) {
std::sprintf(windowTitle, "%s @sfall " VERSION_STRING " %ix%i >> %ix%i", (const char*)0x50AF08, ResWidth, ResHeight, gWidth, gHeight);
} else {
std::sprintf(windowTitle, "%s @sfall " VERSION_STRING, (const char*)0x50AF08);
}
SetWindowTextA(a, windowTitle);
CoInitialize(0);
ResetDevice(true); // create
//dlog("Creating D3D9 Device window...", DL_MAIN);
WinProc::SetTitle(gWidth, gHeight);
if (Graphics::mode >= 5) {
SetWindowLongA(a, GWL_STYLE, windowStyle);
RECT r;
r.left = 0;
r.right = gWidth;
r.top = 0;
r.bottom = gHeight;
AdjustWindowRect(&r, windowStyle, false);
r.right -= r.left;
r.bottom -= r.top;
SetWindowPos(a, HWND_NOTOPMOST, windowLeft, windowTop, r.right, r.bottom, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
long windowStyle = (Graphics::mode == 5) ? (WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU) : WS_OVERLAPPED;
WinProc::SetStyle(windowStyle);
}
dlogr(" Done", DL_MAIN);
//dlogr(" Done", DL_MAIN);
return DD_OK;
}
@@ -1161,34 +1067,10 @@ HRESULT __stdcall InitFakeDirectDrawCreate(void*, IDirectDraw** b, void*) {
else if (Graphics::GPUBlt == 2) Graphics::GPUBlt = 0; // Use CPU
if (Graphics::mode == 5) {
moveWindowKey[0] = IniReader::GetConfigInt("Input", "WindowScrollKey", 0);
if (moveWindowKey[0] < 0) {
switch (moveWindowKey[0]) {
case -1:
moveWindowKey[0] = DIK_LCONTROL;
moveWindowKey[1] = DIK_RCONTROL;
break;
case -2:
moveWindowKey[0] = DIK_LMENU;
moveWindowKey[1] = DIK_RMENU;
break;
case -3:
moveWindowKey[0] = DIK_LSHIFT;
moveWindowKey[1] = DIK_RSHIFT;
break;
default:
moveWindowKey[0] = 0;
}
} else {
moveWindowKey[0] &= 0xFF;
}
windowData = IniReader::GetConfigInt("Graphics", "WindowData", -1);
if (windowData > 0) {
windowLeft = windowData >> 16;
windowTop = windowData & 0xFFFF;
} else if (windowData == -1) {
SetWindowToCenter();
}
WinProc::SetMoveKeys();
WinProc::SetSize(gWidth, gHeight);
WinProc::LoadPosition();
}
rcpres[0] = 1.0f / (float)gWidth;
@@ -1275,39 +1157,49 @@ void __stdcall Graphics::ForceGraphicsRefresh(DWORD d) {
}
void Graphics::BackgroundClearColor(long indxColor) {
if (GPUBlt) {
D3DLOCKED_RECT buf;
mainTex->LockRect(0, &buf, 0, D3DLOCK_DISCARD);
std::memset(buf.pBits, indxColor, ResWidth * ResHeight);
mainTex->UnlockRect(0);
if (Graphics::mode >= 4) {
if (GPUBlt) {
D3DLOCKED_RECT buf;
mainTex->LockRect(0, &buf, 0, D3DLOCK_DISCARD);
std::memset(buf.pBits, indxColor, ResWidth * ResHeight);
mainTex->UnlockRect(0);
} else {
DDSURFACEDESC desc;
primarySurface->GetSurfaceDesc(&desc);
std::memset(desc.lpSurface, indxColor, ResWidth * ResHeight);
}
} else {
DDSURFACEDESC desc;
primarySurface->GetSurfaceDesc(&desc);
std::memset(desc.lpSurface, indxColor, ResWidth * ResHeight);
//
}
}
void Graphics::init() {
Graphics::mode = IniReader::GetConfigInt("Graphics", "Mode", 0);
int gMode = IniReader::GetConfigInt("Graphics", "Mode", 4);
if (gMode >= 4) Graphics::mode = gMode;
if (Graphics::mode == 6) {
windowStyle = WS_OVERLAPPED;
} else if (Graphics::mode != 4 && Graphics::mode != 5) {
//windowStyle = WS_OVERLAPPED;
} else if (Graphics::mode < 0 && Graphics::mode > 5) {
Graphics::mode = 0;
}
IsWindowMode = (mode == 5 || mode == 6);
//IsWindowMode = (mode == 2 || mode == 5 || mode == 6);
if (Graphics::mode) {
// DirectX9 mode
if (Graphics::mode >= 4) {
dlog("Applying DX9 graphics patch.", DL_INIT);
#define _DLL_NAME "d3dx9_43.dll"
HMODULE h = LoadLibraryEx(_DLL_NAME, 0, LOAD_LIBRARY_AS_DATAFILE);
if (!h) {
MessageBoxA(0, "You have selected DirectX graphics mode, but " _DLL_NAME " is missing.\n"
"Switch back to mode 0, or install an up to date version of DirectX.", "Error", MB_TASKMODAL | MB_ICONERROR);
dlogr(" Failed", DL_INIT);
MessageBoxA(0, "Switching back to DirectDraw mode.\n"
"You have selected DirectX graphics mode, but " _DLL_NAME " is missing.\n"
"Install an up to date version of DirectX 9.0c.", "Error", MB_TASKMODAL | MB_ICONERROR);
#undef _DLL_NAME
ExitProcess(-1);
} else {
FreeLibrary(h);
Graphics::mode -= 3; //ExitProcess(-1);
goto DDInit;
}
FreeLibrary(h);
SafeWrite8(0x50FB6B, '2'); // Set call DirectDrawCreate2
HookCall(0x44260C, game_init_hook);
@@ -1328,20 +1220,19 @@ void Graphics::init() {
LoadGameHook::OnGameReset() += []() {
ForceGraphicsRefresh(0); // disable refresh
};
} else {
DDInit:
if (HRP::Setting::IsEnabled()) DirectDraw::init(Graphics::mode);
}
if (HRP::Setting::IsEnabled()) HRP::MoviesScreen::SetDrawMode(Graphics::mode < 4);
WindowRender::init();
}
void Graphics::exit() {
if (Graphics::mode) {
RECT rect;
if (Graphics::mode == 5 && GetWindowRect(window, &rect)) {
int data = rect.top | (rect.left << 16);
if (data >= 0 && data != windowData) IniReader::SetConfigInt("Graphics", "WindowData", data);
}
CoUninitialize();
}
WinProc::SavePosition(Graphics::mode);
if (Graphics::mode >= 4) CoUninitialize();
}
}
+3 -4
View File
@@ -60,7 +60,6 @@ public:
static DWORD GPUBlt;
static bool IsWindowMode;
static HWND GetFalloutWindowInfo(RECT* rect);
static long GetGameWidthRes();
static long GetGameHeightRes();
@@ -90,7 +89,7 @@ public:
static __forceinline void UpdateDDSurface(BYTE* surface, int width, int height, int widthFrom, RECT* rect) {
long x = rect->left;
long y = rect->top;
if (Graphics::mode == 0) {
if (Graphics::mode < 4) { // DirecrDraw
__asm {
xor eax, eax;
push y;
@@ -99,10 +98,10 @@ public:
push width;
push eax; // yFrom
push eax; // xFrom
push eax; // heightFrom
push height; // heightFrom
push widthFrom;
push surface;
call ds:[FO_VAR_scr_blit]; // GNW95_ShowRect_(int from, int widthFrom, int heightFrom, int xFrom, int yFrom, int width, int height, int x, int y)
call ds:[FO_VAR_scr_blit]; // call GNW95_ShowRect_(int from, int widthFrom, int heightFrom, int xFrom, int yFrom, int width, int height, int x, int y)
add esp, 9*4;
}
} else {
+2 -6
View File
@@ -560,10 +560,6 @@ static __declspec(naked) void LostFocus() {
void Movies::init() {
dlog("Applying movie patch.", DL_INIT);
//if (*((DWORD*)0x00518DA0) != 0x00503300) {
// dlog("Error: The value at address 0x001073A0 is not equal to 0x00503300.", DL_INIT);
//}
// Pause and resume movie/sound playback when the game loses focus
fo::func::set_focus_func(LostFocus);
@@ -590,13 +586,13 @@ void Movies::init() {
WIP: Task
Implement subtitle output from the need to play an mve file in the background.
*/
if (Graphics::mode != 0) {
if (Graphics::mode >= 4) {
int allowDShowMovies = IniReader::GetConfigInt("Graphics", "AllowDShowMovies", 0);
if (allowDShowMovies > 0) {
Graphics::AviMovieWidthFit = (allowDShowMovies >= 2);
MakeJump(0x44E690, gmovie_play_hack);
HookCall(0x44E993, gmovie_play_hook_stop);
/* NOTE: At this address 0x487781, HRP changes the callback procedure to display mve frames. */
/* NOTE: At this address 0x487781 (movieStart_), HRP changes the callback procedure to display mve frames. */
}
}
dlogr(" Done", DL_INIT);
+2 -2
View File
@@ -69,7 +69,7 @@ void __stdcall SetShaderMode(DWORD d, DWORD mode) {
}
int __stdcall LoadShader(const char* file) {
if (!Graphics::mode || strstr(file, "..") || strstr(file, ":")) return -1;
if (Graphics::mode < 4 || strstr(file, "..") || strstr(file, ":")) return -1;
char buf[MAX_PATH];
sprintf_s(buf, "%s\\shaders\\%s", fo::var::master_db_handle->path, file); // fo::var::patches
for (DWORD d = 0; d < shadersSize; d++) {
@@ -220,7 +220,7 @@ void ScriptShaders::Release() {
}
void ScriptShaders::init() {
if (Graphics::mode) {
if (Graphics::mode >= 4) {
for each (const auto& shaderFile in IniReader::GetConfigList("Graphics", "GlobalShaderFile", "", 1024)) {
if (shaderFile.length() > 3) gShaderFiles.push_back(GlobalShader(shaderFile));
}
+2 -2
View File
@@ -157,7 +157,7 @@ LRESULT CALLBACK SoundWndProc(HWND wnd, UINT msg, WPARAM w, LPARAM l) {
static void CreateSndWnd() {
dlog("Creating sfall sound callback window.", DL_INIT);
if (Graphics::mode == 0) CoInitialize(0);
if (Graphics::mode < 4) CoInitialize(0);
WNDCLASSEX wcx;
std::memset(&wcx, 0, sizeof(wcx));
@@ -1068,7 +1068,7 @@ void Sound::init() {
}
void Sound::exit() {
if (soundwindow && Graphics::mode == 0) CoUninitialize();
if (soundwindow && Graphics::mode < 4) CoUninitialize();
}
}
+300
View File
@@ -0,0 +1,300 @@
/*
* sfall
* Copyright (C) 2008-2021 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 <http://www.gnu.org/licenses/>.
*/
#pragma comment(lib, "ddraw.lib")
#include <ddraw.h>
#include "..\..\main.h"
#include "..\..\FalloutEngine\Fallout2.h"
#include "..\..\WinProc.h"
#include "..\..\HRP\Init.h"
#include "DirectDraw.h"
namespace sfall
{
static HWND window;
static DWORD mode;
static bool windowedMode;
static IDirectDraw* ddObject; // same as _GNW95_DDObject
static IDirectDrawSurface* ddPrimarySurface;
static IDirectDrawSurface* ddBackSurface;
static IDirectDrawPalette* ddPalette;
static IDirectDrawClipper* ddClipper;
static DirectDraw::PALCOLOR* paletteRGB;
//class ConvertPalette {
DWORD PaletteToRGB24(BYTE r, BYTE g, BYTE b) {
return (r << 16) | (g << 8) | b;
}
// R5G5B5
DWORD PaletteToRGB15(BYTE r, BYTE g, BYTE b) {
DWORD color = r / 8;
color <<= 5;
color |= (g / 8);
color <<= 5;
return color | (b / 8);
}
// R5G6B5
DWORD PaletteToRGB16(BYTE r, BYTE g, BYTE b) {
DWORD color = r / 8;
color <<= 6;
color |= (g / 4);
color <<= 5;
return color | (b / 8);
}
void CopyPaletteSurface16bit() {
}
//};
//static void CopyPaletteSurfaceFunc;
//static void ConvertPaletteFunc;
void SetWindow() {
WinProc::SetHWND(window);
WinProc::SetSize(HRP::Setting::ScreenWidth(), HRP::Setting::ScreenHeight());
WinProc::SetTitle(HRP::Setting::ScreenWidth(), HRP::Setting::ScreenHeight());
if (mode == 2) WinProc::LoadPosition();
if (windowedMode) {
DWORD windowStyle = (mode == 3) ? WS_OVERLAPPED : (WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU);
WinProc::SetStyle(windowStyle);
}
}
static long __stdcall DirectDrawInit(DWORD, IDirectDraw* _ddObject, DWORD) {
window = (HWND)fo::var::getInt(FO_VAR_GNW95_hwnd);
SetWindow();
HRESULT hr = DirectDrawCreate(0, &_ddObject, 0);
if (FAILED(hr)) return -1;
ddObject = _ddObject;
hr = ddObject->SetCooperativeLevel(window, (windowedMode) ? DDSCL_NORMAL : DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_MULTITHREADED);
if (FAILED(hr)) return -1;
if (!windowedMode) {
hr = ddObject->SetDisplayMode(HRP::Setting::ScreenWidth(), HRP::Setting::ScreenHeight(), 32);
if (FAILED(hr)) return -1;
}
DDSURFACEDESC ddsd;
std::memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hr = ddObject->CreateSurface(&ddsd, &ddPrimarySurface, 0);
if (FAILED(hr)) return -1;
std::memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddPrimarySurface->GetSurfaceDesc(&ddsd);
if (ddsd.ddpfPixelFormat.dwRGBBitCount != 32) {
MessageBoxA(window, "The current video mode (not TrueColor) is not supported.", "DirectDraw", 0);
return -1;
}
fo::var::setInt(0x51E2B4) = (DWORD)ddPrimarySurface; //FO_VAR_GNW95_DDPrimarySurface
fo::var::setInt(0x51E2B8) = (DWORD)ddPrimarySurface; //FO_VAR_GNW95_DDRestoreSurface
// Create DirectDraw clipper for windowed mode
if (windowedMode) {
ddObject->CreateClipper(0, &ddClipper, 0);
ddClipper->SetHWnd(0, window);
hr = ddPrimarySurface->SetClipper(ddClipper);
if (FAILED(hr)) return -1;
}
// Create the backbuffer surface
std::memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; // | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; // | DDSCAPS_SYSTEMMEMORY
ddsd.dwWidth = HRP::Setting::ScreenWidth() + 1;
ddsd.dwHeight = HRP::Setting::ScreenHeight() + 1;
//ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
//ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8;
//ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
hr = ddObject->CreateSurface(&ddsd, &ddBackSurface, 0);
if (FAILED(hr)) return -1;
std::memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddBackSurface->GetSurfaceDesc(&ddsd);
// set greyscale (delete)
for (size_t i = 0; i < 256; i++) {
paletteRGB[i].xRGB = (i << 16) | (i << 8) | i;
}
hr = ddObject->CreatePalette(DDPCAPS_ALLOW256 | DDPCAPS_8BIT, (PALETTEENTRY*)paletteRGB, &ddPalette, 0);
if (FAILED(hr)) return -1;
fo::var::setInt(0x51E2BC) = (DWORD)ddPalette; // FO_VAR_GNW95_DDPrimaryPalette
return 0;
}
void BufToBuf_32bit(BYTE* src, int width, int height, DWORD* dst, int pitch) {
while (height--) {
int x = width;
while (x--) dst[x] = paletteRGB[src[x]].xRGB;
src += width;
dst += pitch;
};
}
static void __cdecl GNW95_ShowRect(BYTE* srcSurface, int sWidth, int sHeight, int sX, int sY, int width, int height, int x, int y) {
WinProc::Moving();
if (sHeight > 0 && sWidth > 0 && fo::var::getInt(FO_VAR_GNW95_isActive)) {
DDSURFACEDESC desc;
std::memset(&desc, 0, sizeof(DDSURFACEDESC));
desc.dwSize = sizeof(DDSURFACEDESC);
while (true) {
HRESULT hr = ddBackSurface->Lock(0, &desc, DDLOCK_WAIT, 0);
if (!hr) break;
// 0x887601C2
if (hr != DDERR_SURFACELOST || ddBackSurface->Restore()) return;
}
int pitch = desc.lPitch / 4;
DWORD* dst = (DWORD*)desc.lpSurface;
dst += (x + (y * pitch));
BYTE* src = srcSurface;
src += sX + (sY * sWidth);
BufToBuf_32bit(src, sWidth, sHeight, dst, pitch);
ddBackSurface->Unlock(desc.lpSurface);
RECT backRect;
backRect.left = x;
backRect.top = y;
backRect.right = x + width;
backRect.bottom = y + height;
POINT point;
point.x = 0;
point.y = 0;
if (mode == 2) ClientToScreen(window, &point);
RECT primRect;
primRect.left = point.x + x;
primRect.top = point.y + y;
primRect.right = point.x + x + width;
primRect.bottom = point.y + y + height;
// Draw
while (ddPrimarySurface->Blt(&primRect, ddBackSurface, &backRect, DDBLT_WAIT, 0) == DDERR_SURFACELOST) ddPrimarySurface->Restore();
}
}
static void __fastcall SetPalette(fo::PALETTE* pal, long start, long count) {
// copy and swap color B <> R
while (count--) {
paletteRGB[start++].xRGB = PaletteToRGB24(pal->B << 2, pal->G << 2, pal->R << 2);
pal++;
};
//ddPalette->SetEntries(0, start, count, (PALETTEENTRY*)paletteRGB);
}
static __declspec(naked) void GNW95_SetPaletteEntries_hack_replacement() {
__asm {
push ebx;
mov ecx, eax;
call SetPalette;
test ebx, ebx;
jz skip;
// update
mov eax, FO_VAR_scr_size;
call fo::funcoffs::win_refresh_all_;
skip:
pop ecx;
retn;
}
}
static __declspec(naked) void GNW95_SetPalette_hack_replacement() {
__asm {
push ecx;
push edx;
mov ecx, eax;
xor edx, edx;
push 256;
call SetPalette;
// update
mov eax, FO_VAR_scr_size;
call fo::funcoffs::win_refresh_all_;
pop edx;
pop ecx;
retn;
}
}
static IDirectDraw* GNW95_reset_mode_hack() {
ddBackSurface->Release();
if (ddClipper) {
ddClipper->Release();
ddClipper = nullptr;
}
ddPrimarySurface = nullptr;
ddPalette = nullptr;
ddBackSurface = nullptr;
return ddObject;
}
void DirectDraw::init(long gMode) {
mode = gMode;
windowedMode = (gMode == 2 || gMode == 3);
if (gMode == 2) WinProc::SetMoveKeys();
paletteRGB = new DirectDraw::PALCOLOR[256];
// GNW95_init_DirectDraw_
MakeCall(0x4CAFE6, DirectDrawInit, 1); // GNW95_init_DirectDraw_
SafeWrite8(0x4CAFEE, CodeType::Jump);
SafeWrite32(0x4CAFEF, 433); // jmp 0x4CB1A4
// GNW95_init_mode_ex_
SafeWrite32(0x4CAE72, (DWORD)&GNW95_ShowRect); // replace engine GNW95_ShowRect_ with sfall function
MakeJump(fo::funcoffs::GNW95_SetPaletteEntries_ + 1, GNW95_SetPaletteEntries_hack_replacement); // 0x4CB310
MakeJump(fo::funcoffs::GNW95_SetPalette_, GNW95_SetPalette_hack_replacement); // 0x4CB568
MakeCall(0x4CB1FD, GNW95_reset_mode_hack);
}
}
+43
View File
@@ -0,0 +1,43 @@
/*
* sfall
* Copyright (C) 2008-2021 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace sfall
{
class DirectDraw {
public:
static void init(long);
#pragma pack(push, 1)
struct PALCOLOR {
union {
DWORD xRGB;
struct {
BYTE R;
BYTE G;
BYTE B;
BYTE x;
};
};
};
#pragma pack(pop)
};
}
+1 -1
View File
@@ -291,7 +291,7 @@ void TalkingHeads::init() {
// Disable centering the screen if NPC has talking head
HookCall(0x445224, gdialogInitFromScript_hook);
if (Graphics::mode && IniReader::GetConfigInt("Graphics", "Use32BitHeadGraphics", 0)) {
if (Graphics::mode >= 4 && IniReader::GetConfigInt("Graphics", "Use32BitHeadGraphics", 0)) {
LoadGameHook::OnAfterGameInit() += TalkingHeadsInit;
}
}
+152 -2
View File
@@ -7,27 +7,44 @@
#include "main.h"
#include "FalloutEngine\Fallout2.h"
#include "InputFuncs.h"
#include "version.h"
#include "WinProc.h"
namespace sfall
{
static HWND window;
static Rectangle win;
static long moveWindowKey[2];
static long windowData;
static long reqGameQuit;
static bool cCursorShow = true;
static bool bkgndErased = false;
static int __stdcall WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
RECT rect;
//POINT point;
switch (msg) {
//case WM_CREATE:
// break;
case WM_DESTROY:
__asm xor eax, eax;
__asm call fo::funcoffs::exit_;
case WM_ERASEBKGND:
return 1;
case WM_ERASEBKGND:
if (bkgndErased || !window) return 1;
bkgndErased = true;
break;
case WM_PAINT:
if (GetUpdateRect(hWnd, &rect, 0) == 1) {
if (GetUpdateRect(hWnd, &rect, 0) != 0) {
rect.right -= 1;
rect.bottom -= 1;
__asm {
@@ -112,8 +129,141 @@ void WinProc::SetWindowProc() {
SetWindowLongA((HWND)fo::var::getInt(FO_VAR_GNW95_hwnd), GWL_WNDPROC, (LONG)WindowProc);
}
void WinProc::SetHWND(HWND _window) {
window = _window;
}
void WinProc::SetSize(long w, long h) {
win.x = 0;
win.x = 0;
win.width = w;
win.height = h;
}
// Sets the window style and its position
void WinProc::SetStyle(long windowStyle) {
SetWindowLongA(window, GWL_STYLE, windowStyle);
RECT r;
r.left = 0;
r.right = win.width;
r.top = 0;
r.bottom = win.height;
AdjustWindowRect(&r, windowStyle, false);
r.right -= r.left;
r.bottom -= r.top;
SetWindowPos(window, HWND_NOTOPMOST, win.x, win.y, r.right, r.bottom, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
}
void WinProc::SetTitle(long wWidth, long wHeight) {
char windowTitle[128];
if (HRP::Setting::ScreenWidth() != wWidth || HRP::Setting::ScreenHeight() != wHeight) {
std::sprintf(windowTitle, "%s @sfall " VERSION_STRING " %ix%i >> %ix%i", (const char*)0x50AF08, HRP::Setting::ScreenWidth(), HRP::Setting::ScreenHeight(), wWidth, wHeight);
} else {
std::sprintf(windowTitle, "%s @sfall " VERSION_STRING, (const char*)0x50AF08);
}
SetWindowTextA(window, windowTitle);
}
void WinProc::SetMoveKeys() {
moveWindowKey[0] = IniReader::GetConfigInt("Input", "WindowScrollKey", 0);
if (moveWindowKey[0] < 0) {
switch (moveWindowKey[0]) {
case -1:
moveWindowKey[0] = DIK_LCONTROL;
moveWindowKey[1] = DIK_RCONTROL;
break;
case -2:
moveWindowKey[0] = DIK_LMENU;
moveWindowKey[1] = DIK_RMENU;
break;
case -3:
moveWindowKey[0] = DIK_LSHIFT;
moveWindowKey[1] = DIK_RSHIFT;
break;
default:
moveWindowKey[0] = 0;
}
} else {
moveWindowKey[0] &= 0xFF;
}
}
void WinProc::Moving() {
if ((moveWindowKey[0] != 0 && KeyDown(moveWindowKey[0])) ||
(moveWindowKey[1] != 0 && KeyDown(moveWindowKey[1])))
{
int winX, winY;
GetMouse(&winX, &winY);
win.x += winX;
win.y += winY;
RECT r, r2;
r.left = win.x;
r.right = win.x + win.width;
r.top = win.y;
r.bottom = win.y + win.height;
AdjustWindowRect(&r, WS_CAPTION, false);
r.right -= (r.left - win.x);
r.left = win.x;
r.bottom -= (r.top - win.y);
r.top = win.y;
if (GetWindowRect(GetShellWindow(), &r2)) {
if (r.right > r2.right) {
DWORD move = r.right - r2.right;
win.x -= move;
r.right -= move;
} else if (r.left < r2.left) {
DWORD move = r2.left - r.left;
win.x += move;
r.right += move;
}
if (r.bottom > r2.bottom) {
DWORD move = r.bottom - r2.bottom;
win.y -= move;
r.bottom -= move;
} else if (r.top < r2.top) {
DWORD move = r2.top - r.top;
win.y += move;
r.bottom += move;
}
}
MoveWindow(window, win.x, win.y, r.right - win.x, r.bottom - win.y, true);
}
}
void WinProc::SetToCenter(long wWidth, long wHeight, long* outX, long* outY) {
RECT desktop;
GetWindowRect(GetDesktopWindow(), &desktop);
*outX = (desktop.right / 2) - (wWidth / 2);
*outY = (desktop.bottom / 2) - (wHeight / 2);
}
void WinProc::LoadPosition() {
windowData = IniReader::GetConfigInt("Graphics", "WindowData", -1);
if (windowData > 0) {
win.x = windowData >> 16;
win.y = windowData & 0xFFFF;
} else if (windowData == -1) {
WinProc::SetToCenter(win.width, win.height, &win.x, &win.y);
}
}
void WinProc::SavePosition(long mode) {
RECT rect;
if ((mode == 2 || mode == 5) && GetWindowRect(window, &rect)) {
int data = rect.top | (rect.left << 16);
if (data >= 0 && data != windowData) IniReader::SetConfigInt("Graphics", "WindowData", data);
}
}
void WinProc::init() {
// Replace the engine WindowProc_ with sfall one
MakeJump(0x4DE9FC, WindowProc); // WindowProc_
HookCall(0x481B2A, main_menu_loop_hook);
//SafeWrite8(0x4DEB0D, 1); // for test
+14
View File
@@ -14,6 +14,20 @@ public:
static void init();
static void SetWindowProc();
static void SetHWND(HWND _window);
static void SetSize(long w, long h);
static void SetTitle(long gWidth, long gHeight);
//Sets the window style and its position
static void SetStyle(long windowStyle);
static void SetMoveKeys();
static void Moving();
static void SetToCenter(long wWidth, long wHeight, long* outX, long* outY);
static void LoadPosition();
static void SavePosition(long mode);
};
}
+9 -5
View File
@@ -20,12 +20,16 @@
extern ddrawDll ddraw;
typedef HRESULT (__stdcall *DDrawCreateProc)(void* a, void* b, void* c);
//typedef HRESULT (__stdcall *DDrawCreateProc)(DWORD a, IDirectDraw* b, DWORD c);
HRESULT __stdcall FakeDirectDrawCreate(void* a, void* b, void* c) {
DDrawCreateProc proc = (DDrawCreateProc)ddraw.DirectDrawCreate;
if (!proc) return -1;
return proc(a, b, c);
//HRESULT __stdcall FakeDirectDrawCreate(DWORD a, IDirectDraw* b, DWORD c) {
// DDrawCreateProc proc = (DDrawCreateProc)ddraw.DirectDrawCreate;
// if (!proc) return -1;
// return proc(a, b, c);
//}
__declspec(naked) void FakeDirectDrawCreate() {
__asm jmp [ddraw.DirectDrawCreate];
}
__declspec(naked) void FakeAcquireDDThreadLock() {
+2
View File
@@ -359,6 +359,7 @@
<ClInclude Include="Modules\Scripting\Handlers\Math.h" />
<ClInclude Include="Modules\SpeedPatch.h" />
<ClInclude Include="Modules\SubModules\CombatBlock.h" />
<ClInclude Include="Modules\SubModules\DirectDraw.h" />
<ClInclude Include="Modules\SubModules\EnginePerks.h" />
<ClInclude Include="Modules\SubModules\ObjectName.h" />
<ClInclude Include="Modules\SubModules\WindowRender.h" />
@@ -495,6 +496,7 @@
<ClCompile Include="Modules\Scripting\Handlers\Math.cpp" />
<ClCompile Include="Modules\SpeedPatch.cpp" />
<ClCompile Include="Modules\SubModules\CombatBlock.cpp" />
<ClCompile Include="Modules\SubModules\DirectDraw.cpp" />
<ClCompile Include="Modules\SubModules\EnginePerks.cpp" />
<ClCompile Include="Modules\SubModules\ObjectName.cpp" />
<ClCompile Include="Modules\SubModules\WindowRender.cpp" />
+6
View File
@@ -434,6 +434,9 @@
<ClInclude Include="HRP\MoviesScreen.h">
<Filter>HRP</Filter>
</ClInclude>
<ClInclude Include="Modules\SubModules\DirectDraw.h">
<Filter>Modules\SubModules</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
@@ -803,6 +806,9 @@
<ClCompile Include="HRP\MoviesScreen.cpp">
<Filter>HRP</Filter>
</ClCompile>
<ClCompile Include="Modules\SubModules\DirectDraw.cpp">
<Filter>Modules\SubModules</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />