Mercurial > mm7
view VideoPlayer.cpp @ 2331:9551756f46c4
Moving functions out of mm7_6.cpp into appropriate classes as static methods or free functions
author | Grumpy7 |
---|---|
date | Wed, 02 Apr 2014 01:21:05 +0200 |
parents | d65414f65bd4 |
children | ddb803517a48 |
line wrap: on
line source
#define _CRT_SECURE_NO_WARNINGS #include "Bink_Smacker.h" #include "mm7_data.h" #include "CShow.h" #include "Mouse.h" #include "VideoPlayer.h" #include "AudioPlayer.h" #include "Game.h" #include "Render.h" #include "Party.h" #include "GUIWindow.h" #include "Timer.h" #include "Log.h" #include "texts.h" #include "UI\UIHouses.h" VideoPlayer *pVideoPlayer = nullptr; #pragma comment(lib, "Version.lib") bool GetDllVersion(const wchar_t *pDllName, uint *pMajor, uint *pMinor) { uint uVersionSize = GetFileVersionInfoSizeW(pDllName, nullptr); void *pVersionData = HeapAlloc(GetProcessHeap(), 0, uVersionSize); { GetFileVersionInfoW(pDllName, 0, uVersionSize, pVersionData); VS_FIXEDFILEINFO *pInfo = nullptr; UINT uInfoSize = 0; VerQueryValueW(pVersionData, L"\\", (void **)&pInfo, &uInfoSize); if (!pMajor || !pMinor) { HeapFree(GetProcessHeap(), 0, pVersionData); return false; } *pMajor = pInfo->dwFileVersionMS; *pMinor = pInfo->dwFileVersionLS; } HeapFree(GetProcessHeap(), 0, pVersionData); return true; } // 3.15.1.0: // 3 15 1 0 // 0x0003000F00010000 unsigned __int64 uBinkVersion; bool BinkLockBuffer(struct _BINKBUF *_this); void BinkUnlockBuffer(struct _BINKBUF *_this); //----- (004BFE2D) -------------------------------------------------------- _BINKBUF *VideoPlayer::CreateBinkBuffer(unsigned int uWidth, unsigned int uHeight, char a4) { _BINKBUF *v5; // esi@3 HRESULT v6; // eax@5 IDirectDrawSurface *v7; // eax@6 HRESULT v8; // eax@9 DDSURFACEDESC2 v11; // [sp+Ch] [bp-108h]@7 DDSURFACEDESC Dst; // [sp+88h] [bp-8Ch]@3 IDirectDrawSurface4 *v15; // [sp+108h] [bp-Ch]@7 IDirectDrawSurface2 *a2; // [sp+10Ch] [bp-8h]@3 //if (pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || //pVersion->pVersionInfo.dwMajorVersion >= 5u ) { v15 = 0; if (uBinkVersion == 0x0001000500150000) { v5 = new _BINKBUF_1_5_21_0; memset(v5, 0, sizeof(_BINKBUF_1_5_21_0)); } else if (uBinkVersion == 0x0003000000000000) { v5 = new _BINKBUF_3_0_0_0; memset(v5, 0, sizeof(_BINKBUF_3_0_0_0)); } else __debugbreak(); memset(&v11, 0, 0x7C); v11.dwSize = 124; v11.dwWidth = uWidth; v11.dwFlags = 0x1007; // DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT v11.ddsCaps.dwCaps = 0x4040; // DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY v11.dwHeight = uHeight; *(_QWORD *)&v11.ddpfPixelFormat.dwSize = 0x400000020ui64;// DDPF_FOURCC v11.ddpfPixelFormat.dwFourCC = 0x32595559; if (FAILED(pRenderer->pDirectDraw4->CreateSurface(&v11, &v15, 0))) { memset(&v11.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT)); v11.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; v11.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; long hr = pRenderer->pDirectDraw4->CreateSurface(&v11, &v15, 0); ErrD3D(hr); } v5->uWidth = v11.dwWidth; v5->uHeight = v11.dwHeight; v5->uBinkDDSurfaceType = BinkDDSurfaceType((IDirectDrawSurface *)v15); v5->field_38 = 0; v7 = (IDirectDrawSurface *)v15; } /*else { v4 = 0; a2 = 0; if (uBinkVersion == 0x0001000500150000) { v5 = new _BINKBUF_1_5_21_0; memset(v5, 0, sizeof(_BINKBUF_1_5_21_0)); } else if (uBinkVersion == 0x0003000000000000) { v5 = new _BINKBUF_3_0_0_0; memset(v5, 0, sizeof(_BINKBUF_3_0_0_0)); } else __debugbreak(); memset(&Dst, 0, 0x6Cu); Dst.dwSize = 108; Dst.dwWidth = uWidth; Dst.dwFlags = 4103; Dst.ddsCaps.dwCaps = 16448; Dst.dwHeight = uHeight; Dst.ddpfPixelFormat.dwSize = 32; Dst.ddpfPixelFormat.dwFlags = 4; Dst.ddpfPixelFormat.dwFourCC = 844715353; if (FAILED(pRenderer->pDirectDraw2->CreateSurface(&Dst, (LPDIRECTDRAWSURFACE *)&a2, 0))) { memset(&Dst.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT)); Dst.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; Dst.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; long hr = pRenderer->pDirectDraw2->CreateSurface(&Dst, (LPDIRECTDRAWSURFACE *)&a2, 0); ErrD3D(hr); } v5->uWidth = Dst.dwWidth; v5->uHeight = Dst.dwHeight; v5->uBinkDDSurfaceType = BinkDDSurfaceType((IDirectDrawSurface *)a2); v5->field_38 = 0; v7 = (IDirectDrawSurface *)a2; }*/ v5->pTargetDDrawSurface = v7; v5->hWnd = window->GetApiHandle(); v5->field_4C = 0; v5->field_68 = 0; v5->field_5C = 0; v5->field_74 = a4 & 0x1F; v5->field_78 = 1; v5->target_width = GetSystemMetrics(SM_CXSCREEN); v5->target_height = GetSystemMetrics(SM_CYSCREEN); v5->field_2C = 16; RECT Rect; GetWindowRect(window->GetApiHandle(), &Rect); v5->field_8 = window->GetWidth(); v5->field_C = window->GetHeight(); v5->field_1C = Rect.left; v5->field_20 = Rect.top; Rect.left = 0; Rect.top = 0; ClientToScreen(window->GetApiHandle(), (POINT *)&Rect); v5->field_1C = Rect.left - v5->field_1C; v5->field_20 = Rect.top - v5->field_20; GetClientRect(window->GetApiHandle(), &Rect); v5->field_30 = v5->field_8 - Rect.right; v5->field_34 = v5->field_C - Rect.bottom; v5->field_8 = v5->uWidth + v5->field_30; v5->field_C = v5->uHeight + v5->field_34; BinkBufferSetOffset(v5, 0, 0); BinkBufferSetScale(v5, v5->uWidth, v5->uHeight); return v5; } //----- (004C0133) -------------------------------------------------------- bool BinkLockBuffer(_BINKBUF *_this) { IDirectDrawSurface *v2; // edi@5 IDirectDrawSurface4 *v6; // edi@11 //if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion >= 5u ) { DDSURFACEDESC2 v8; // [sp+Ch] [bp-7Ch]@4 if ( _this->pTargetDDrawSurface ) { memset(&v8, 0, 0x7C); v8.dwSize = 124; while ( 1 ) { v6 = (IDirectDrawSurface4 *)_this->pTargetDDrawSurface; if ( !v6->Lock(0, &v8, 1, 0) ) break; if (uBinkVersion < 0x0003000000000000) _this->uBinkDDSurfaceType |= 0x80000000; else _this->uBinkDDSurfaceType |= 0x4000000; if ( v6->Restore() ) return 0; } _this->pDDrawSurfaceData_ = v8.lpSurface; _this->pDDrawSurfaceData = v8.lpSurface; _this->uDDrawSurfacePitch = v8.lPitch; return 1; } } /*else { DDSURFACEDESC v8; // [sp+Ch] [bp-7Ch]@4 if ( _this->pTargetDDrawSurface ) { memset(&v8.lPitch, 0, 0x6Cu); v8.lPitch = 108; while ( 1 ) { v2 = _this->pTargetDDrawSurface; if ( !v2->Lock(0, (LPDDSURFACEDESC)&v8.lPitch, 1, 0) ) break; if (uBinkVersion < 0x0003000000000000) __asm int 3; else BYTE3(_this->uBinkDDSurfaceType) |= 4u; if ( v2->Restore() ) return 0; } _this->pDDrawSurfaceData_ = v8.lpSurface; _this->pDDrawSurfaceData = v8.lpSurface; _this->uDDrawSurfacePitch = v8.dwReserved; return 1; } }*/ return 1; } //----- (004C01FB) -------------------------------------------------------- void BinkUnlockBuffer(_BINKBUF *_this) { IDirectDrawSurface *v2; // eax@1 v2 = _this->pTargetDDrawSurface; if ( v2 ) { v2->Unlock(0); _this->uDDrawSurfacePitch = 0; _this->pDDrawSurfaceData = 0; if (uBinkVersion < 0x0003000000000000) BYTE3(_this->uBinkDDSurfaceType) &= 0x7F; else BYTE3(_this->uBinkDDSurfaceType) &= 0xFB; } } //----- (004BF794) -------------------------------------------------------- void ShowMM7IntroVideo_and_LoadingScreen() { RGBTexture tex; // [sp+Ch] [bp-30h]@1 unsigned int uTrackStartMS; // [sp+34h] [bp-8h]@8 unsigned int uTrackEndMS; // [sp+38h] [bp-4h]@8 pVideoPlayer->bStopBeforeSchedule = false; pVideoPlayer->pResetflag = 0; bGameoverLoop = true; if (!bNoVideo) { pRenderer->PresentBlackScreen(); if ( !pVideoPlayer->bStopBeforeSchedule ) PlayFullscreenMovie(MOVIE_Intro, true); } char pContainerName[64]; tex.Load("mm6title.pcx", 2); pRenderer->BeginScene(); pRenderer->DrawTextureRGB(0, 0, &tex); free(tex.pPixels); tex.pPixels = 0; //LoadFonts_and_DrawCopyrightWindow(); DrawMM7CopyrightWindow(); pRenderer->EndScene(); pRenderer->Present(); #ifndef _DEBUG Sleep(1500); // let the copyright window stay for a while #endif if (!bNoSound && pAudioPlayer->hAILRedbook ) { pAudioPlayer->SetMusicVolume((signed __int64)(pSoundVolumeLevels[uMusicVolimeMultiplier] * 64.0)); AIL_redbook_stop(pAudioPlayer->hAILRedbook); AIL_redbook_track_info(pAudioPlayer->hAILRedbook, 14, &uTrackStartMS, &uTrackEndMS); AIL_redbook_play(pAudioPlayer->hAILRedbook, uTrackStartMS + 1, uTrackEndMS); } bGameoverLoop = false; } //----- (004BE70E) -------------------------------------------------------- void VideoPlayer::MovieLoop(const char *pMovieName, int a2, int ScreenSizeFlag, int a4) { int v4; // ebp@1 const char *pName; // edi@1 MSG Msg; // [sp+Ch] [bp-1Ch]@12 v4 = a2; pName = pMovieName; if ( !(dword_6BE364_game_settings_1 & (GAME_SETTINGS_NO_HOUSE_ANIM | GAME_SETTINGS_NO_INTRO)) ) { if ( a2 == 2 ) v4 = 0; ShowCursor(0); OpenGlobalMovie(pName, 0, ScreenSizeFlag); bPlayingMovie = 1; field_44 = v4; //if ( pRenderer->pRenderD3D ) { pRenderer->ClearTarget(0); } /* else { pRenderer->BeginScene(); pRenderer->ClearTarget(0); pRenderer->EndScene(); }*/ pCurrentScreen = SCREEN_VIDEO; auto hwnd = pVideoPlayer->window->GetApiHandle(); RECT rc_client; GetClientRect(hwnd, &rc_client); int client_width = rc_client.right - rc_client.left, client_height = rc_client.bottom - rc_client.top; HDC dc = GetDC(hwnd); HDC back_dc = CreateCompatibleDC(dc); HBITMAP back_bmp; SelectObject(back_dc, back_bmp = CreateCompatibleBitmap(dc, client_width, client_height)); while (true) { if ( pVideoPlayer->bStopBeforeSchedule ) break; while (PeekMessageA(&Msg, hwnd, 0, 0, PM_REMOVE)) { if (Msg.message == 18) Game_DeinitializeAndTerminate(0); if (Msg.message == 15) break; TranslateMessage(&Msg); DispatchMessageA(&Msg); } GUI_MainMenuMessageProc(); if (pMovie->Stopped()) break; char *image = pPlayer->DoFrame(); if (image) { // draw to hwnd BITMAPINFO bmi; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = client_width; bmi.bmiHeader.biHeight = -client_height; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biSizeImage = 0; bmi.bmiHeader.biXPelsPerMeter = 0; bmi.bmiHeader.biYPelsPerMeter = 0; bmi.bmiHeader.biClrUsed = 0; bmi.bmiHeader.biClrImportant = 0; GetDIBits(back_dc, back_bmp, 0, client_height, 0, &bmi, DIB_RGB_COLORS); SetDIBits(back_dc, back_bmp, 0, client_height, image, &bmi, DIB_RGB_COLORS); BitBlt(dc, 0, 0, client_width, client_height, back_dc, 0, 0, SRCCOPY); delete[] image; } if (pVideoPlayer->bStopBeforeSchedule == 1) Sleep(1000); } pVideoPlayer->Unload(); /* if ( pVideoPlayer->uMovieFormat == 2 ) { if ( pVideoPlayer->pBinkMovie ) { //pVideoPlayer->BinkDrawFrame(v4, ScreenSizeFlag); } } if ( pVideoPlayer->bStopBeforeSchedule == 1 ) Sleep(0x3E8u); }*/ /* if ( pVideoPlayer->uMovieFormat == 1 ) { if ( pVideoPlayer->pSmackerMovie ) { pVideoPlayer->SmackDrawFrame(v4, ScreenSizeFlag); while ( pVideoPlayer->pSmackerMovie ) { if ( pVideoPlayer->bStopBeforeSchedule ) break; while ( PeekMessageW(&Msg, 0, 0, 0, 1) ) { if (Msg.message == WM_QUIT) Game_DeinitializeAndTerminate(0); if (Msg.message == WM_PAINT) break; TranslateMessage(&Msg); DispatchMessageW(&Msg); } GUI_MainMenuMessageProc(); if ( !pVideoPlayer->pSmackerMovie ) break; if ( !SmackWait(pVideoPlayer->pSmackerMovie) && !pVideoPlayer->bStopBeforeSchedule ) pVideoPlayer->SmackDrawFrame(v4, ScreenSizeFlag); } } } */ if (a4 == 1) pCurrentScreen = SCREEN_GAME; pVideoPlayer->bPlayingMovie = 0; ShowCursor(1); if ( pCurrentScreen == SCREEN_VIDEO ) pCurrentScreen = SCREEN_GAME; } } //----- (004BE95A) -------------------------------------------------------- unsigned int VideoPlayer::SmackCheckSurfaceFromat() { DDPIXELFORMAT a2; // [sp+0h] [bp-20h]@1 a2.dwSize = 32; a2.dwFlags = 64; pRenderer->GetTargetPixelFormat(&a2); if (a2.dwRGBBitCount == 32) return SMACKBUFFER565; if ( a2.dwRGBBitCount != 8 ) { if ( a2.dwRBitMask == 0xF800 ) { if ( a2.dwGBitMask == 0x7E0 && a2.dwBBitMask == 0x1F ) return SMACKBUFFER565; } else { if ( a2.dwRBitMask == 0x7C00 && a2.dwGBitMask == 0x3E0 && a2.dwBBitMask == 0x1F ) return SMACKBUFFER555; } MessageBoxA(0, "Unsupported pixel format.", "Smacker Error", 0); } return 0; } //----- (004BE9D8) -------------------------------------------------------- void VideoPlayer::Initialize(OSWindow *target_window) { DWORD NumberOfBytesRead; // [sp+10h] [bp-4h]@9 window = target_window; uint uBinkVersionMajor = -1, uBinkVersionMinor = -1; GetDllVersion(L"BINKW32.DLL", &uBinkVersionMajor, &uBinkVersionMinor); uBinkVersion = (unsigned __int64)uBinkVersionMajor << 32 | uBinkVersionMinor; strcpy(pTmpBuf.data(), "anims\\might7.vid"); hMightVid = CreateFileW(L"anims\\might7.vid", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0x8000080, 0); if ( hMightVid == INVALID_HANDLE_VALUE ) { sprintf(pTmpBuf2.data(), "Can't open file - anims\\%s.smk", pTmpBuf.data()); MessageBoxA(0, pTmpBuf2.data(), "Video File Error", 0); return; } strcpy(pTmpBuf.data(), "anims\\magic7.vid"); hMagicVid = CreateFileW(L"anims\\magic7.vid", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0x8000080, 0); if ( hMagicVid == INVALID_HANDLE_VALUE ) { if ( !bCanLoadFromCD ) { sprintf(pTmpBuf2.data(), "Can't open file - anims\\%s.smk", pTmpBuf.data()); MessageBoxA(0, pTmpBuf2.data(), "Video File Error", 0); return; } sprintf(pTmpBuf2.data(), "%c:\\%s", (unsigned __int8)cMM7GameCDDriveLetter, pTmpBuf.data()); hMagicVid = CreateFileA(pTmpBuf2.data(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0x8000080, 0); if ( hMagicVid == (HANDLE)INVALID_HANDLE_VALUE ) { sprintf(pTmpBuf2.data(), "Can't open file - %s", pTmpBuf.data()); MessageBoxA(0, pTmpBuf2.data(), "Video File Error", 0); return; } } ReadFile(hMightVid, &uNumMightVideoHeaders, 4, &NumberOfBytesRead, 0); ReadFile(hMagicVid, &uNumMagicVideoHeaders, 4, &NumberOfBytesRead, 0); pMagicVideoHeaders = 0; pMightVideoHeaders = 0; pMightVideoHeaders = (MovieHeader *)malloc(sizeof(MovieHeader) * uNumMightVideoHeaders + 2); pMagicVideoHeaders = (MovieHeader *)malloc(sizeof(MovieHeader) * uNumMagicVideoHeaders + 2); ReadFile(hMightVid, pMightVideoHeaders, 44 * uNumMightVideoHeaders, &NumberOfBytesRead, 0); ReadFile(hMagicVid, pMagicVideoHeaders, 44 * uNumMagicVideoHeaders, &NumberOfBytesRead, 0); } //----- (004BEB41) -------------------------------------------------------- void VideoPlayer::Prepare() { pEventTimer->Pause(); if ( pAudioPlayer->hAILRedbook ) AIL_redbook_pause(pAudioPlayer->hAILRedbook); bStopBeforeSchedule = false; bBufferLoaded = 1; /* pSmackerMovie = 0; pSmackerBuffer = 0; pBinkMovie = 0; pBinkBuffer = 0; */ bPlayingMovie = false; bFirstFrame = false; bUsingSmackerMMX = SmackUseMMX(1); BinkSetSoundSystem(BinkOpenMiles, pAudioPlayer->hDigDriver); uBinkDirectDrawSurfaceType = BinkDDSurfaceType((IDirectDrawSurface *)pRenderer->pBackBuffer4); } //----- (004BEBD7) -------------------------------------------------------- void VideoPlayer::Unload() { //_BINK *pBinkMovie; // eax@1 //_BINKBUF *pBinkBuffer; // eax@3 //_SMACK *pSmackerMovie; // eax@5 /* if ( pBinkMovie ) { //BinkPause(pBinkMovie, 1); Sleep(300); //BinkClose(pBinkMovie); pBinkMovie = 0; } if ( pBinkBuffer ) { pBinkBuffer->pTargetDDrawSurface->Release(); pBinkBuffer->pTargetDDrawSurface = 0; free(pBinkBuffer); pBinkBuffer = 0; } if ( pSmackerMovie ) { //SmackSoundOnOff(pSmackerMovie, 0); //SmackClose(pSmackerMovie); pSmackerMovie = 0; } if ( pSmackerBuffer ) { SmackBufferClose(pSmackerBuffer); pSmackerBuffer = 0; } */ if ( pSmackMovieBlit ) { SmackBlitClose(pSmackMovieBlit); pSmackMovieBlit = 0; } bBufferLoaded = 0; uMovieFormat = 0; uMovieFormatSwapped = 0; memset(pCurrentMovieName, 0, 0x40); if ( pAudioPlayer->hAILRedbook && !bGameoverLoop ) AIL_redbook_resume(pAudioPlayer->hAILRedbook); pEventTimer->Resume(); if (pMovie) { delete pMovie; pMovie = nullptr; } } //----- (004BECD5) -------------------------------------------------------- /* void VideoPlayer::FastForwardToFrame(unsigned int uDstFrameNum) { VideoPlayer *v2; // esi@1 unsigned int v3; // eax@1 v2 = this; v3 = this->uMovieFormat; if ( v3 == 2 ) { if (uDstFrameNum) { int *pCurrentFrame = uBinkVersion == 0x0001000500150000 ? &((_BINK_1_5_21_0 *)pBinkMovie)->uCurrentFrame : uBinkVersion == 0x0003000000000000 ? &((_BINK_3_0_0_0 *)pBinkMovie)->uCurrentFrame : nullptr; while (*pCurrentFrame < uDstFrameNum) { BinkDoFrame(pBinkMovie); BinkNextFrame(pBinkMovie); } } } else { if ( v3 != 1 ) return; SmackSoundOnOff(this->pSmackerMovie, 0); if (uDstFrameNum) { while ( v2->pSmackerMovie->FrameNum < uDstFrameNum) { SmackDoFrame(v2->pSmackerMovie); SmackNextFrame(v2->pSmackerMovie); } } } Unload(); } //----- (004BED4F) -------------------------------------------------------- void VideoPlayer::BinkDrawFrame(int a3, int a4) { //VideoPlayer *v4; // esi@1 _BINKBUF *v5; // eax@5 LONG v6; // edx@6 int v7; // ecx@6 LONG v8; // edx@6 struct tagRECT a3a; // [sp+8h] [bp-20h]@10 struct tagRECT a1; // [sp+18h] [bp-10h]@6 //v4 = this; if ( this->pBinkMovie && this->pBinkBuffer ) { BinkDoFrame(pBinkMovie); BinkGetRects(pBinkMovie, pBinkBuffer->uBinkDDSurfaceType); if ( BinkLockBuffer(pBinkBuffer) ) { BinkCopyToBuffer(pBinkMovie, pBinkBuffer->pDDrawSurfaceData, pBinkBuffer->uDDrawSurfacePitch, pBinkBuffer->uHeight, 0, 0, pBinkBuffer->uBinkDDSurfaceType); BinkUnlockBuffer(pBinkBuffer); } v5 = pBinkBuffer; if ( pRenderer->bWindowMode ) { v6 = v5->uRectX; a1.left = v6; a1.top = v5->uRectY; v7 = v6 + v5->uWidth; a1.right = v6 + v5->uWidth; v8 = a1.top + v5->uHeight; } else { a1.left = 0; a1.top = 0; v7 = v5->uWidth; a1.right = v5->uWidth; v8 = v5->uHeight; } a1.bottom = v8; if ( a4 ) { a1.right = v5->uWidth + v7; a1.bottom = v5->uHeight + v8; } a3a.left = 0; a3a.top = 0; a3a.right = v5->uWidth; a3a.bottom = v5->uHeight; pRenderer->BltToFront(&a1, v5->pTargetDDrawSurface, &a3a, 0x1000000u); int *pCurrentFrame = uBinkVersion == 0x0001000500150000 ? &((_BINK_1_5_21_0 *)pBinkMovie)->uCurrentFrame : uBinkVersion == 0x0003000000000000 ? &((_BINK_3_0_0_0 *)pBinkMovie)->uCurrentFrame: nullptr; int *pNumFrames = uBinkVersion == 0x0001000500150000 ? &((_BINK_1_5_21_0 *)pBinkMovie)->uNumFrames : uBinkVersion == 0x0003000000000000 ? &((_BINK_3_0_0_0 *)pBinkMovie)->uNumFrames : nullptr; if (*pCurrentFrame != *pNumFrames - 1 || bLoopPlaying) BinkNextFrame(pBinkMovie); else Unload(); } } //----- (004BEE6B) -------------------------------------------------------- void VideoPlayer::SmackDrawFrame(int a3, int a4) { VideoPlayer *v4; // esi@1 _SMACK *v5; // eax@3 unsigned int v6; // eax@5 char v7; // zf@5 int v8; // eax@11 _SMACK *v9; // eax@13 _SMACK *v10; // eax@16 _SMACK *v11; // eax@20 unsigned int v12; // [sp-1Ch] [bp-34h]@7 LONG v13; // [sp-18h] [bp-30h]@7 LONG v14; // [sp-14h] [bp-2Ch]@7 signed int v15; // [sp-10h] [bp-28h]@7 signed int v16; // [sp-Ch] [bp-24h]@7 signed int v17; // [sp-8h] [bp-20h]@7 struct tagPOINT Point; // [sp+8h] [bp-10h]@7 unsigned short *pOutSurface; // [sp+10h] [bp-8h]@5 unsigned int uPixelsPerRow; // [sp+14h] [bp-4h]@5 v4 = this; if ( !pRenderer->bWindowMode || window->Focused()) { v5 = v4->pSmackerMovie; if ( v5->NewPalette ) SmackBlitSetPalette(v4->pSmackMovieBlit, v5->Palette, v5->PalType); SmackDoFrame(v4->pSmackerMovie); pRenderer->LockFrontBuffer((void **)&pOutSurface, &uPixelsPerRow); v6 = 2 * uPixelsPerRow; v7 = v4->bFirstFrame == 0; uPixelsPerRow *= 2; if ( !v7 ) { if ( pRenderer->bWindowMode ) { Point.y = 0; Point.x = 0; ClientToScreen(window->GetApiHandle(), &Point); v17 = -1; v16 = 480; v15 = 640; v14 = Point.y; v13 = Point.x; v12 = uPixelsPerRow; } else { v17 = -1; v16 = 480; v15 = 640; v14 = 0; v13 = 0; v12 = v6; } SmackBlitClear(v4->pSmackMovieBlit, pOutSurface, v12, v13, v14, v15, v16, v17); v4->bFirstFrame = 0; } pRenderer->RestoreFrontBuffer(); if ( pRenderer->bWindowMode ) { Point.y = 0; Point.x = 0; ClientToScreen(window->GetApiHandle(), &Point); v8 = SmackToBufferRect(v4->pSmackerMovie, 0); if ( a4 ) { while ( v8 ) { v9 = v4->pSmackerMovie; SmackBlit( v4->pSmackMovieBlit, pOutSurface, uPixelsPerRow, v9->LastRectx + Point.x / 2, a3 + v9->LastRecty + Point.y / 2, v4->pSomeSmackerBuffer, v9->Width, v9->LastRectx, v9->LastRecty, v9->LastRectw, v9->LastRecth); v8 = SmackToBufferRect(v4->pSmackerMovie, 0); } } else { while ( v8 ) { v10 = v4->pSmackerMovie; SmackBlit(v4->pSmackMovieBlit, pOutSurface, uPixelsPerRow, Point.x + v10->LastRectx, a3 + Point.y + v10->LastRecty, v4->pSomeSmackerBuffer, v10->Width, v10->LastRectx, v10->LastRecty, v10->LastRectw, v10->LastRecth); v8 = SmackToBufferRect(v4->pSmackerMovie, 0); } } } else { while ( SmackToBufferRect(v4->pSmackerMovie, 0) ) { v11 = v4->pSmackerMovie; SmackBlit(v4->pSmackMovieBlit, pOutSurface, uPixelsPerRow, v11->LastRectx, a3 + v11->LastRecty, v4->pSomeSmackerBuffer, v11->Width, v11->LastRectx, v11->LastRecty, v11->LastRectw, v11->LastRecth); } } pRenderer->UnlockFrontBuffer(); if ( v4->pSmackerMovie->FrameNum != v4->pSmackerMovie->Frames - 1 || v4->bLoopPlaying ) SmackNextFrame(v4->pSmackerMovie); else Unload(); } } */ void VideoPlayer::_inlined_in_463149() { /* if ( pSmackMovie && !SmackWait(pSmackerMovie) ) { pRenderer->BeginScene(); pMouse->DrawCursorToTarget(); SmackUpdatePalette(); pMouse->ReadCursorWithItem(); pRenderer->EndScene(); } else if ( pBinkMovie && !BinkWait(pBinkMovie) ) { pRenderer->BeginScene(); pMouse->DrawCursorToTarget(); BinkUpdatePalette(); pMouse->ReadCursorWithItem(); pRenderer->EndScene(); } */ if (pMovie) { pRenderer->BeginScene(); pMouse->DrawCursorToTarget(); UpdatePalette(); pMouse->ReadCursorWithItem(); pRenderer->EndScene(); } } //auto pixels = new unsigned short[640 * 480]; void VideoPlayer::UpdatePalette() { Log::Warning(L"smacker"); pRenderer->BeginScene(); if (pMovie->Stopped())//видео завершено/перезагрузка { int width = game_viewport_width; int height = game_viewport_height; delete pMovie; SetFilePointer(hVidFile, uOffset, nullptr, FILE_BEGIN); pMovie = pPlayer->LoadMovieFromLOD(hVidFile, &readFunction, &seekFunction, width, height); } else { char *image = pPlayer->DoFrame(); int image_array[460 * 344];//game_viewport_width * game_viewport_height if (image) { memcpy(image_array, image, sizeof (image_array)); for (unsigned int y = 8; y < 8 + game_viewport_height; ++y)//координаты местоположения видеоролика { for (unsigned int x = 8; x < 8 + game_viewport_width; ++x) { auto p = (unsigned __int32 *)pRenderer->pTargetSurface + x + y * pRenderer->uTargetSurfacePitch; *p = image_array[((x - 8) + ((y - 8)*game_viewport_width))]; } } delete[] image; } } pRenderer->EndScene(); } /* //----- (004BF08B) -------------------------------------------------------- void VideoPlayer::SmackUpdatePalette() { //VideoPlayer *v2; // esi@1 unsigned __int16 *v3; // ebx@1 unsigned int v4; // edi@1 unsigned int v5; // eax@1 //_SMACK *v6; // eax@1 Log::Warning(L"smacker"); pRenderer->BeginScene(); v3 = pixels;//pRenderer->pTargetSurface; v4 = 640;//pRenderer->uTargetSurfacePitch; v5 = SmackCheckSurfaceFromat(); SmackToBuffer(pSmackerMovie, 8, 8, 2 * v4, pRenderer->field_14, v3, v5); for (unsigned int y = 8; y < 8 + pSmackerMovie->Height; ++y) for (unsigned int x = 8; x < 8 + pSmackerMovie->Width; ++x) { pRenderer->WritePixel16(x, y, pixels[x + y * 640]); } //delete [] pixels; //v6 = pSmackerMovie; while (true) { if ( pSmackerMovie->NewPalette ) { SmackBufferNewPalette(pSmackerBuffer, pSmackerMovie->Palette, (pSmackerMovie->PalType)); SmackColorRemapWithTrans( pSmackerMovie, pSmackerBuffer->Palette, pSmackerBuffer->MaxPalColors, pSmackerBuffer->PalType, 1000); } SmackDoFrame(pSmackerMovie); if ( pSmackerMovie->FrameNum != pSmackerMovie->Frames - 1 || bLoopPlaying ) SmackNextFrame(pSmackerMovie); else Unload(); pRenderer->EndScene(); } */ /* //----- (004BF141) -------------------------------------------------------- _BINK *VideoPlayer::OpenBink(const char *pName) { //VideoPlayer *v2; // esi@1 signed int v3; // edi@1 int v4; // ebx@2 signed int v5; // edi@5 int v6; // ebx@6 HANDLE v8; // [sp-8h] [bp-18h]@10 unsigned int v9; // [sp-4h] [bp-14h]@10 for (uint i = 0; i < uNumMightVideoHeaders; ++i) if (!_stricmp(pName, pMightVideoHeaders[i].pVideoName)) { SetFilePointer(hMightVid, pMightVideoHeaders[i].uFileOffset, 0, FILE_BEGIN); if (uBinkVersion < 0x0003000000000000) return BinkOpen(hMightVid, 0x8800000); else return BinkOpen(hMightVid, 0x82000000); } for (uint i = 0; i < uNumMagicVideoHeaders; ++i) if (!_stricmp(pName, pMagicVideoHeaders[i].pVideoName)) { SetFilePointer(hMagicVid, pMagicVideoHeaders[i].uFileOffset, 0, FILE_BEGIN); if (uBinkVersion < 0x0003000000000000) return BinkOpen(hMagicVid, BINKNOTHREADEDIO | BINKFILEHANDLE);//0x8800000); else return BinkOpen(hMagicVid, BINKIOPROCESSOR | BINKCOPYALL);//0x82000000); } return nullptr; } //----- (004BF1E6) -------------------------------------------------------- _SMACK *VideoPlayer::OpenSmack(const char *pFilename) { if ( this->uNumMightVideoHeaders ) { for ( uint i = 0; i < (signed int)this->uNumMightVideoHeaders; ++i) { if ( !_stricmp(this->pMightVideoHeaders[i].pVideoName, pFilename) ) { SetFilePointer(this->hMightVid, this->pMightVideoHeaders[i].uFileOffset, 0, 0); return SmackOpen(this->hMightVid, SMACKTRACK2|SMACKTRACK1|SMACKFILEHANDLE|SMACKLOADEXTRA|SMACKNEEDVOLUME, -1);//0x7140, } } } if ( this->uNumMagicVideoHeaders ) { for ( uint i = 0; i < (signed int)this->uNumMagicVideoHeaders; ++i ) { if ( !_stricmp(this->pMagicVideoHeaders[i].pVideoName, pFilename) ) { SetFilePointer(this->hMagicVid, this->pMagicVideoHeaders[i].uFileOffset, 0, 0); return SmackOpen(this->hMagicVid, SMACKTRACK2|SMACKTRACK1|SMACKFILEHANDLE|SMACKLOADEXTRA|SMACKNEEDVOLUME, -1); } } } return 0; } */ //----- (004BF28F) -------------------------------------------------------- void VideoPlayer::OpenHouseMovie(const char *pMovieName, unsigned int a3_1) { if (!this->bBufferLoaded) { //Prepare(); pEventTimer->Pause(); if (pAudioPlayer->hAILRedbook) AIL_redbook_pause(pAudioPlayer->hAILRedbook); bStopBeforeSchedule = false; bBufferLoaded = 1; /* pSmackerMovie = 0; pSmackerBuffer = 0; pBinkMovie = 0; pBinkBuffer = 0; */ bPlayingMovie = false; bFirstFrame = false; bUsingSmackerMMX = SmackUseMMX(1); this->bLoopPlaying = a3_1; if ( LOBYTE(this->field_104) == 1 ) { MessageBoxA(nullptr, "Unsupported Bink playback!", "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Video.cpp:925", 0); return; } LoadMovie(pMovieName); /* this->pSmackerMovie = OpenSmack(Str2); if ( !this->pSmackerMovie ) { this->Unload(); sprintf(pTmpBuf.data(), "Can't load %s", &Str2); MessageBoxA(nullptr, pTmpBuf.data(), "E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Video.cpp:937", 0); return; } */ /* this->pSmackerBuffer = (_SMACKBUF *)SmackBufferOpen(window->GetApiHandle(), 4, LOWORD(this->pSmackerMovie->Width), LOWORD(this->pSmackerMovie->Height), LOWORD(this->pSmackerMovie->Width), LOWORD(this->pSmackerMovie->Height)); if ( this->pSmackerBuffer ) { pRenderer->BeginScene(); SmackToBuffer(this->pSmackerMovie, 8, 8, 2 * pRenderer->uTargetSurfacePitch, pRenderer->field_14, pRenderer->pTargetSurface, SmackCheckSurfaceFromat()); pRenderer->EndScene(); } SmackVolumePan(this->pSmackerMovie, 1040384, (signed __int64)(pSoundVolumeLevels[(char)uSoundVolumeMultiplier] * 32767.0), 32767); */ } } //----- (004BF3F9) -------------------------------------------------------- bool VideoPlayer::AnyMovieLoaded() { return pMovie;// pSmackerMovie || pBinkMovie; } //----- (004BF411) -------------------------------------------------------- void VideoPlayer::OpenGlobalMovie(const char *pFilename, unsigned int bLoop, int a4) { unsigned int v10; // eax@11 if (!this->bBufferLoaded) { //Prepare(); pEventTimer->Pause(); if (pAudioPlayer->hAILRedbook) AIL_redbook_pause(pAudioPlayer->hAILRedbook); bStopBeforeSchedule = false; bBufferLoaded = 1; /* pSmackerMovie = 0; pSmackerBuffer = 0; pBinkMovie = 0; pBinkBuffer = 0; */ bPlayingMovie = false; bFirstFrame = false; bUsingSmackerMMX = SmackUseMMX(1); this->bLoopPlaying = bLoop; LoadMovie(pFilename); return; /* sprintf(pVideoName, "%s.bik", pFilename); this->pBinkMovie = OpenBink(pVideoName); if ( this->pBinkMovie ) { this->uMovieFormat = 2; strcpy(this->pCurrentMovieName, pFilename); pBinkMovie = this->pBinkMovie; this->uMovieFormatSwapped = 1; if ( pBinkMovie ) this->pBinkBuffer = CreateBinkBuffer(pBinkMovie->uWidth, pBinkMovie->uHeight, 0); } else { Unload(); sprintfex(pVideoName, "%s.smk", pFilename); this->pSmackerMovie = OpenSmack(pVideoName); if ( !this->pSmackerMovie ) { Unload(); sprintf(pVideoName, "Can't load file - anims\\%s.smk", pFilename); MessageBoxA(0, pVideoName, "Smacker Error", 0); return; } this->uMovieFormat = 1; strcpy(this->pCurrentMovieName, pFilename); this->uMovieFormatSwapped = 2; this->pSomeSmackerBuffer = (char *)malloc(this->pSmackerMovie->Width * this->pSmackerMovie->Height); if ( !this->pSomeSmackerBuffer ) { Unload(); sprintf(pVideoName, "Can't allocate memory for buffer"); MessageBoxA(0, pVideoName, "Smacker Error", 0); return; } SmackToBuffer(this->pSmackerMovie, 0, 0, this->pSmackerMovie->Width, this->pSmackerMovie->Height, this->pSomeSmackerBuffer, 0); v10 = SmackCheckSurfaceFromat(); if ( a4 ) { v10 |= SMACKBLIT2X; if (uCPUSpeed >= 165 ) v10 |= SMACKBLIT2XSMOOTHING; else Log::Warning(L"Smacker seems to use lower resolution because it thinks CPU is slow"); } this->pSmackMovieBlit = SmackBlitOpen(v10); if ( !this->pSmackMovieBlit ) { Unload(); sprintf(pVideoName, "Failed to open Blit API"); MessageBoxA(0, pVideoName, "Smacker Error", 0); return; } }*/ } } //----- (004BF5B2) -------------------------------------------------------- void VideoPlayer::_4BF5B2() { //__debugbreak(); /*if ( this->uMovieFormat == 2 ) { BinkGoto(pBinkMovie, 1, 0); BinkDoFrame(pBinkMovie); BinkNextFrame(pBinkMovie); } else { if ( this->uMovieFormat != 1 ) return; SmackGoto(pSmackerMovie, 1); if ( pVersion->pVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || pVersion->pVersionInfo.dwMajorVersion != 4 ) { SmackDoFrame(pSmackerMovie); SmackNextFrame(pSmackerMovie); } }*/ pMouse->_469E24(); if ( window_SpeakInHouse && window_SpeakInHouse->ptr_1C == (void *)165 && !this->pMovie)//!this->pSmackerMovie ) { bGameoverLoop = true; HouseDialogPressCloseBtn(); window_SpeakInHouse->Release(); pParty->uFlags &= 0xFFFFFFFD; if ( EnterHouse(HOUSE_BODY_GUILD_ERATHIA) ) { pAudioPlayer->PlaySound(SOUND_Invalid, 0, 0, -1, 0, 0, 0, 0); window_SpeakInHouse = GUIWindow::Create(0, 0, window->GetWidth(), window->GetHeight(), WINDOW_HouseInterior, 165, 0); window_SpeakInHouse->CreateButton(0x3Du, 0x1A8u, 0x1Fu, 0, 2, 94, UIMSG_SelectCharacter, 1, 0x31, "", 0); window_SpeakInHouse->CreateButton(0xB1u, 0x1A8u, 0x1Fu, 0, 2, 94, UIMSG_SelectCharacter, 2, 0x32, "", 0); window_SpeakInHouse->CreateButton(0x124u, 0x1A8u, 0x1Fu, 0, 2, 94, UIMSG_SelectCharacter, 3, 0x33, "", 0); window_SpeakInHouse->CreateButton(0x197u, 0x1A8u, 0x1Fu, 0, 2, 94, UIMSG_SelectCharacter, 4, 0x34, "", 0); } bGameoverLoop = 0; } } //----- (004BF73A) -------------------------------------------------------- void VideoPlayer::SelectMovieType() { char Source[32]; // [sp+Ch] [bp-40h]@1 strcpy(Source, this->pCurrentMovieName); Unload(); if ( this->uMovieFormatSwapped == 1 ) OpenHouseMovie(Source, LOBYTE(this->bLoopPlaying)); else if ( this->uMovieFormatSwapped == 2 ) OpenGlobalMovie(Source, LOBYTE(this->bLoopPlaying), 1); else __debugbreak(); } //----- (004BF8F6) -------------------------------------------------------- void VideoPlayer::PlayDeathMovie() { bStopBeforeSchedule = 0; pResetflag = 0; PlayFullscreenMovie(MOVIE_Death, true); //pGame->pCShow->PlayMovie(MOVIE_Death, 1); } //----- (004BE6F5) -------------------------------------------------------- VideoPlayer::VideoPlayer() : bBufferLoaded(0), //pBinkMovie(nullptr), pBinkBuffer(nullptr), //pSmackerMovie(nullptr), pSmackerBuffer(nullptr), pSmackMovieBlit(nullptr) { //RGBTexture::RGBTexture(&pVideoPlayer->pVideoFrame); bStopBeforeSchedule = false; pResetflag = 0; pPlayer = new MultimediaPlayer(); pPlayer->Initialize(); pMovie = nullptr; //pBinkMovie = nullptr; } bool MultimediaPlayer::libavcodec_initialized = false; void MultimediaPlayer::Logger(void *, int, const char *format, va_list args) { char msg[1024]; vsprintf(msg, format, args); DWORD w; WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), msg, lstrlenA(msg), &w, nullptr); } int VideoPlayer::readFunction(void* opaque, uint8_t* buf, int buf_size) { HANDLE stream = (HANDLE)opaque; //int numBytes = stream->read((char*)buf, buf_size); int numBytes; ReadFile(stream, (char *)buf, buf_size, (LPDWORD)&numBytes, NULL); return numBytes; } int64_t VideoPlayer::seekFunction(void* opaque, int64_t offset, int whence) { if (whence == AVSEEK_SIZE) return pVideoPlayer->uSize; HANDLE h = (HANDLE)opaque; LARGE_INTEGER li; li.QuadPart = offset; if (!SetFilePointerEx(h, li, (PLARGE_INTEGER)&li, FILE_BEGIN)) return -1; return li.QuadPart; } void VideoPlayer::LoadMovie(const char * pFilename) { char pVideoNameBik[120]; // [sp+Ch] [bp-28h]@2 char pVideoNameSmk[120]; // [sp+Ch] [bp-28h]@2 sprintf(pVideoNameBik, "%s.bik", pFilename); sprintf(pVideoNameSmk, "%s.smk", pFilename); for (uint i = 0; i < uNumMightVideoHeaders; ++i) { //no BIK in MightVid /* if (!_stricmp(pVideoNameBik, pMightVideoHeaders[i].pVideoName)) { hVidFile = hMightVid; uOffset = pMightVideoHeaders[i].uFileOffset; uSize = pMightVideoHeaders[i + 1].uFileOffset - uOffset; this->uMovieFormat = 2; this->uMovieFormatSwapped = 1; } */ if (!_stricmp(pVideoNameSmk, pMightVideoHeaders[i].pVideoName)) { hVidFile = hMightVid; uOffset = pMightVideoHeaders[i].uFileOffset; uSize = pMightVideoHeaders[i + 1].uFileOffset - uOffset; this->uMovieFormat = 1; this->uMovieFormatSwapped = 2; } } for (uint i = 0; i < uNumMagicVideoHeaders; ++i) { if (!_stricmp(pVideoNameBik, pMagicVideoHeaders[i].pVideoName)) { hVidFile = hMagicVid; uOffset = pMagicVideoHeaders[i].uFileOffset; uSize = pMagicVideoHeaders[i + 1].uFileOffset - uOffset; this->uMovieFormat = 2; this->uMovieFormatSwapped = 1; } if (!_stricmp(pVideoNameSmk, pMagicVideoHeaders[i].pVideoName)) { hVidFile = hMagicVid; uOffset = pMagicVideoHeaders[i].uFileOffset; uSize = pMagicVideoHeaders[i + 1].uFileOffset - uOffset; this->uMovieFormat = 1; this->uMovieFormatSwapped = 2; } } if (!hVidFile) { Unload(); MessageBoxA(0, "VideoPlayer error", "VideoPlayer Error", 0); return; } SetFilePointer(hVidFile, uOffset, 0, FILE_BEGIN); strcpy(this->pCurrentMovieName, pFilename); auto hwnd = pVideoPlayer->window->GetApiHandle(); RECT rc_client; GetClientRect(hwnd, &rc_client); int client_width = rc_client.right - rc_client.left, client_height = rc_client.bottom - rc_client.top; pMovie = pPlayer->LoadMovieFromLOD(hVidFile, &readFunction, &seekFunction, client_width, client_height); }