diff --git a/sfall/FalloutEngine/VariableOffsets.h b/sfall/FalloutEngine/VariableOffsets.h index 04808204..d724000c 100644 --- a/sfall/FalloutEngine/VariableOffsets.h +++ b/sfall/FalloutEngine/VariableOffsets.h @@ -173,6 +173,8 @@ #define FO_VAR_last_level 0x5707B4 #define FO_VAR_lastMovieH 0x638E64 #define FO_VAR_lastMovieW 0x638E68 +#define FO_VAR_lastMovieX 0x638E6C +#define FO_VAR_lastMovieY 0x638E70 #define FO_VAR_lastTime 0x56FB58 #define FO_VAR_lastWin 0x51DD80 #define FO_VAR_Level_pc 0x6681B0 @@ -212,6 +214,9 @@ #define FO_VAR_movePointRect 0x518FD4 #define FO_VAR_movie_list 0x518DA0 #define FO_VAR_Mutate_ 0x5708B4 +#define FO_VAR_mve_win_rect 0x638E10 +#define FO_VAR_mveBH 0x6B402F +#define FO_VAR_mveBW 0x6B3CFC #define FO_VAR_name_color 0x56D744 #define FO_VAR_name_critter 0x51833C #define FO_VAR_name_font 0x56D74C @@ -299,6 +304,7 @@ #define FO_VAR_stack_offset 0x59E844 #define FO_VAR_stat_data 0x51D53C #define FO_VAR_stat_flag 0x66452A +#define FO_VAR_subtitleH 0x638EA0 #define FO_VAR_subtitleList 0x638E74 #define FO_VAR_subtitles 0x663974 #define FO_VAR_sWindows 0x6727B0 @@ -338,6 +344,7 @@ #define FO_VAR_wmBkWin 0x51DE14 #define FO_VAR_wmBkWinBuf 0x51DE24 #define FO_VAR_wmEncounterIconShow 0x672E48 +#define FO_VAR_wmInterfaceWasInitialized 0x51DE38 #define FO_VAR_wmLastRndTime 0x51DEA0 #define FO_VAR_wmMaxAreaNum 0x51DDFC #define FO_VAR_wmMaxMapNum 0x51DE10 diff --git a/sfall/HRP/DeathScreen.cpp b/sfall/HRP/DeathScreen.cpp index 259f7689..9e7c3bc3 100644 --- a/sfall/HRP/DeathScreen.cpp +++ b/sfall/HRP/DeathScreen.cpp @@ -43,12 +43,14 @@ static void __cdecl main_death_scene_hook_buf_to_buf(fo::FrmData* frm, long w, l 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 x = 0; long y = 0; - if (x >= w) { // extract x/y image position - y = x / w; - x -= y * w; - } + 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()); } diff --git a/sfall/HRP/HelpScreen.cpp b/sfall/HRP/HelpScreen.cpp index bf252c30..61672869 100644 --- a/sfall/HRP/HelpScreen.cpp +++ b/sfall/HRP/HelpScreen.cpp @@ -38,12 +38,9 @@ static void __cdecl game_help_hook_buf_to_buf(fo::FrmData* frm, long w, long 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 x = 0; long y = 0; - if (x >= w) { // extract x/y image position - y = x / w; - x -= y * w; - } + Image::GetAspectSize(width, height, &x, &y, w, h); if (x || y) dst += x + (y * Setting::ScreenWidth()); } Image::Scale(frm->frame.data, width, height, dst, w, h, Setting::ScreenWidth()); diff --git a/sfall/HRP/Image.cpp b/sfall/HRP/Image.cpp index f03719a7..80ba3f13 100644 --- a/sfall/HRP/Image.cpp +++ b/sfall/HRP/Image.cpp @@ -28,18 +28,25 @@ long Image::GetDarkColor(fo::PALETTE* palette) { return index; } -long Image::GetAspectSize(long &dW, long &dH, float sW, float sH) { +long Image::GetAspectSize(long sW, long sH, long* x, long* y, long &dW, long &dH) { + float sWf = (float)sW; + float sHf = (float)sH; + float width = (float)dW; float height = (float)dH; float aspectD = (float)dW / dH; - float aspectS = sW / sH; + float aspectS = sWf / sHf; if (aspectD < aspectS) { - dH = (long)((sH / sW) * dW); // set new height - return (long)(((height - dH) / 2) * dW); // shift y-offset center + dH = (long)((sHf / sWf) * dW); // set new height + long cy = (long)((height - dH) / 2); // shift y-offset center + if (y) *y = cy; + return cy * width; } else if (aspectD > aspectS) { - dW = (long)((dH / sH) * sW); // set new width - return (long)((width - dW) / 2); // shift x-offset center + dW = (long)((dH / sHf) * sWf); // set new width + long cx = (long)((width - dW) / 2); // shift x-offset center + if (x) *x = cx; + return cx; } return 0; } @@ -83,43 +90,6 @@ void Image::Scale(BYTE* src, long sWidth, long sHeight, BYTE* dst, long dWidth, while (--dHeight); } -// Fixme -void Image::TransScale(BYTE* src, long sWidth, long sHeight, BYTE* dst, long dWigth, long dHeight, long dPitch, long tranColorIdx) { - if (dWigth <= 0 || dHeight <= 0) return; - - float sw = (float)sWidth; - float sh = (float)sHeight; - float xStep = sw / dWigth; - float hStep = sh / dHeight; - - long height = dHeight; - dPitch -= dWigth; - - float sy = 0.0f; - do { - float sx = 0.0f; - int w = dWigth; - do { - BYTE pixel = *(src + std::lround(sx)); - if (pixel != tranColorIdx) *dst = pixel; - dst++; - sx += xStep; - if (sx >= sw) sx = sw - 1.0f; - } while (--w); - - if (sHeight) { - sy += hStep; - float y = std::round(sy); - if (y >= 1.0f && --sHeight) { - src += sWidth * (int)y; - sy -= y; - } - } - dst += dPitch; - } - while (--height); -} - // Simplified implementation of FMtext_to_buf_ engine function with text scaling void Image::ScaleText(BYTE* dstSurf, const char* text, long txtWidth, long dstWidth, long colorFlags, float scaleFactor) { if (*text) { diff --git a/sfall/HRP/Image.h b/sfall/HRP/Image.h index 5a970e10..a08b3e45 100644 --- a/sfall/HRP/Image.h +++ b/sfall/HRP/Image.h @@ -13,10 +13,9 @@ class Image { public: static long GetDarkColor(fo::PALETTE* palette); - static long GetAspectSize(long &dW, long &dH, float sW, float sH); + static long GetAspectSize(long sW, long sH, long* x, long* y, long &dW, long &dH); 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); }; diff --git a/sfall/HRP/Init.cpp b/sfall/HRP/Init.cpp index 6c983c79..903e0399 100644 --- a/sfall/HRP/Init.cpp +++ b/sfall/HRP/Init.cpp @@ -84,7 +84,8 @@ static std::string GetBackupFileName(const char* runFileName, bool wait) { size_t n = bakExeName.rfind('.'); if (n != std::string::npos) { bakExeName.replace(n, 4, ".hrp"); - while (remove(bakExeName.c_str()) != 0 && wait) Sleep(1000); // delete .hrp (if it exists) + char c = 10; + while (std::remove(bakExeName.c_str()) != 0 && wait && --c) Sleep(1000); // delete .hrp (if it exists) } return bakExeName; } @@ -96,18 +97,20 @@ static bool DisableExtHRP(const char* runFileName, std::string &cmdline) { std::rename(runFileName, bakExeName.c_str()); // rename the process file to .hrp CopyFileA(bakExeName.c_str(), runFileName, 0); // restore .exe (already unoccupied by a running process) - FILE* ft = fopen(runFileName,"r+b"); + FILE* ft = std::fopen(runFileName,"r+b"); if (!ft) return false; - fseek(ft, 0xD4880, SEEK_SET); // 0x4E4480 + std::fseek(ft, 0xD4880, SEEK_SET); // 0x4E4480 BYTE restore[] = {0xC7, 0x05, 0x88, 0x27, 0x6B, 0x00, 0x00, 0xE7, 0x4D, 0x00}; - fwrite(restore, 1, sizeof(restore), ft); + _fwrite_nolock(restore, 1, sizeof(restore), ft); + + // 0x4FE1C0 - 0x4FE1E7 + std::fseek(ft, 0xEE5C0, SEEK_SET); + + DWORD restore1[10] = {0}; + _fwrite_nolock(restore1, 4, sizeof(restore1), ft); - fseek(ft, 0xEE5C0, SEEK_SET); - BYTE restore1[39] = {0}; - fwrite(restore1, 1, sizeof(restore1), ft); fclose(ft); - cmdline.append(" -restart"); MessageBoxA(0, "High Resolution Patch has been successfully deactivated.", "sfall", MB_TASKMODAL | MB_ICONINFORMATION); @@ -176,7 +179,9 @@ void Setting::init(const char* exeFileName, std::string &cmdline) { //HookCall(0x482899, mem_copy); //SafeWrite16(0x4B2EA8, 0x9090); // _show_grid - if (!Setting::ExternalEnabled() && sf::IniReader::GetIntDefaultConfig("Main", "HiResMode", 1) == 0) return; // vanilla game mode + bool resMode = sf::IniReader::GetIntDefaultConfig("Main", "HiResMode", 1) != 0; + + if (!Setting::ExternalEnabled() && !resMode) return; // vanilla game mode SCR_WIDTH = sf::IniReader::GetInt("Main", "SCR_WIDTH", 640, f2ResIni); SCR_HEIGHT = sf::IniReader::GetInt("Main", "SCR_HEIGHT", 480, f2ResIni); @@ -187,15 +192,24 @@ void Setting::init(const char* exeFileName, std::string &cmdline) { if (cmdline.find(" -restart") != std::string::npos) { GetBackupFileName(exeFileName, true); // delete after restart } + if (resMode == false) return; if (Setting::ExternalEnabled()) { char infoMsg[512]; sf::Translate::Get("sfall", "HiResInfo", "This version of sfall has its own integrated High Resolution mode patch, which is compatible with the High Resolution Patch by Mash.\n\n" - "If you want to continue using the High Resolution Patch by Mash without seeing this message, disable the \"HiResMode\" option in the ddraw.ini file.\n" + "If you want to continue using the High Resolution Patch by Mash without seeing this message, disable the 'HiResMode' option in the ddraw.ini file.\n" "Or you can disable the external HRP to get new graphic improvements from sfall.\n\n" "Do you want to disable the High Resolution Patch by Mash?", infoMsg, 512); + // replace \n for translated message + for (size_t i = 0; i < sizeof(infoMsg); i++) { + if (infoMsg[i] == '\0') break; + if (infoMsg[i] == '\\' && infoMsg[i + 1] == 'n') { + infoMsg[i] = ' '; + infoMsg[++i] = '\n'; + } + } if (MessageBoxA(0, infoMsg, "sfall: Conflict of High Resolution patches", MB_TASKMODAL | MB_ICONWARNING | MB_YESNO) == IDYES) { if (!DisableExtHRP(exeFileName, cmdline)) { MessageBoxA(0, "An error occurred while trying to deactivate the High Resolution Patch.", "sfall", MB_TASKMODAL | MB_ICONERROR); diff --git a/sfall/HRP/MainMenu.cpp b/sfall/HRP/MainMenu.cpp index 13fea25b..b36e3dfe 100644 --- a/sfall/HRP/MainMenu.cpp +++ b/sfall/HRP/MainMenu.cpp @@ -39,7 +39,7 @@ static long mainmenuWidth = 640; static float scaleWidth, scaleHeight; // multiplier for shifting buttons/text static float scaleFactor = 1.0f; // scale for buttons and text -static long offsetX, offsetY; +static long offsetX = 0, offsetY = 0; // draw image to main menu window static void __cdecl main_menu_create_hook_buf_to_buf(BYTE* src, long sw, long sh, long srcW, BYTE* dst, long dstW) { @@ -117,7 +117,7 @@ static long __fastcall main_menu_create_hook_add_win(long h, long y, long color, w = Setting::ScreenWidth(); h = Setting::ScreenHeight(); - x = Image::GetAspectSize(w, h, (float)sw, (float)sh); + x = Image::GetAspectSize(sw, sh, 0, 0, w, h); if (w > Setting::ScreenWidth()) w = Setting::ScreenWidth(); if (h > Setting::ScreenHeight()) h = Setting::ScreenHeight(); diff --git a/sfall/HRP/MoviesScreen.cpp b/sfall/HRP/MoviesScreen.cpp index e1e80189..f20f4985 100644 --- a/sfall/HRP/MoviesScreen.cpp +++ b/sfall/HRP/MoviesScreen.cpp @@ -4,8 +4,13 @@ * */ +#include + +#include "..\main.h" #include "..\FalloutEngine\Fallout2.h" +#include "Image.h" + #include "MoviesScreen.h" namespace HRP @@ -15,8 +20,169 @@ namespace sf = sfall; long MoviesScreen::MOVIE_SIZE; +static RECT movieToSize; + +static void __fastcall SetMovieSize() { + long sWidth = Setting::ScreenWidth(); + long sHeight = Setting::ScreenHeight(); + + long bH = fo::var::getInt(FO_VAR_mveBH); + long bW = fo::var::getInt(FO_VAR_mveBW); + + long subtitleHeight = (fo::var::getInt(FO_VAR_subtitles) && fo::var::getInt(FO_VAR_subtitleList)) ? fo::var::getInt(FO_VAR_subtitleH) + 4 : 0; + + if (MoviesScreen::MOVIE_SIZE == 1 || bW > sWidth || bH > sHeight) { + long aspectW = sWidth; + long aspectH = sHeight - subtitleHeight; + long x = 0; + long y = 0; + Image::GetAspectSize(bW, bH, &x, &y, aspectW, aspectH); + + movieToSize.left = x; + movieToSize.top = y; + movieToSize.right = x + aspectW; + movieToSize.bottom = y + aspectH; + } else if (MoviesScreen::MOVIE_SIZE == 2) { + movieToSize.top = 0; + movieToSize.bottom = Setting::ScreenHeight() - subtitleHeight; + + movieToSize.left = 0; + movieToSize.right = Setting::ScreenWidth(); + } else { + // set to center + movieToSize.top = (Setting::ScreenHeight() - bH) / 2; + movieToSize.bottom = bH + movieToSize.top; + + movieToSize.left = (Setting::ScreenWidth() - bW) / 2; + movieToSize.right = bW + movieToSize.left; + } +} + +static void __declspec(naked) nfConfig_hack() { + __asm { + call SetMovieSize; + xor eax, eax; + mov ecx, 27; + retn; + } +} + +// surface: _nf_mve_buf1 +static long __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; + 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 + + return surface->Blt(&movieToSize, surface, &movieSize, MoviesScreen::MOVIE_SIZE, 0); // for sfall DX9 +} + +// Adjust Y position +static long __fastcall SubtitleAdjustPosition(long yTop, long yBottom) { + if (yBottom > Setting::ScreenHeight()) return yTop - (yBottom - Setting::ScreenHeight()); + + if (MoviesScreen::MOVIE_SIZE == 0 || Setting::ScreenHeight() == 480) return yTop; + + long y = fo::var::getInt(FO_VAR_lastMovieY); + y += fo::var::getInt(FO_VAR_lastMovieH) + 4; + + if (yTop >= y) return yTop; + + long spaceHeight = Setting::ScreenHeight() - y; + if (spaceHeight > fo::var::getInt(FO_VAR_subtitleH)) { + spaceHeight -= fo::var::getInt(FO_VAR_subtitleH); + y += spaceHeight / 2; // centering + } + + long yMax = Setting::ScreenHeight() - fo::var::getInt(FO_VAR_subtitleH); + return (y < yMax) ? y : yMax; +} + +static void __declspec(naked) doSubtitle_hook() { + __asm { + mov ecx, esi; + call SubtitleAdjustPosition; + mov esi, eax; + retn; + } +} + +static void __declspec(naked) gmovie_play_hack_begin() { + __asm { + cmp ds:[FO_VAR_wmInterfaceWasInitialized], 1; + jne skip; + mov eax, fo::funcoffs::wmMouseBkProc_; + call fo::funcoffs::remove_bk_process_; +skip: + mov edx, 1; + retn; + } +} + +static void __declspec(naked) gmovie_play_hack_end() { + __asm { + cmp ds:[FO_VAR_wmInterfaceWasInitialized], 1; + jne skip; + mov edx, eax; + mov eax, fo::funcoffs::wmMouseBkProc_; + call fo::funcoffs::add_bk_process_; + mov eax, edx; +skip: + pop edx; // ret addr + pop ebp; + pop edi; + pop esi; + pop ecx; + pop ebx; + jmp edx; + } +} + void MoviesScreen::init() { + if (MOVIE_SIZE < 0) MOVIE_SIZE = 0; + else if (MOVIE_SIZE > 2) MOVIE_SIZE = 2; + + // gmovie_play_ set GNWWin window size + sf::SafeWrite32(0x44E7D4, Setting::ScreenHeight()); + sf::SafeWrite32(0x44E7D9, Setting::ScreenWidth()); + sf::SafeWrite8(0x44E7D2, fo::WinFlags::Exclusive | fo::WinFlags::MoveOnTop); // fix + //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::MakeCall(0x4F5D40, nfConfig_hack); + + // openSubtitle_ + sf::HookCall(0x48738E, Setting::ScreenWidth); // replace windowGetXres_ + + // doSubtitle_ hacks + sf::SafeWrite32(0x487580, Setting::ScreenHeight()); + sf::HookCall(0x4875BE, doSubtitle_hook); + sf::SafeWrite8(0x4875C5, sf::CodeType::JumpShort); // jle > jmp + + // Prevent processing scrolling global map during playback + sf::MakeCall(0x44E6B2, gmovie_play_hack_begin); + sf::MakeCalls(gmovie_play_hack_end, {0x44EAC9, 0x44EADD}); + + // Disable _MVE_lastBuffer copying function (unnecessary option for the engine) + //sf::SafeWrite8(0x486F2E, sf::CodeType::Jump); // jz > jmp (cleanupMovie_) } } diff --git a/sfall/HRP/SlidesScreen.cpp b/sfall/HRP/SlidesScreen.cpp index 816fcf37..04a528f0 100644 --- a/sfall/HRP/SlidesScreen.cpp +++ b/sfall/HRP/SlidesScreen.cpp @@ -54,12 +54,9 @@ static void __cdecl endgame_display_image_hook_buf_to_buf(BYTE* src, long w, lon 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 x = 0; long y = 0; - if (x >= w) { // extract x/y image position - y = x / w; - x -= y * w; - } + Image::GetAspectSize(width, height, &x, &y, w, h); if (x || y) dst += x + (y * Setting::ScreenWidth()); } bottomPos = h; @@ -125,7 +122,7 @@ static void __declspec(naked) endgame_show_subtitles_hook_buf_fill() { 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) + 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()); @@ -140,12 +137,9 @@ static void __cdecl endgame_pan_desert_hook_buf_to_buf(BYTE* src, long w, long h 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 x = 0; long y = 0; - if (x >= width) { // extract x/y image position - y = x / width; - x -= y * width; - } + Image::GetAspectSize(w, h, &x, &y, width, height); if (x || y) dst += x + (y * Setting::ScreenWidth()); bottomPos = height; diff --git a/sfall/HRP/SplashScreen.cpp b/sfall/HRP/SplashScreen.cpp index e9f7b373..08265680 100644 --- a/sfall/HRP/SplashScreen.cpp +++ b/sfall/HRP/SplashScreen.cpp @@ -31,11 +31,8 @@ static void __cdecl game_splash_screen_hack_scr_blit(BYTE* srcPixels, long srcWi // stretch texture for DirectX 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; - } + x = 0; + Image::GetAspectSize(srcWidth, srcHeight, &x, &y, w, h); rect.top = y; rect.bottom = (y + h) - 1; diff --git a/sfall/Modules/Graphics.cpp b/sfall/Modules/Graphics.cpp index 5babf980..d41c1b1e 100644 --- a/sfall/Modules/Graphics.cpp +++ b/sfall/Modules/Graphics.cpp @@ -56,7 +56,7 @@ bool Graphics::IsWindowMode; bool Graphics::PlayAviMovie = false; bool Graphics::AviMovieWidthFit = false; -static DWORD yoffset; +//static DWORD yoffset; //static DWORD xoffset; bool DeviceLost = false; @@ -643,19 +643,27 @@ class FakeDirectDrawSurface : IDirectDrawSurface { private: ULONG Refs; bool isPrimary; + BYTE* lockTarget = nullptr; RECT* lockRect; + // size for secondary (mve) surface + DWORD m_width; + DWORD m_height; + public: static bool IsPlayMovie; - FakeDirectDrawSurface(bool primary) { + FakeDirectDrawSurface(bool primary, DDSURFACEDESC* desc) { Refs = 1; isPrimary = primary; - if (primary && Graphics::GPUBlt) { - // use the mainTex texture as source buffer + if (primary) { + if (Graphics::GPUBlt == 0) lockTarget = new BYTE[ResWidth * ResHeight](); + // for enabled GPUBlt, use the mainTex texture as source buffer } else { - lockTarget = new BYTE[ResWidth * ResHeight](); + m_width = desc->dwWidth; + m_height = desc->dwHeight; + lockTarget = new BYTE[m_width * m_height]; } } @@ -678,11 +686,12 @@ public: HRESULT __stdcall AddAttachedSurface(LPDIRECTDRAWSURFACE) { UNUSEDFUNCTION; } HRESULT __stdcall AddOverlayDirtyRect(LPRECT) { UNUSEDFUNCTION; } - HRESULT __stdcall Blt(LPRECT dst, LPDIRECTDRAWSURFACE b, LPRECT scr, DWORD d, LPDDBLTFX e) { // called 0x4868DA movie_MVE_ShowFrame_ (used for game movies, only for w/o HRP) - mveDesc.dwHeight = (dst->bottom - dst->top); - yoffset = (ResHeight - mveDesc.dwHeight) / 2; - mveDesc.lPitch = (dst->right - dst->left); + // called 0x4868DA movie_MVE_ShowFrame_ used for game movies (only for w/o HRP by Mash) + HRESULT __stdcall Blt(LPRECT dst, LPDIRECTDRAWSURFACE b, LPRECT scr, DWORD d, LPDDBLTFX e) { + mveDesc.dwHeight = scr->bottom; //(dst->bottom - dst->top); + mveDesc.lPitch = scr->right; //(dst->right - dst->left); //xoffset = (ResWidth - mveDesc.lPitch) / 2; + //yoffset = (ResHeight - mveDesc.dwHeight) / 2; //dlog_f("\nBlt: [mveDesc: w:%d, h:%d]", DL_INIT, mveDesc.lPitch, mveDesc.dwHeight); @@ -698,11 +707,11 @@ public: DWORD width = mveDesc.lPitch; // the current size of the width of the mve movie if (Graphics::GPUBlt) { - fo::func::buf_to_buf(lockTarget, width, mveDesc.dwHeight, width, (BYTE*)dRect.pBits, dRect.Pitch); - //char* pBits = (char*)dRect.pBits; - //for (DWORD y = 0; y < mveDesc.dwHeight; y++) { - // CopyMemory(&pBits[y * pitch], &lockTarget[y * width], width); - //} + if (d != 0) { + fo::func::cscale(lockTarget, width, mveDesc.dwHeight, width, (BYTE*)dRect.pBits, dst->right - dst->left, dst->bottom - dst->top, dRect.Pitch); + } else { + fo::func::buf_to_buf(lockTarget, width, mveDesc.dwHeight, width, (BYTE*)dRect.pBits, dRect.Pitch); + } } else { int pitch = dRect.Pitch / 4; DWORD* pBits = (DWORD*)dRect.pBits; @@ -719,6 +728,11 @@ public: mainTex->UnlockRect(0); d3d9Device->UpdateTexture(mainTex, mainTexD); + //IDirect3DSurface9 *mSurf, *mSurfD; + //mainTex->GetSurfaceLevel(0, &mSurf); + //mainTexD->GetSurfaceLevel(0, &mSurfD); + //d3d9Device->StretchRect(mSurf, 0, mSurfD, 0, D3DTEXF_LINEAR); + //mainTexLock = false; //if (Graphics::PlayAviMovie) return DD_OK; // Blt method is not executed during avi playback because the sfShowFrame_ function is blocked @@ -756,8 +770,8 @@ public: 0x4CB887 GNW95_ShowRect_ [c=1] 0x48699D movieShowFrame_ [c=1] 0x4CBBFA GNW95_zero_vid_mem_ [c=1] (clear surface) - 0x4F5E91/0x4F5EBB sub_4F5E60 [c=0] (from MVE_rmStepMovie_) 0x486861 movie_MVE_ShowFrame_ [c=1] (capture, never called) + 0x4F5E91/0x4F5EBB nf_mve_buf_lock [c=0] (from MVE_rmStepMovie_) */ HRESULT __stdcall Lock(LPRECT a, LPDDSURFACEDESC b, DWORD c, HANDLE d) { if (DeviceLost && Restore() == DD_FALSE) return DDERR_SURFACELOST; // DDERR_SURFACELOST 0x887601C2 @@ -776,11 +790,12 @@ public: b->lpSurface = lockTarget; } } else { - mveDesc.lPitch = fo::var::getInt(FO_VAR_lastMovieW); - mveDesc.dwHeight = fo::var::getInt(FO_VAR_lastMovieH); - //dlog_f("\nLock: [mveDesc: w:%d, h:%d]", DL_INIT, mveDesc.lPitch, mveDesc.dwHeight); + mveDesc.dwWidth = m_width; + mveDesc.lPitch = m_width; //fo::var::getInt(FO_VAR_lastMovieW); + mveDesc.dwHeight = m_height; //fo::var::getInt(FO_VAR_lastMovieH); *b = mveDesc; b->lpSurface = lockTarget; + //dlog_f("\nLock: [mveDesc: w:%d, h:%d]", DL_INIT, mveDesc.lPitch, mveDesc.dwHeight); } return DD_OK; } @@ -839,8 +854,9 @@ public: 0x4CB8F0 GNW95_ShowRect_ (common game, primary) 0x486A87 movieShowFrame_ 0x4CBC5A GNW95_zero_vid_mem_ (clear surface) - 0x4F5ECC sub_4F5E60 (from MVE_rmStepMovie_) + 0x4F5ECC nf_mve_buf_lock (from MVE_rmStepMovie_) 0x4868BA movie_MVE_ShowFrame_ (capture never call) + 0x4F5EFA/0x4F5F0B nf_mve_buf_unlock (from MVE_rmStepMovie_) */ HRESULT __stdcall Unlock(LPVOID lockSurface) { if (!isPrimary) return DD_OK; @@ -1034,11 +1050,11 @@ public: 0x4CB094 GNW95_init_DirectDraw_ (primary surface) 0x4F5DD4/0x4F5DF9 nfConfig_ (mve surface) */ - HRESULT __stdcall CreateSurface(LPDDSURFACEDESC a, LPDIRECTDRAWSURFACE* b, IUnknown* c) { - if (a->ddsCaps.dwCaps == DDSCAPS_PRIMARYSURFACE && a->dwFlags == DDSD_CAPS) { - *b = primarySurface = (IDirectDrawSurface*)new FakeDirectDrawSurface(true); + HRESULT __stdcall CreateSurface(LPDDSURFACEDESC desc, LPDIRECTDRAWSURFACE* b, IUnknown* c) { + if (desc->ddsCaps.dwCaps == DDSCAPS_PRIMARYSURFACE && desc->dwFlags == DDSD_CAPS) { + *b = primarySurface = (IDirectDrawSurface*)new FakeDirectDrawSurface(true, nullptr); } else { - *b = (IDirectDrawSurface*)new FakeDirectDrawSurface(false); + *b = (IDirectDrawSurface*)new FakeDirectDrawSurface(false, desc); } return DD_OK; }