mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Added DeathScreen.cpp/h and SlidesScreen.cpp/h
Added optimization for the save/load game screens.
This commit is contained in:
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2016 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/>.
|
||||
*/
|
||||
* sfall
|
||||
* Copyright (C) 2008-2016 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/>.
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -389,6 +389,7 @@ long wmGetCurrentTerrainType() {
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// TODO: Review SurfaceCopyToMem/DrawToSurface functions
|
||||
// copy the area from the interface buffer to the data array
|
||||
void SurfaceCopyToMem(long fromX, long fromY, long width, long height, long fromWidth, BYTE* fromSurface, BYTE* toMem) {
|
||||
fromSurface += fromY * fromWidth + fromX;
|
||||
@@ -448,10 +449,10 @@ void DrawToSurface(long width, long height, long fromX, long fromY, long fromWid
|
||||
}
|
||||
}
|
||||
|
||||
//void TranslucentDarkFill(BYTE* surface, long x, long y, long width, long height, long surfWidth) {
|
||||
// BYTE* surf = surface + (y * surfWidth) + x;
|
||||
// fo::func::wmInterfaceDrawSubTileRectFogged(surf, width, height, surfWidth);
|
||||
//}
|
||||
void TranslucentDarkFill(BYTE* surface, long x, long y, long width, long height, long surfWidth) {
|
||||
BYTE* surf = surface + (y * surfWidth) + x;
|
||||
fo::func::wmInterfaceDrawSubTileRectFogged(surf, width, height, surfWidth);
|
||||
}
|
||||
|
||||
// Fills the specified interface window with index color
|
||||
bool WinFillRect(long winID, long x, long y, long width, long height, BYTE indexColor) {
|
||||
@@ -475,6 +476,14 @@ bool WinFillRect(long winID, long x, long y, long width, long height, BYTE index
|
||||
return result;
|
||||
}
|
||||
|
||||
void FillRect(BYTE* surface, long x, long y, long width, long height, long wPitch, BYTE indexColor) {
|
||||
surface += (wPitch * y) + x;
|
||||
while (height--) {
|
||||
std::memset(surface, indexColor, width);
|
||||
surface += wPitch;
|
||||
};
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2016 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/>.
|
||||
*/
|
||||
* sfall
|
||||
* Copyright (C) 2008-2016 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
|
||||
|
||||
@@ -142,9 +142,13 @@ void DrawToSurface(long width, long height, long fromX, long fromY, long fromWid
|
||||
|
||||
void DrawToSurface(long width, long height, long fromX, long fromY, long fromWidth, BYTE* fromSurf, long toX, long toY, long toWidth, long toHeight, BYTE* toSurf);
|
||||
|
||||
void TranslucentDarkFill(BYTE* surface, long x, long y, long width, long height, long surfWidth);
|
||||
|
||||
// Fills the specified interface window with index color
|
||||
bool WinFillRect(long winID, long x, long y, long width, long height, BYTE indexColor);
|
||||
|
||||
void FillRect(BYTE* surface, long x, long y, long width, long height, long wPitch, BYTE indexColor);
|
||||
|
||||
// Fills the specified interface window with index color 0 (black color)
|
||||
void ClearWindow(long winID, bool refresh = true);
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ WRAP_WATCOM_FUNC1(long, critterIsOverloaded, fo::GameObject*, critter)
|
||||
WRAP_WATCOM_FUNC1(void, display_print, const char*, msg) // Displays message in main UI console window
|
||||
WRAP_WATCOM_FUNC0(void, display_stats)
|
||||
WRAP_WATCOM_FUNC1(long, critter_kill_count_type, fo::GameObject*, critter)
|
||||
WRAP_WATCOM_FUNC2(void, endgame_load_palette, long, artType, long, fid)
|
||||
WRAP_WATCOM_FUNC1(void, EndLoad, fo::DbFile*, file)
|
||||
// Execute script proc by internal proc number (from script's proc table, basically a sequential number of a procedure as defined in code, starting from 1)
|
||||
WRAP_WATCOM_FUNC2(void, executeProcedure, fo::Program*, sptr, long, procNum)
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
#define FO_VAR_endgame_subtitle_done 0x570BD0
|
||||
#define FO_VAR_endgame_subtitle_characters 0x51866C
|
||||
#define FO_VAR_endgame_voiceover_loaded 0x570AB8
|
||||
#define FO_VAR_endgame_window_buffer 0x570BF0
|
||||
#define FO_VAR_endWindowRect 0x518FA0
|
||||
#define FO_VAR_Experience_pc 0x6681B4
|
||||
#define FO_VAR_fade_steps 0x6642D0
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#include "..\main.h"
|
||||
#include "..\FalloutEngine\Fallout2.h"
|
||||
|
||||
#include "Image.h"
|
||||
|
||||
#include "DeathScreen.h"
|
||||
|
||||
namespace HRP
|
||||
{
|
||||
|
||||
namespace sf = sfall;
|
||||
|
||||
// 0 - background image will display at its original size
|
||||
// 1 - background image will stretch to fit the screen while maintaining its aspect ratio
|
||||
// 2 - background image will stretch to fill the screen
|
||||
long DeathScreen::DEATH_SCRN_SIZE;
|
||||
|
||||
static long __fastcall main_death_scene_hook_win_add(long height, long y, long color, long flags) {
|
||||
__asm mov eax, 0x50AF9C; // art\intrface\death.pal
|
||||
__asm call fo::funcoffs::loadColorTable_;
|
||||
|
||||
color = Image::GetDarkColor((fo::PALETTE*)FO_VAR_cmap);
|
||||
return fo::func::win_add(0, 0, Setting::ScreenWidth(), Setting::ScreenHeight(), color, flags);
|
||||
}
|
||||
|
||||
static BYTE* winSurface;
|
||||
static long yPosition; // bottom position
|
||||
|
||||
static void __cdecl main_death_scene_hook_buf_to_buf(fo::FrmData* frm, long w, long h, long srcW, BYTE* dst, long dstW) {
|
||||
winSurface = dst;
|
||||
|
||||
long width = frm->frame.width;
|
||||
long height = frm->frame.height;
|
||||
|
||||
w = Setting::ScreenWidth();
|
||||
h = Setting::ScreenHeight();
|
||||
|
||||
if (DeathScreen::DEATH_SCRN_SIZE || width > w || height > h) {
|
||||
if (DeathScreen::DEATH_SCRN_SIZE == 1) {
|
||||
long x = Image::GetAspectSize(w, h, (float)width, (float)height);
|
||||
long y = 0;
|
||||
if (x >= w) { // extract x/y image position
|
||||
y = x / w;
|
||||
x -= y * w;
|
||||
}
|
||||
if (x || y) {
|
||||
dst += x + (y * Setting::ScreenWidth());
|
||||
}
|
||||
}
|
||||
yPosition = h;
|
||||
Image::Scale(frm->frame.data, width, height, dst, w, h, Setting::ScreenWidth());
|
||||
return;
|
||||
}
|
||||
yPosition = height;
|
||||
|
||||
long y = (h - height) / 2;
|
||||
long x = (w - width) / 2;
|
||||
if (x || y) {
|
||||
yPosition += y;
|
||||
dst += x + (y * Setting::ScreenWidth());
|
||||
}
|
||||
fo::func::buf_to_buf(frm->frame.data, width, height, width, dst, Setting::ScreenWidth());
|
||||
}
|
||||
|
||||
// Darkens a rectangle area for printing text
|
||||
static BYTE* __fastcall DarkRectangle(long totalLines, long w) { // w:564
|
||||
long tHeight = fo::util::GetTextHeight();
|
||||
long y = (Setting::ScreenHeight() - (totalLines * tHeight) - 20);
|
||||
long x = (Setting::ScreenWidth() / 2) - (560 / 2);
|
||||
|
||||
if (y <= yPosition) {
|
||||
fo::util::TranslucentDarkFill(winSurface, x - 4, y - 5, w, (totalLines * (tHeight + 2)) + 6, Setting::ScreenWidth());
|
||||
}
|
||||
long yOffset = Setting::ScreenWidth() * y;
|
||||
return winSurface + x + yOffset; // text print offset
|
||||
}
|
||||
|
||||
static void __declspec(naked) main_death_scene_hook_buf_fill() {
|
||||
__asm {
|
||||
mov ecx, [esp + 0x2B4 - 0x1C + 4]; // totalLines
|
||||
call DarkRectangle;
|
||||
mov esi, eax;
|
||||
retn 4;
|
||||
}
|
||||
}
|
||||
|
||||
void DeathScreen::init() {
|
||||
sf::HookCall(0x4811E1, main_death_scene_hook_win_add);
|
||||
sf::HookCall(0x481269, main_death_scene_hook_buf_to_buf);
|
||||
sf::HookCall(0x481353, main_death_scene_hook_buf_fill);
|
||||
|
||||
// main_death_scene_
|
||||
sf::SafeWrite32(0x48135D, Setting::ScreenWidth()); // ToWidth
|
||||
sf::SafeWrite32(0x48138E, Setting::ScreenWidth()); // imul
|
||||
|
||||
// main_death_scene_
|
||||
sf::HookCall(0x481225, (void*)fo::funcoffs::art_ptr_lock_); // replace art_ptr_lock_data_ with art_ptr_lock_
|
||||
sf::SafeWrite16(0x481223, 0xCA89); // mov edx, ecx
|
||||
|
||||
// block loadColorTable_
|
||||
sf::BlockCall(0x4813C1); // main_death_scene_
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace HRP
|
||||
{
|
||||
|
||||
class DeathScreen {
|
||||
public:
|
||||
static void init();
|
||||
|
||||
static long DEATH_SCRN_SIZE;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -36,8 +36,8 @@ static void __cdecl game_help_hook_buf_to_buf(fo::FrmData* frm, long w, long h,
|
||||
w = Setting::ScreenWidth();
|
||||
h = Setting::ScreenHeight();
|
||||
|
||||
if (HelpScreen::HELP_SCRN_SIZE) {
|
||||
if (HelpScreen::HELP_SCRN_SIZE == 1 || width > w || height > h) {
|
||||
if (HelpScreen::HELP_SCRN_SIZE || width > w || height > h) {
|
||||
if (HelpScreen::HELP_SCRN_SIZE == 1) {
|
||||
long x = Image::GetAspectSize(w, h, (float)width, (float)height);
|
||||
long y = 0;
|
||||
if (x >= w) { // extract x/y image position
|
||||
@@ -62,8 +62,9 @@ void HelpScreen::init() {
|
||||
sf::HookCall(0x44401D, game_help_hook_buf_to_buf);
|
||||
|
||||
// game_help_
|
||||
sf::HookCall(0x443FEE, (void*)fo::funcoffs::art_ptr_lock_); // replace art_ptr_lock_data_ to art_ptr_lock_
|
||||
sf::HookCall(0x443FEE, (void*)fo::funcoffs::art_ptr_lock_); // replace art_ptr_lock_data_ with art_ptr_lock_
|
||||
sf::SafeWrite16(0x443FEC, 0xCA89); // mov edx, ecx
|
||||
|
||||
// game_help_
|
||||
sf::BlockCall(0x444039); // block loadColorTable_
|
||||
}
|
||||
|
||||
+14
-9
@@ -45,7 +45,7 @@ long Image::GetAspectSize(long &dW, long &dH, float sW, float sH) {
|
||||
}
|
||||
|
||||
// Resizes src image to dWidth/dHeight size
|
||||
void Image::Scale(BYTE* src, long sWidth, long sHeight, BYTE* dst, long dWidth, long dHeight, long dPitch) {
|
||||
void Image::Scale(BYTE* src, long sWidth, long sHeight, BYTE* dst, long dWidth, long dHeight, long dPitch, long sPitch) {
|
||||
if (dWidth <= 0 || dHeight <= 0) return;
|
||||
|
||||
float sw = (float)sWidth;
|
||||
@@ -53,25 +53,30 @@ void Image::Scale(BYTE* src, long sWidth, long sHeight, BYTE* dst, long dWidth,
|
||||
float xStep = sw / dWidth;
|
||||
float hStep = sh / dHeight;
|
||||
|
||||
if (sPitch > 0) sWidth = sPitch;
|
||||
if (dPitch > 0) dPitch -= dWidth;
|
||||
|
||||
float sy = 0.0f;
|
||||
do {
|
||||
float sx = 0.0f;
|
||||
int w = dWidth;
|
||||
int x = 0, w = dWidth;
|
||||
do {
|
||||
*dst++ = *(src + std::lround(sx)); // copy pixel
|
||||
sx += xStep;
|
||||
if (sx >= sw) sx = sw - 1.0f;
|
||||
*dst++ = *(src + x); // copy pixel
|
||||
if (x < sw) {
|
||||
sx += xStep;
|
||||
if (sx >= 1.0f) {
|
||||
x += (int)sx;
|
||||
sx -= (int)sx;
|
||||
}
|
||||
}
|
||||
} while (--w);
|
||||
dst += dPitch;
|
||||
|
||||
if (sHeight) {
|
||||
sy += hStep;
|
||||
float y = std::round(sy);
|
||||
if (y >= 1.0f && --sHeight) {
|
||||
src += sWidth * (int)y;
|
||||
sy -= y;
|
||||
if (sy >= 1.0f && --sHeight) {
|
||||
src += (sWidth * (int)sy);
|
||||
sy -= (int)sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ public:
|
||||
|
||||
static long GetAspectSize(long &dW, long &dH, float sW, float sH);
|
||||
|
||||
static void Scale(BYTE* src, long sWight, long sHeight, BYTE* dst, long dWight, long dHeight, long dPitch = 0);
|
||||
static void Scale(BYTE* src, long sWight, long sHeight, BYTE* dst, long dWight, long dHeight, long dPitch = 0, long sPitch = 0);
|
||||
static void TransScale(BYTE* src, long sWight, long sHeight, BYTE* dst, long dWight, long dHeight, long dPitch, long tranColorIdx);
|
||||
static void ScaleText(BYTE* dst, const char* text, long txtWidth, long dstWidth, long colorFlags, float scaleFactor);
|
||||
};
|
||||
|
||||
+6
-2
@@ -22,6 +22,8 @@
|
||||
#include "MiscInterface.h"
|
||||
#include "Worldmap.h"
|
||||
#include "HelpScreen.h"
|
||||
#include "DeathScreen.h"
|
||||
#include "SlidesScreen.h"
|
||||
|
||||
#include "Init.h"
|
||||
|
||||
@@ -174,8 +176,8 @@ void Setting::init() {
|
||||
|
||||
SplashScreen::SPLASH_SCRN_SIZE = sf::IniReader::GetInt("STATIC_SCREENS", "SPLASH_SCRN_SIZE", 1, f2ResIni);
|
||||
HelpScreen::HELP_SCRN_SIZE = sf::IniReader::GetInt("STATIC_SCREENS", "HELP_SCRN_SIZE", 0, f2ResIni);
|
||||
//DEATH_SCRN_SIZE
|
||||
//END_SLIDE_SIZE
|
||||
DeathScreen::DEATH_SCRN_SIZE = sf::IniReader::GetInt("STATIC_SCREENS", "DEATH_SCRN_SIZE", 1, f2ResIni);
|
||||
SlidesScreen::END_SLIDE_SIZE = sf::IniReader::GetInt("STATIC_SCREENS", "END_SLIDE_SIZE", 1, f2ResIni);
|
||||
|
||||
std::string x = sf::trim(sf::IniReader::GetString("MAPS", "SCROLL_DIST_X", "480", 16, f2ResIni));
|
||||
std::string y = sf::trim(sf::IniReader::GetString("MAPS", "SCROLL_DIST_Y", "400", 16, f2ResIni));
|
||||
@@ -241,6 +243,8 @@ void Setting::init() {
|
||||
LoadSave::init();
|
||||
MiscInterface::init();
|
||||
HelpScreen::init();
|
||||
DeathScreen::init();
|
||||
SlidesScreen::init();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#include "..\main.h"
|
||||
#include "..\FalloutEngine\Fallout2.h"
|
||||
|
||||
#include "Image.h"
|
||||
|
||||
#include "SlidesScreen.h"
|
||||
|
||||
namespace HRP
|
||||
{
|
||||
|
||||
namespace sf = sfall;
|
||||
|
||||
// 0 - background image will display at its original size
|
||||
// 1 - background image will stretch to fit the screen while maintaining its aspect ratio
|
||||
// 2 - background image will stretch to fill the screen
|
||||
long SlidesScreen::END_SLIDE_SIZE;
|
||||
|
||||
static fo::FrmData* frmArt;
|
||||
static long artID;
|
||||
static long color = -1;
|
||||
static long textLine;
|
||||
static long bottomPos;
|
||||
static long panDesert;
|
||||
|
||||
static void __declspec(naked) endgame_display_image_hook_art_frame_data() {
|
||||
__asm {
|
||||
mov panDesert, 0;
|
||||
mov color, -1;
|
||||
mov artID, esi;
|
||||
mov frmArt, eax;
|
||||
jmp fo::funcoffs::art_frame_data_;
|
||||
}
|
||||
}
|
||||
|
||||
static void __cdecl endgame_display_image_hook_buf_to_buf(BYTE* src, long w, long h, long srcW, BYTE* dst, long dstW) {
|
||||
textLine = 0;
|
||||
long width = frmArt->frame.width;
|
||||
long height = frmArt->frame.height;
|
||||
|
||||
w = Setting::ScreenWidth();
|
||||
h = Setting::ScreenHeight();
|
||||
|
||||
if (color == -1) {
|
||||
fo::func::endgame_load_palette(fo::ArtType::OBJ_TYPE_INTRFACE, artID & 0xFFF);
|
||||
color = Image::GetDarkColor((fo::PALETTE*)FO_VAR_cmap);
|
||||
}
|
||||
if (SlidesScreen::END_SLIDE_SIZE != 2) std::memset(dst, color, w * h);
|
||||
|
||||
if (SlidesScreen::END_SLIDE_SIZE || width > w || height > h) {
|
||||
if (SlidesScreen::END_SLIDE_SIZE == 1) {
|
||||
long x = Image::GetAspectSize(w, h, (float)width, (float)height);
|
||||
long y = 0;
|
||||
if (x >= w) { // extract x/y image position
|
||||
y = x / w;
|
||||
x -= y * w;
|
||||
}
|
||||
if (x || y) dst += x + (y * Setting::ScreenWidth());
|
||||
}
|
||||
bottomPos = h;
|
||||
Image::Scale(src, width, height, dst, w, h, Setting::ScreenWidth());
|
||||
} else {
|
||||
bottomPos = height;
|
||||
long y = (h - height) / 2;
|
||||
long x = (w - width) / 2;
|
||||
if (x || y) {
|
||||
bottomPos += y;
|
||||
dst += x + (y * Setting::ScreenWidth());
|
||||
}
|
||||
fo::func::buf_to_buf(src, width, height, width, dst, Setting::ScreenWidth());
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) endgame_display_image_hook_buf_to_buf_loop() {
|
||||
static long tmp;
|
||||
__asm {
|
||||
pop ebp; // ret addr
|
||||
mov tmp, edx;
|
||||
call endgame_display_image_hook_buf_to_buf;
|
||||
mov edx, tmp;
|
||||
jmp ebp;
|
||||
}
|
||||
}
|
||||
|
||||
// rectangle area for printing text
|
||||
static fo::BoundRect darkRect;
|
||||
|
||||
static long __fastcall DarkRectangle(long tH, long tW, short totalLines) {
|
||||
totalLines--; // count text lines
|
||||
long y = Setting::ScreenHeight() - (totalLines * tH) - 20;
|
||||
long x = (Setting::ScreenWidth() - tW) / 2; // tW - max 540
|
||||
|
||||
if (textLine == 0) {
|
||||
if (panDesert <= 1) {
|
||||
darkRect.x = x - 10;
|
||||
darkRect.y = y - 5;
|
||||
darkRect.offx = tW + 20;
|
||||
darkRect.offy = (totalLines * (tH + 2)) + 6;
|
||||
}
|
||||
if (y <= bottomPos) {
|
||||
fo::util::TranslucentDarkFill((BYTE*)fo::var::getInt(FO_VAR_endgame_window_buffer), darkRect.x, darkRect.y, darkRect.offx, darkRect.offy, Setting::ScreenWidth());
|
||||
} else if (panDesert) { // correct the overlapping of text when the text is located below the image
|
||||
panDesert = 2;
|
||||
fo::util::FillRect((BYTE*)fo::var::getInt(FO_VAR_endgame_window_buffer), darkRect.x, darkRect.y, darkRect.offx, darkRect.offy, Setting::ScreenWidth(), (BYTE)color);
|
||||
}
|
||||
}
|
||||
return x + ((y + (tH * textLine++)) * Setting::ScreenWidth()); // text print offset
|
||||
}
|
||||
|
||||
static void __declspec(naked) endgame_show_subtitles_hook_buf_fill() {
|
||||
__asm {
|
||||
push [esp + 0xBC - 0x20 + 8]; // count lines
|
||||
mov ecx, ebx;
|
||||
call DarkRectangle;
|
||||
mov [esp + 0xBC - 0x34 + 8], eax; // replace x_offset
|
||||
mov dword ptr [esp + 0xBC - 0x38 + 8], 0; // y_offset
|
||||
retn 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void __fastcall endgame_pan_desert_hook_buf_fill(long, long, long) {
|
||||
fo::func::endgame_load_palette(fo::ArtType::OBJ_TYPE_INTRFACE, 327);
|
||||
if (SlidesScreen::END_SLIDE_SIZE != 2) {
|
||||
color = Image::GetDarkColor((fo::PALETTE*)FO_VAR_cmap);
|
||||
std::memset((void*)fo::var::getInt(FO_VAR_endgame_window_buffer), color, Setting::ScreenWidth() * Setting::ScreenHeight());
|
||||
}
|
||||
panDesert = 1;
|
||||
}
|
||||
|
||||
static void __cdecl endgame_pan_desert_hook_buf_to_buf(BYTE* src, long w, long h, long srcW, BYTE* dst, long dstW) {
|
||||
textLine = 0;
|
||||
|
||||
if (SlidesScreen::END_SLIDE_SIZE == 1) {
|
||||
long width = Setting::ScreenWidth();
|
||||
long height = Setting::ScreenHeight();
|
||||
long x = Image::GetAspectSize(width, height, (float)w, (float)h);
|
||||
long y = 0;
|
||||
if (x >= width) { // extract x/y image position
|
||||
y = x / width;
|
||||
x -= y * width;
|
||||
}
|
||||
if (x || y) dst += x + (y * Setting::ScreenWidth());
|
||||
bottomPos = height;
|
||||
|
||||
Image::Scale(src, w, h, dst, width, height, Setting::ScreenWidth(), srcW);
|
||||
|
||||
} else if (SlidesScreen::END_SLIDE_SIZE == 2) {
|
||||
bottomPos = Setting::ScreenHeight();
|
||||
Image::Scale(src, w, h, dst, Setting::ScreenWidth(), Setting::ScreenHeight(), 0, srcW);
|
||||
} else {
|
||||
bottomPos = h;
|
||||
long y = (Setting::ScreenHeight() - h) / 2;
|
||||
long x = (Setting::ScreenWidth() - w) / 2;
|
||||
if (x || y) {
|
||||
bottomPos += y;
|
||||
dst += x + (y * Setting::ScreenWidth());
|
||||
}
|
||||
fo::func::buf_to_buf(src, w, h, srcW, dst, Setting::ScreenWidth());
|
||||
}
|
||||
}
|
||||
|
||||
void SlidesScreen::init() {
|
||||
// endgame_init_
|
||||
sf::SafeWrite32(0x43FA01, Setting::ScreenHeight());
|
||||
sf::SafeWrite32(0x43FA14, Setting::ScreenWidth());
|
||||
// endgame_show_subtitles_
|
||||
sf::SafeWrite32(0x44065A, Setting::ScreenWidth());
|
||||
|
||||
sf::HookCall(0x440023, endgame_display_image_hook_art_frame_data);
|
||||
sf::HookCall(0x44004E, endgame_display_image_hook_buf_to_buf);
|
||||
sf::HookCall(0x440129, endgame_display_image_hook_buf_to_buf_loop);
|
||||
sf::HookCall(0x440639, endgame_show_subtitles_hook_buf_fill);
|
||||
|
||||
sf::HookCall(0x43FDE3, endgame_pan_desert_hook_buf_to_buf);
|
||||
sf::HookCall(0x43FC80, endgame_pan_desert_hook_buf_fill);
|
||||
|
||||
// block endgame_load_palette_
|
||||
sf::BlockCall(0x440072); // endgame_display_image_
|
||||
sf::BlockCall(0x43FC94); // endgame_pan_desert_
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* sfall
|
||||
* Copyright (C) 2008-2021 The sfall team
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace HRP
|
||||
{
|
||||
|
||||
class SlidesScreen {
|
||||
public:
|
||||
static void init();
|
||||
|
||||
static long END_SLIDE_SIZE;
|
||||
};
|
||||
|
||||
}
|
||||
+21
-29
@@ -24,51 +24,43 @@ long SplashScreen::SPLASH_SCRN_SIZE;
|
||||
|
||||
static void __cdecl game_splash_screen_hack_scr_blit(BYTE* srcPixels, long srcWidth, long srcHeight, long srcX, long srcY, long width, long height, long x, long y) {
|
||||
RECT rect;
|
||||
long w = sf::Graphics::GetGameWidthRes();
|
||||
long h = sf::Graphics::GetGameHeightRes();
|
||||
long w = Setting::ScreenWidth();
|
||||
long h = Setting::ScreenHeight();
|
||||
|
||||
// TODO: Load an alternative 32-bit BMP image or DirectX texture
|
||||
// stretch texture for DirectX
|
||||
if (SplashScreen::SPLASH_SCRN_SIZE == 1 || srcWidth > w || srcHeight > h) {
|
||||
x = Image::GetAspectSize(w, h, (float)srcWidth, (float)srcHeight);
|
||||
if (SplashScreen::SPLASH_SCRN_SIZE || srcWidth > w || srcHeight > h) {
|
||||
if (SplashScreen::SPLASH_SCRN_SIZE == 1) {
|
||||
x = Image::GetAspectSize(w, h, (float)srcWidth, (float)srcHeight);
|
||||
if (x >= w) { // extract x/y image position
|
||||
y = x / w;
|
||||
x -= y * w;
|
||||
}
|
||||
|
||||
rect.top = y;
|
||||
rect.bottom = (y + h) - 1;
|
||||
rect.left = x;
|
||||
rect.right = (rect.left + w) - 1;
|
||||
} else {
|
||||
rect.top = 0;
|
||||
rect.left = 0;
|
||||
rect.right = w - 1;
|
||||
rect.bottom = h - 1;
|
||||
}
|
||||
BYTE* resizeBuff = new BYTE[w * h];
|
||||
Image::Scale(srcPixels, srcWidth, srcHeight, resizeBuff, w, h);
|
||||
|
||||
// extract x/y image position
|
||||
if (x >= w) {
|
||||
y = x / w;
|
||||
x -= y * w;
|
||||
}
|
||||
|
||||
rect.top = y;
|
||||
rect.bottom = (y + h) - 1;
|
||||
rect.left = x;
|
||||
rect.right = (rect.left + w) - 1;
|
||||
sf::Graphics::UpdateDDSurface(resizeBuff, w, h, w, &rect);
|
||||
|
||||
delete[] resizeBuff;
|
||||
return;
|
||||
} else if (SplashScreen::SPLASH_SCRN_SIZE == 2) {
|
||||
BYTE* resizeBuff = new BYTE[sf::Graphics::GetGameWidthRes() * sf::Graphics::GetGameHeightRes()];
|
||||
Image::Scale(srcPixels, srcWidth, srcHeight, resizeBuff, sf::Graphics::GetGameWidthRes(), sf::Graphics::GetGameHeightRes());
|
||||
|
||||
rect.top = 0;
|
||||
rect.left = 0;
|
||||
rect.right =sf:: Graphics::GetGameWidthRes() - 1;
|
||||
rect.bottom = sf::Graphics::GetGameHeightRes() - 1;
|
||||
sf::Graphics::UpdateDDSurface(resizeBuff, sf::Graphics::GetGameWidthRes(), sf::Graphics::GetGameHeightRes(), sf::Graphics::GetGameWidthRes(), &rect);
|
||||
|
||||
delete[] resizeBuff;
|
||||
return;
|
||||
}
|
||||
|
||||
// original size to center screen
|
||||
|
||||
rect.left = (sf::Graphics::GetGameWidthRes() / 2) - (srcWidth / 2) + x;
|
||||
rect.left = ((Setting::ScreenWidth() - srcWidth) / 2) + x;
|
||||
rect.right = (rect.left + srcWidth) - 1 ;
|
||||
|
||||
rect.top = (sf::Graphics::GetGameHeightRes() / 2) - (srcHeight / 2) + y;
|
||||
rect.top = ((Setting::ScreenHeight() - srcHeight) / 2) + y;
|
||||
rect.bottom = (rect.top + srcHeight) - 1;
|
||||
|
||||
sf::Graphics::UpdateDDSurface(srcPixels, srcWidth, srcHeight, srcWidth, &rect);
|
||||
|
||||
@@ -852,6 +852,16 @@ static void EngineOptimizationPatches() {
|
||||
SafeWrite32(0x4D630C, 0x9090C031); // xor eax, eax
|
||||
SafeWrite8(0x4D6310, 0x90);
|
||||
BlockCall(0x4D6319);
|
||||
|
||||
// Reduce excessive delays in the save/load game screens
|
||||
SafeWriteBatch<BYTE>(16, { // 41 to 16 ms
|
||||
0x47D00D, // LoadGame_
|
||||
0x47C1FD // SaveGame_
|
||||
});
|
||||
// LoadGame_
|
||||
SafeWrite8(0x47CF0D, 195 + 10); // jz +10
|
||||
// SaveGame_
|
||||
SafeWrite8(0x47C135, 140 + 10); // jz +10
|
||||
}
|
||||
|
||||
void MiscPatches::init() {
|
||||
@@ -954,10 +964,12 @@ void MiscPatches::init() {
|
||||
HookCall(0x48A954, obj_move_to_tile_hook_redraw);
|
||||
HookCall(0x483726, map_check_state_hook_redraw);
|
||||
|
||||
// Corrects the height of the black background for death screen subtitles
|
||||
if (!HRP::Setting::ExternalEnabled()) SafeWrite32(0x48134D, 38 - (640 * 3)); // main_death_scene_ (shift y-offset 2px up, w/o HRP)
|
||||
if (!HRP::Setting::ExternalEnabled() || HRP::Setting::VersionIsValid) SafeWrite8(0x481345, 4); // main_death_scene_
|
||||
if (HRP::Setting::VersionIsValid) SafeWrite8(HRP::Setting::GetAddress(0x10011738), 10);
|
||||
if (!HRP::Setting::IsEnabled()) {
|
||||
// Corrects the height of the black background for death screen subtitles
|
||||
if (!HRP::Setting::ExternalEnabled()) SafeWrite32(0x48134D, 38 - (640 * 3)); // main_death_scene_ (shift y-offset 2px up, w/o HRP)
|
||||
if (!HRP::Setting::ExternalEnabled() || HRP::Setting::VersionIsValid) SafeWrite8(0x481345, 4); // main_death_scene_
|
||||
if (HRP::Setting::VersionIsValid) SafeWrite8(HRP::Setting::GetAddress(0x10011738), 10);
|
||||
}
|
||||
|
||||
F1EngineBehaviorPatch();
|
||||
DialogueFix();
|
||||
|
||||
@@ -310,6 +310,7 @@
|
||||
<ClInclude Include="Game\stats.h" />
|
||||
<ClInclude Include="Game\tilemap.h" />
|
||||
<ClInclude Include="HRP\Character.h" />
|
||||
<ClInclude Include="HRP\DeathScreen.h" />
|
||||
<ClInclude Include="HRP\Dialog.h" />
|
||||
<ClInclude Include="HRP\HelpScreen.h" />
|
||||
<ClInclude Include="HRP\Image.h" />
|
||||
@@ -319,6 +320,7 @@
|
||||
<ClInclude Include="HRP\LoadSave.h" />
|
||||
<ClInclude Include="HRP\MainMenu.h" />
|
||||
<ClInclude Include="HRP\MiscInterface.h" />
|
||||
<ClInclude Include="HRP\SlidesScreen.h" />
|
||||
<ClInclude Include="HRP\SplashScreen.h" />
|
||||
<ClInclude Include="HRP\ViewMap\EdgeBorder.h" />
|
||||
<ClInclude Include="HRP\ViewMap\EdgeClipping.h" />
|
||||
@@ -443,6 +445,7 @@
|
||||
<ClCompile Include="Game\stats.cpp" />
|
||||
<ClCompile Include="Game\tilemap.cpp" />
|
||||
<ClCompile Include="HRP\Character.cpp" />
|
||||
<ClCompile Include="HRP\DeathScreen.cpp" />
|
||||
<ClCompile Include="HRP\Dialog.cpp" />
|
||||
<ClCompile Include="HRP\HelpScreen.cpp" />
|
||||
<ClCompile Include="HRP\Image.cpp" />
|
||||
@@ -452,6 +455,7 @@
|
||||
<ClCompile Include="HRP\LoadSave.cpp" />
|
||||
<ClCompile Include="HRP\MainMenu.cpp" />
|
||||
<ClCompile Include="HRP\MiscInterface.cpp" />
|
||||
<ClCompile Include="HRP\SlidesScreen.cpp" />
|
||||
<ClCompile Include="HRP\SplashScreen.cpp" />
|
||||
<ClCompile Include="HRP\ViewMap\EdgeBorder.cpp" />
|
||||
<ClCompile Include="HRP\ViewMap\EdgeClipping.cpp" />
|
||||
|
||||
@@ -422,6 +422,12 @@
|
||||
<ClInclude Include="HRP\Worldmap.h">
|
||||
<Filter>HRP</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HRP\DeathScreen.h">
|
||||
<Filter>HRP</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HRP\SlidesScreen.h">
|
||||
<Filter>HRP</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
@@ -779,6 +785,12 @@
|
||||
<ClCompile Include="HRP\Worldmap.cpp">
|
||||
<Filter>HRP</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HRP\DeathScreen.cpp">
|
||||
<Filter>HRP</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HRP\SlidesScreen.cpp">
|
||||
<Filter>HRP</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc" />
|
||||
|
||||
Reference in New Issue
Block a user