diff --git a/sfall/HRP/CreditsScreen.cpp b/sfall/HRP/CreditsScreen.cpp new file mode 100644 index 00000000..51d4b8a8 --- /dev/null +++ b/sfall/HRP/CreditsScreen.cpp @@ -0,0 +1,80 @@ +/* + * sfall + * Copyright (C) 2008-2021 The sfall team + * + */ + +#include "..\main.h" +#include "..\FalloutEngine\Fallout2.h" + +#include "CreditsScreen.h" + +namespace HRP +{ + +namespace sf = sfall; + +static void __cdecl credits_hook_buf_to_buf_art(BYTE* src, long w, long h, long srcW, BYTE* dst, long dstW) { + long y = (Setting::ScreenHeight() - h) / 2; + dst += (y * Setting::ScreenWidth()); + + fo::func::buf_to_buf(src, w, h, srcW, dst, Setting::ScreenWidth()); +} + +static void __declspec(naked) credits_hack() { + __asm { // edx: H + call Setting::ScreenWidth; + imul eax, edx; // ScreenWidth * H + retn; + } +} + +static void PatchBufToBuf(DWORD w, DWORD h, DWORD srcW, DWORD dstW) { + sf::SafeWriteBatch(Setting::ScreenWidth(), { w, srcW, dstW }); + sf::SafeWrite32(h, Setting::ScreenHeight()); +} + +void CreditsScreen::init() { + // credits_ + // set window size + sf::SafeWrite32(0x42C945, Setting::ScreenHeight()); + sf::SafeWrite32(0x42C94F, Setting::ScreenWidth()); + + sf::HookCall(0x42CA38, credits_hook_buf_to_buf_art); + sf::SafeWrite16(0x42CA21, 0x9009); // remove 'add edi, eax' + + sf::MakeCall(0x42CAAE, credits_hack); + + DWORD patchWidth[] = { + 0x42CA18, // _text_to_buf + 0x42CB1C, + 0x42CB79, // textWidth < ScreenWidth + 0x42CBA8, // _text_to_buf + 0x42CBCB, 0x42CBEC, + 0x42CCD9, + 0x42CD1D, 0x42CD55 + }; + sf::SafeWriteBatch(Setting::ScreenWidth(), patchWidth); + + size_t screenBufSize = Setting::ScreenWidth() * Setting::ScreenHeight(); + size_t screenBufSize0 = screenBufSize - Setting::ScreenWidth(); + + sf::SafeWriteBatch(screenBufSize, { + 0x42C98B, // allocate backgrounf art buffer + 0x42C9AB, // clear art buffer + 0x42CA4D, // allocate buffer + 0x42CA68 // clear buffer + }); + + sf::SafeWriteBatch(screenBufSize0, {0x42CB22, 0x42CC22, 0x42CD23, 0x42CD3D}); + + PatchBufToBuf(0x42CAE6, 0x42CAE1, 0x42CADC, 0x42CACF); // buf_to_buf_ + PatchBufToBuf(0x42CC76, 0x42CC71, 0x42CC6C, 0x42CC5F); // buf_to_buf_ + PatchBufToBuf(0x42CC9B, 0x42CC96, 0x42CC91, 0x42CC8B); // trans_buf_to_buf_ + PatchBufToBuf(0x42CD7A, 0x42CD75, 0x42CD70, 0x42CD63); // buf_to_buf_ + PatchBufToBuf(0x42CDA6, 0x42CDA1, 0x42CD9C, 0x42CD8F); // trans_buf_to_buf_ + + sf::SafeWrite32(0x42CDDC, Setting::ScreenHeight()); +} + +} diff --git a/sfall/HRP/CreditsScreen.h b/sfall/HRP/CreditsScreen.h new file mode 100644 index 00000000..4b9bbccf --- /dev/null +++ b/sfall/HRP/CreditsScreen.h @@ -0,0 +1,17 @@ +/* + * sfall + * Copyright (C) 2008-2021 The sfall team + * + */ + +#pragma once + +namespace HRP +{ + +class CreditsScreen { +public: + static void init(); +}; + +} diff --git a/sfall/HRP/Init.cpp b/sfall/HRP/Init.cpp index a0a08c5c..6cd6a116 100644 --- a/sfall/HRP/Init.cpp +++ b/sfall/HRP/Init.cpp @@ -24,6 +24,7 @@ #include "HelpScreen.h" #include "DeathScreen.h" #include "SlidesScreen.h" +#include "CreditsScreen.h" #include "Init.h" @@ -178,6 +179,7 @@ void Setting::init() { HelpScreen::HELP_SCRN_SIZE = sf::IniReader::GetInt("STATIC_SCREENS", "HELP_SCRN_SIZE", 0, f2ResIni); 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); + //MoviesScreen::MOVIE_SIZE = sf::IniReader::GetInt("MOVIES", "MOVIE_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)); @@ -245,6 +247,7 @@ void Setting::init() { HelpScreen::init(); DeathScreen::init(); SlidesScreen::init(); + CreditsScreen::init(); } } diff --git a/sfall/HRP/InterfaceBar.cpp b/sfall/HRP/InterfaceBar.cpp index a102c8ac..72bd6aac 100644 --- a/sfall/HRP/InterfaceBar.cpp +++ b/sfall/HRP/InterfaceBar.cpp @@ -82,7 +82,7 @@ public: } *panels; static long __fastcall IntfaceWinCreate(long height, long yPos, long xPos, long width, long color, long flags) { - if (width != IFaceBar::IFACE_BAR_WIDTH) width = IFaceBar::IFACE_BAR_WIDTH; + if (Setting::ScreenWidth() >= IFaceBar::IFACE_BAR_WIDTH) width = IFaceBar::IFACE_BAR_WIDTH; yPos += Setting::ScreenHeight() - 479; // yPos:379 = 479-100 xPos += (Setting::ScreenWidth() - width) / 2; diff --git a/sfall/HRP/MainMenu.cpp b/sfall/HRP/MainMenu.cpp index d515ec23..13fea25b 100644 --- a/sfall/HRP/MainMenu.cpp +++ b/sfall/HRP/MainMenu.cpp @@ -28,32 +28,24 @@ long MainMenuScreen::MAIN_MENU_SIZE; bool MainMenuScreen::USE_HIRES_IMAGES; bool MainMenuScreen::SCALE_BUTTONS_AND_TEXT_MENU; // if the value is false and USE_HIRES_IMAGES is false, btnBackgroundFrm and buttons with text labels are not scaled -long MainMenuScreen::MENU_BG_OFFSET_X = 29; +long MainMenuScreen::MENU_BG_OFFSET_X = 30; long MainMenuScreen::MENU_BG_OFFSET_Y = 19; static fo::UnlistedFrm* mainBackgroundFrm; static fo::UnlistedFrm* btnBackgroundFrm; static long mainmenuWidth = 640; -static float scaleFactor = 1.0f; // for buttons and text -static float scaleXFactor = 1.0f; -static long GetXOffset() { - return (scaleXFactor > 1.0f) ? std::lround(15 * scaleXFactor) : 0; -} +static float scaleWidth, scaleHeight; // multiplier for shifting buttons/text +static float scaleFactor = 1.0f; // scale for buttons and text -static long GetYOffset() { - return (scaleXFactor > 1.0f) ? std::lround(9 * scaleXFactor) : 0; -} +static long offsetX, offsetY; // draw image to main menu window -static void __cdecl main_menu_create_hook_buf_to_buf(BYTE* src, long w, long h, long srcW, BYTE* dst, long dstW) { - long sw = w; - long sh = h; - +static void __cdecl main_menu_create_hook_buf_to_buf(BYTE* src, long sw, long sh, long srcW, BYTE* dst, long dstW) { fo::Window* win = fo::var::window[fo::var::main_window]; // the window size is always equal to the scaled image - h = win->height; - w = win->width; + long h = win->height; + long w = win->width; dstW = w; if (mainBackgroundFrm) { @@ -73,15 +65,28 @@ static void __cdecl main_menu_create_hook_buf_to_buf(BYTE* src, long w, long h, // background image for buttons if (btnBackgroundFrm) { + // offset of the button background + long x = MainMenuScreen::MENU_BG_OFFSET_X; + long y = MainMenuScreen::MENU_BG_OFFSET_Y; + + if (MainMenuScreen::SCALE_BUTTONS_AND_TEXT_MENU) { + x += (long)(x * scaleFactor); + y += (long)(y * scaleFactor); + } + + x += (long)(sf::MainMenu::mXOffset * scaleWidth) + offsetX; + y += (long)(sf::MainMenu::mYOffset * scaleHeight) + offsetY; + + if (x < 0) x = 0; + if (y < 0) y = 0; + dst += (y * dstW) + x; + sh = btnBackgroundFrm->frames->height; sw = btnBackgroundFrm->frames->width; if (MainMenuScreen::SCALE_BUTTONS_AND_TEXT_MENU) { - scaleFactor *= 1.6f; // additional scaling - dst += (MainMenuScreen::MENU_BG_OFFSET_Y * dstW) + MainMenuScreen::MENU_BG_OFFSET_X; fo::func::trans_cscale(btnBackgroundFrm->frames->indexBuff, sw, sh, sw, dst, (long)(sw * scaleFactor), (long)(sh * scaleFactor), dstW); } else { - dst += ((MainMenuScreen::MENU_BG_OFFSET_Y + GetYOffset()) * dstW) + MainMenuScreen::MENU_BG_OFFSET_X + GetXOffset(); fo::func::trans_buf_to_buf(btnBackgroundFrm->frames->indexBuff, sw, sh, sw, dst, dstW); // direct copy } } @@ -92,7 +97,6 @@ static void __cdecl main_menu_create_hook_buf_to_buf(BYTE* src, long w, long h, static long __fastcall main_menu_create_hook_add_win(long h, long y, long color, long flags) { long x = 0; long w = 640; - long offset = 0; long sw = w, sh = h; sf::Graphics::BackgroundClearColor(0); @@ -113,7 +117,7 @@ static long __fastcall main_menu_create_hook_add_win(long h, long y, long color, w = Setting::ScreenWidth(); h = Setting::ScreenHeight(); - offset = Image::GetAspectSize(w, h, (float)sw, (float)sh); + x = Image::GetAspectSize(w, h, (float)sw, (float)sh); if (w > Setting::ScreenWidth()) w = Setting::ScreenWidth(); if (h > Setting::ScreenHeight()) h = Setting::ScreenHeight(); @@ -123,36 +127,39 @@ static long __fastcall main_menu_create_hook_add_win(long h, long y, long color, } if (MainMenuScreen::MAIN_MENU_SIZE == 1) { - if (offset) { - x = offset; - // extract x/y window position - if (x >= mainmenuWidth) { - y = x / mainmenuWidth; - x -= y * mainmenuWidth; - } - } else { - // nothing??? + // extract x/y window position + if (x >= mainmenuWidth) { + y = x / mainmenuWidth; + x -= y * mainmenuWidth; } } else if (MainMenuScreen::MAIN_MENU_SIZE == 2) { - w = Setting::ScreenWidth(); h = Setting::ScreenHeight(); + w = Setting::ScreenWidth(); mainmenuWidth = w; } else { // centering - x += (Setting::ScreenWidth() / 2) - (w / 2); - y += (Setting::ScreenHeight() / 2) - (h / 2); + x += (Setting::ScreenWidth() - w) / 2; + y += (Setting::ScreenHeight() - h) / 2; } // set scaling factor + scaleWidth = (w / 640.0f); + scaleHeight = (h / 480.0f); + // is not scaled if USE_HIRES_IMAGES is used and the SCALE_BUTTONS_AND_TEXT_MENU option is disabled if (MainMenuScreen::USE_HIRES_IMAGES == false || (MainMenuScreen::USE_HIRES_IMAGES && MainMenuScreen::SCALE_BUTTONS_AND_TEXT_MENU)) { - scaleFactor = h / (float)sh; - //scaleFactor = std::round(scaleFactor * 100.0f) / 100.0f; + scaleFactor = scaleHeight; + } else { + if (w != 640) offsetX = (long)(6.0f * (Setting::ScreenWidth() * 0.0015625)); + if (h != 480) offsetY = (long)(4.0f * (Setting::ScreenHeight() * 0.0020833334f)); } - scaleXFactor = Setting::ScreenWidth() / (float)640; // TODO: find out how Mash's HRP gets the coefficient for button offsets for different game resolutions - sf::MainMenu::mTextOffset = sf::MainMenu::mXOffset; - if (sf::MainMenu::mYOffset) sf::MainMenu::mTextOffset += (sf::MainMenu::mYOffset * w); + sf::MainMenu::mTextOffset = offsetX; + if (offsetY) sf::MainMenu::mTextOffset += offsetY * mainmenuWidth; + + // button text offset + if (sf::MainMenu::mXOffset) sf::MainMenu::mTextOffset += (long)(sf::MainMenu::mXOffset * scaleWidth); + if (sf::MainMenu::mYOffset) sf::MainMenu::mTextOffset += (long)(sf::MainMenu::mYOffset * scaleHeight) * mainmenuWidth; if (x < 0) x = 0; if (y < 0) y = 0; @@ -185,26 +192,21 @@ static void __declspec(naked) main_menu_create_hook_win_print() { } } -static void __fastcall TextScale(long xOffset, const char* text, long yPos, long color) { - if (MainMenuScreen::USE_HIRES_IMAGES) { - xOffset += GetXOffset(); - yPos += GetYOffset(); - } - - xOffset = (long)(xOffset * scaleFactor); +static void __fastcall TextScale(long xPos, const char* text, long yPos, long color) { + xPos = (long)(xPos * scaleFactor); yPos = (long)(yPos * scaleFactor); yPos *= mainmenuWidth; - yPos += sf::MainMenu::mTextOffset; // TODO: check + yPos += sf::MainMenu::mTextOffset; Image::ScaleText( - (BYTE*)(fo::var::getInt(FO_VAR_main_window_buf) + yPos + xOffset), + (BYTE*)(fo::var::getInt(FO_VAR_main_window_buf) + yPos + xPos), text, fo::util::GetTextWidth(text), mainmenuWidth, color, scaleFactor ); } // buttons text print static void __declspec(naked) main_menu_create_hook_text_to_buf() { - __asm { // eax:xOffset, ebp:yPos, edx:text, ebx:txtWidth (640-txtWidth)-1 + __asm { // eax:xOffset (0), ebp:yPos, edx:text, ebx:txtWidth (640-txtWidth)-1 cmp scaleFactor, 1.0f; jne scale; mov ecx, mainmenuWidth; @@ -225,37 +227,41 @@ scale: static BYTE* buttonImageData; static BYTE* downButtonImageData; // reference -static long __fastcall ButtonScale(long &width, long xPos, BYTE* &upImageData, BYTE* &downImageData, long &yPos) { - if (MainMenuScreen::USE_HIRES_IMAGES) { - xPos += GetXOffset(); - yPos += GetYOffset(); +static long __fastcall ButtonPosition(long &width, long xPos, BYTE* &upImageData, BYTE* &downImageData, long &yPos) { + /*** Button scale ***/ + if (scaleFactor != 1.0f) { + long sWidth = (int)(width * scaleFactor); + + if (!buttonImageData) { + int size = sWidth * sWidth; + buttonImageData = new BYTE[size * 2]; // two images + + // up + Image::Scale(*(BYTE**)FO_VAR_button_up_data, width, width, buttonImageData, sWidth, sWidth); + // down + downButtonImageData = &buttonImageData[size]; + Image::Scale(*(BYTE**)FO_VAR_button_down_data, width, width, downButtonImageData, sWidth, sWidth); + } + upImageData = buttonImageData; + downImageData = downButtonImageData; + width = sWidth; + + yPos = (long)(yPos * scaleFactor); + xPos = (long)(xPos * scaleFactor); } - int sWidth = (int)(width * scaleFactor); - if (!buttonImageData) { - int size = sWidth * sWidth; - buttonImageData = new BYTE[size * 2]; // two images + long h = fo::var::window[fo::var::main_window]->height; - // up - Image::Scale(*(BYTE**)FO_VAR_button_up_data, width, width, buttonImageData, sWidth, sWidth); - // down - downButtonImageData = &buttonImageData[size]; - Image::Scale(*(BYTE**)FO_VAR_button_down_data, width, width, downButtonImageData, sWidth, sWidth); - } - upImageData = buttonImageData; - downImageData = downButtonImageData; + /*** Button position ***/ + xPos += (long)(sf::MainMenu::mXOffset * scaleWidth) + offsetX; + yPos += (long)(sf::MainMenu::mYOffset * scaleHeight) + offsetY; - width = sWidth; - yPos = (long)(yPos * scaleFactor); - return (long)(xPos * scaleFactor); + if (yPos >= h) yPos = h - width; + return (xPos >= mainmenuWidth) ? mainmenuWidth - width : xPos; } static void __declspec(naked) main_menu_create_hook_register_button() { - __asm { // eax:_main_window, edx:Xpos, ebx:Ypos, ecx:Width - cmp scaleFactor, 1.0f; - jne scale; - jmp fo::funcoffs::win_register_button_; -scale: + __asm { // eax:_main_window, edx:Xpos (30), ebx:Ypos (+19), ecx:Width (26) push ecx; // width mov ecx, esp; // width ref push ebx; // Ypos @@ -264,8 +270,8 @@ scale: push ebx; lea ebx, [esp + 24 + 16]; // button_up_data ref push ebx; - call ButtonScale; - // set scale size + call ButtonPosition; + // set out values mov edx, eax; // out Xpos pop ebx; // out Ypos pop ecx; // out width @@ -291,9 +297,6 @@ static void FreeMainMenuImages() { } void MainMenuScreen::init() { - if (MENU_BG_OFFSET_X < 0) MENU_BG_OFFSET_X = 0; - if (MENU_BG_OFFSET_Y < 0) MENU_BG_OFFSET_Y = 0; - // Mainmenu window size //sf::SafeWrite32(0x481674, HRP::ScreenHeight()); //sf::SafeWrite32(0x48167A, HRP::ScreenWidth()); diff --git a/sfall/HRP/SlidesScreen.cpp b/sfall/HRP/SlidesScreen.cpp index 80cc0888..816fcf37 100644 --- a/sfall/HRP/SlidesScreen.cpp +++ b/sfall/HRP/SlidesScreen.cpp @@ -88,7 +88,7 @@ static void __declspec(naked) endgame_display_image_hook_buf_to_buf_loop() { } // rectangle area for printing text -static fo::BoundRect darkRect; +static sf::Rectangle darkRect; static long __fastcall DarkRectangle(long tH, long tW, short totalLines) { totalLines--; // count text lines @@ -99,14 +99,14 @@ static long __fastcall DarkRectangle(long tH, long tW, short totalLines) { if (panDesert <= 1) { darkRect.x = x - 10; darkRect.y = y - 5; - darkRect.offx = tW + 20; - darkRect.offy = (totalLines * (tH + 2)) + 6; + darkRect.width = tW + 20; + darkRect.height = (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()); + fo::util::TranslucentDarkFill((BYTE*)fo::var::getInt(FO_VAR_endgame_window_buffer), darkRect.x, darkRect.y, darkRect.width, darkRect.height, 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); + fo::util::FillRect((BYTE*)fo::var::getInt(FO_VAR_endgame_window_buffer), darkRect.x, darkRect.y, darkRect.width, darkRect.height, Setting::ScreenWidth(), (BYTE)color); } } return x + ((y + (tH * textLine++)) * Setting::ScreenWidth()); // text print offset @@ -123,8 +123,9 @@ static void __declspec(naked) endgame_show_subtitles_hook_buf_fill() { } } -static void __fastcall endgame_pan_desert_hook_buf_fill(long, long, long) { - fo::func::endgame_load_palette(fo::ArtType::OBJ_TYPE_INTRFACE, 327); +static void __fastcall endgame_pan_desert_hook_buf_fill(long, long, fo::FrmData* frm) { + frmArt = frm; + fo::func::endgame_load_palette(fo::ArtType::OBJ_TYPE_INTRFACE, 327); // panning desert image (DP.FRM) 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()); @@ -134,6 +135,7 @@ static void __fastcall endgame_pan_desert_hook_buf_fill(long, long, long) { static void __cdecl endgame_pan_desert_hook_buf_to_buf(BYTE* src, long w, long h, long srcW, BYTE* dst, long dstW) { textLine = 0; + h = frmArt->frame.height; // h: default 480 if (SlidesScreen::END_SLIDE_SIZE == 1) { long width = Setting::ScreenWidth(); @@ -178,6 +180,7 @@ void SlidesScreen::init() { sf::HookCall(0x43FDE3, endgame_pan_desert_hook_buf_to_buf); sf::HookCall(0x43FC80, endgame_pan_desert_hook_buf_fill); + sf::SafeWrite8(0x43FC75, 0x56); //push eax > push esi // block endgame_load_palette_ sf::BlockCall(0x440072); // endgame_display_image_ diff --git a/sfall/Modules/MainMenu.cpp b/sfall/Modules/MainMenu.cpp index 2da04118..eed3d638 100644 --- a/sfall/Modules/MainMenu.cpp +++ b/sfall/Modules/MainMenu.cpp @@ -81,17 +81,17 @@ void MainMenu::init() { SafeWrite32(0x48175C, 460 + offset); } if (offset = IniReader::GetConfigInt("Misc", "MainMenuOffsetX", 0)) { - SafeWrite32(0x48187C, 30 + offset); // button mXOffset = offset; - mTextOffset = offset; } if (offset = IniReader::GetConfigInt("Misc", "MainMenuOffsetY", 0)) { mYOffset = offset; - mTextOffset += offset * 640; - MakeJump(0x481844, MainMenuHookButtonYOffset); } - if (!HRP::Setting::IsEnabled() && mTextOffset) { - MakeCall(0x481933, MainMenuHookTextYOffset, 1); + if (!HRP::Setting::IsEnabled()) { + if (mXOffset) SafeWrite32(0x48187C, 30 + mXOffset); // button + if (mYOffset) MakeJump(0x481844, MainMenuHookButtonYOffset); + + mTextOffset = mXOffset + (mYOffset * 640); + if (mTextOffset) MakeCall(0x481933, MainMenuHookTextYOffset, 1); } HookCall(0x4817AB, main_menu_create_hook_print_text); diff --git a/sfall/ddraw.vcxproj b/sfall/ddraw.vcxproj index 2d085cb8..594e0edb 100644 --- a/sfall/ddraw.vcxproj +++ b/sfall/ddraw.vcxproj @@ -310,6 +310,7 @@ + @@ -445,6 +446,7 @@ + diff --git a/sfall/ddraw.vcxproj.filters b/sfall/ddraw.vcxproj.filters index bae9a207..30fe6a95 100644 --- a/sfall/ddraw.vcxproj.filters +++ b/sfall/ddraw.vcxproj.filters @@ -428,6 +428,9 @@ HRP + + HRP + @@ -791,6 +794,9 @@ HRP + + HRP +