From c71237bba3701498625ec5dc44d3d5975b7be1f4 Mon Sep 17 00:00:00 2001 From: AlexVinS Date: Tue, 8 Jul 2014 16:40:25 +0400 Subject: [PATCH] Mingw build with ffmpeg (*) get rid of BIK SMK dlls (-) missing sound (-) spellbook is scaled to fullscreen --- client/CVideoHandler.cpp | 547 --------------------------------------- client/CVideoHandler.h | 174 +------------ client/VCMI_client.cbp | 6 + 3 files changed, 7 insertions(+), 720 deletions(-) diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index 5f48faaba..88d0f4c9f 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -23,553 +23,7 @@ static bool keyDown() } #endif -#if defined(_WIN32) && (_MSC_VER < 1800 || !defined(USE_FFMPEG)) -void checkForError(bool throwing = true) -{ - int error = GetLastError(); - if(!error) - return; - - logGlobal->errorStream() << "Error " << error << " encountered!"; - std::string msg; - char* pTemp = nullptr; - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - nullptr, error, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPSTR)&pTemp, 1, nullptr ); - logGlobal->errorStream() << "Error: " << pTemp; - msg = pTemp; - LocalFree( pTemp ); - pTemp = nullptr; - if(throwing) - throw std::runtime_error(msg); -} - -void blitBuffer(char *buffer, int x, int y, int w, int h, SDL_Surface *dst) -{ - const int bpp = dst->format->BytesPerPixel; - char *dest; - for(int i = h; i > 0; i--) - { - dest = (char*)dst->pixels + dst->pitch*(y+h-i) + x*dst->format->BytesPerPixel; - memcpy(dest, buffer, bpp*w); - buffer += bpp*w; - } -} - -void DLLHandler::Instantiate(const char *filename) -{ - name = filename; - dll = LoadLibraryA(filename); - if(!dll) - { - logGlobal->errorStream() << "Failed loading " << filename; - checkForError(true); - } -} - -void *DLLHandler::FindAddress(const char *symbol) -{ - void *ret; - - if(!dll) - { - logGlobal->errorStream() << "Cannot look for " << symbol << " because DLL hasn't been appropriately loaded!"; - return nullptr; - } - ret = (void*) GetProcAddress(dll,symbol); - if(!ret) - { - logGlobal->errorStream() << "Failed to find " << symbol << " in " << name; - checkForError(); - } - return ret; -} - -DLLHandler::~DLLHandler() -{ - if(dll) - { - if(!FreeLibrary(dll)) - { - logGlobal->errorStream() << "Failed to free " << name; - checkForError(); - } - } -} - -DLLHandler::DLLHandler() -{ - dll = nullptr; -} - -CBIKHandler::CBIKHandler() -{ - Instantiate("BINKW32.DLL"); - //binkGetError = FindAddress("_BinkGetError@0"); - binkOpen = (BinkOpen)FindAddress("_BinkOpen@8"); - binkSetSoundSystem = (BinkSetSoundSystem)FindAddress("_BinkSetSoundSystem@8"); - //getPalette = (BinkGetPalette)FindAddress("_BinkGetPalette@4"); - binkNextFrame = (BinkNextFrame)FindAddress("_BinkNextFrame@4"); - binkDoFrame = (BinkDoFrame)FindAddress("_BinkDoFrame@4"); - binkCopyToBuffer = (BinkCopyToBuffer)FindAddress("_BinkCopyToBuffer@28"); - binkWait = (BinkWait)FindAddress("_BinkWait@4"); - binkClose = (BinkClose)FindAddress("_BinkClose@4"); - - - hBinkFile = nullptr; - hBink = nullptr; - - buffer = nullptr; - bufferSize = 0; -} - -bool CBIKHandler::open(std::string name) -{ - hBinkFile = CreateFileA - ( - name.c_str(), // file name - GENERIC_READ, // access mode - FILE_SHARE_READ, // share mode - nullptr, // Security Descriptor - OPEN_EXISTING, // how to create - FILE_ATTRIBUTE_NORMAL,//FILE_FLAG_SEQUENTIAL_SCAN, // file attributes - 0 // handle to template file - ); - - if(hBinkFile == INVALID_HANDLE_VALUE) - { - logGlobal->errorStream() << "BIK handler: failed to open " << name; - goto checkErrorAndClean; - } - //GCC wants scope of waveout to don`t cross labels/swith/goto - { - void *waveout = GetProcAddress(dll,"_BinkOpenWaveOut@4"); - if(waveout) - binkSetSoundSystem(waveout,nullptr); - - } - - hBink = binkOpen(hBinkFile, 0x8a800000); - if(!hBink) - { - logGlobal->errorStream() << "bink failed to open " << name; - goto checkErrorAndClean; - } - - allocBuffer(); - return true; - -checkErrorAndClean: - CloseHandle(hBinkFile); - hBinkFile = nullptr; - checkForError(); - throw std::runtime_error("BIK failed opening video!"); -} - -void CBIKHandler::show( int x, int y, SDL_Surface *dst, bool update ) -{ - const int w = hBink->width, - h = hBink->height, - Bpp = dst->format->BytesPerPixel; - - int mode = -1; - - //screen color depth might have changed... (eg. because F4) - if(bufferSize != w * h * Bpp) - { - freeBuffer(); - allocBuffer(Bpp); - } - - switch(Bpp) - { - case 2: - mode = 3; //565, mode 2 is 555 probably - break; - case 3: - mode = 0; - break; - case 4: - mode = 1; - break; - default: - return; //not supported screen depth - } - - binkDoFrame(hBink); - binkCopyToBuffer(hBink, buffer, w*Bpp, h, 0, 0, mode); - blitBuffer(buffer, x, y, w, h, dst); - if(update) - SDL_UpdateRect(dst, x, y, w, h); -} - -bool CBIKHandler::nextFrame() -{ - binkNextFrame(hBink); - return true; -} - -void CBIKHandler::close() -{ - binkClose(hBink); - hBink = nullptr; - CloseHandle(hBinkFile); - hBinkFile = nullptr; - delete [] buffer; - - buffer = nullptr; - bufferSize = 0; -} - -bool CBIKHandler::wait() -{ - return binkWait(hBink); -} - -int CBIKHandler::curFrame() const -{ - return hBink->currentFrame; -} - -int CBIKHandler::frameCount() const -{ - return hBink->frameCount; -} - -void CBIKHandler::redraw( int x, int y, SDL_Surface *dst, bool update ) -{ - int w = hBink->width, h = hBink->height; - blitBuffer(buffer, x, y, w, h, dst); - if(update) - SDL_UpdateRect(dst, x, y, w, h); -} - -void CBIKHandler::allocBuffer(int Bpp) -{ - if(!Bpp) Bpp = screen->format->BytesPerPixel; - - bufferSize = hBink->width * hBink->height * Bpp; - buffer = new char[bufferSize]; -} - -void CBIKHandler::freeBuffer() -{ - delete [] buffer; - buffer = nullptr; - bufferSize = 0; -} - -bool CSmackPlayer::nextFrame() -{ - ptrSmackNextFrame(data); - return true; -} - -bool CSmackPlayer::wait() -{ - return ptrSmackWait(data); -} - -CSmackPlayer::CSmackPlayer() : data(nullptr) -{ - Instantiate("smackw32.dll"); - ptrSmackNextFrame = (SmackNextFrame)FindAddress("_SmackNextFrame@4"); - ptrSmackWait = (SmackWait)FindAddress("_SmackWait@4"); - ptrSmackDoFrame = (SmackDoFrame)FindAddress("_SmackDoFrame@4"); - ptrSmackToBuffer = (SmackToBuffer)FindAddress("_SmackToBuffer@28"); - ptrSmackOpen = (SmackOpen)FindAddress("_SmackOpen@12"); - ptrSmackSoundOnOff = (SmackSoundOnOff)FindAddress("_SmackSoundOnOff@8"); - ptrSmackClose = (SmackClose)FindAddress("_SmackClose@4"); - ptrVolumePan = (SmackVolumePan)FindAddress("_SmackVolumePan@16"); -} - -CSmackPlayer::~CSmackPlayer() -{ - if(data) - close(); -} - -void CSmackPlayer::close() -{ - ptrSmackClose(data); - data = nullptr; -} - -bool CSmackPlayer::open( std::string name ) -{ - Uint32 flags[2] = {0xff400, 0xfe400}; - - data = ptrSmackOpen( (void*)name.c_str(), flags[1], -1); - if (!data) - { - logGlobal->errorStream() << "Smack cannot open " << name; - checkForError(); - throw std::runtime_error("SMACK failed opening video"); - } - - buffer = new char[data->width*data->height*2]; - buf = buffer+data->width*(data->height-1)*2; // adjust pointer position for later use by 'SmackToBuffer' - - //ptrVolumePan(data, 0xfe000, 3640 * GDefaultOptions.musicVolume / 11, 0x8000); //set volume - return true; -} - -void CSmackPlayer::show( int x, int y, SDL_Surface *dst, bool update) -{ - int w = data->width; - int stripe = (-w*2) & (~3); - - //put frame to the buffer - ptrSmackToBuffer(data, 0, 0, stripe, w, buf, 0x80000000); - ptrSmackDoFrame(data); - redraw(x, y, dst, update); -} - -int CSmackPlayer::curFrame() const -{ - return data->currentFrame; -} - -int CSmackPlayer::frameCount() const -{ - return data->frameCount; -} - -void CSmackPlayer::redraw( int x, int y, SDL_Surface *dst, bool update ) -{ - int w = std::min(data->width, dst->w - x), h = std::min(data->height, dst->h - y); - /* Lock the screen for direct access to the pixels */ - if ( SDL_MUSTLOCK(dst) ) - { - if ( SDL_LockSurface(dst) < 0 ) - { - fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); - return; - } - } - - // draw the frame - Uint16* addr = (Uint16*) (buffer+w*(h-1)*2-2); - if(dst->format->BytesPerPixel >= 3) - { - for( int j=0; j=0; i--) - { - Uint16 pixel = *addr; - - Uint8 *p = (Uint8 *)dst->pixels + (j+y) * dst->pitch + (i + x) * dst->format->BytesPerPixel; - p[2] = ((pixel & 0x7c00) >> 10) * 8; - p[1] = ((pixel & 0x3e0) >> 5) * 8; - p[0] = ((pixel & 0x1F)) * 8; - - addr--; - } - } - } - else if(dst->format->BytesPerPixel == 2) - { - for( int j=0; j=0; i--) - { - //convert rgb 555 to 565 - Uint16 pixel = *addr; - Uint16 *p = (Uint16 *)((Uint8 *)dst->pixels + (j+y) * dst->pitch + (i + x) * dst->format->BytesPerPixel); - *p = (pixel & 0x1F) - + ((pixel & 0x3e0) << 1) - + ((pixel & 0x7c00) << 1); - - addr--; - } - } - } - - if ( SDL_MUSTLOCK(dst) ) - { - SDL_UnlockSurface(dst); - } - - if(update) - SDL_UpdateRect(dst, x, y, w, h); -} - -CVideoPlayer::CVideoPlayer() -{ - current = nullptr; -} - -CVideoPlayer::~CVideoPlayer() -{ -} - -bool CVideoPlayer::open(std::string name) -{ - fname = name; - first = true; - - try - { - // Extract video from video.vid so we can play it. - // We can handle only videos in form of single file, no archive support yet. - { - ResourceID videoID = ResourceID("VIDEO/" + name, EResType::VIDEO); - auto data = CResourceHandler::get()->load(videoID)->readAll(); - - // try to determine video format using magic number from header (3 bytes, SMK or BIK) - std::string magic(reinterpret_cast(data.first.get()), 3); - if (magic == "BIK") - current = &bikPlayer; - else if (magic == "SMK") - current = &smkPlayer; - else - throw std::runtime_error("Unknown video format: " + magic); - - std::ofstream out(name, std::ofstream::binary); - out.exceptions(std::ifstream::failbit | std::ifstream::badbit); - out.write(reinterpret_cast(data.first.get()), data.second); - } - - current->open(name); - return true; - } - catch(std::exception &e) - { - current = nullptr; - logGlobal->warnStream() << "Failed to open video file " << name << ": " << e.what(); - } - - return false; -} - -void CVideoPlayer::close() -{ - if(!current) - { - logGlobal->warnStream() << "Closing no opened player...?"; - return; - } - - current->close(); - current = nullptr; - if(!DeleteFileA(fname.c_str())) - { - logGlobal->errorStream() << "Cannot remove temporarily extracted video file: " << fname; - checkForError(false); - } - fname.clear(); -} - -bool CVideoPlayer::nextFrame() -{ - if(current) - { - current->nextFrame(); - return true; - } - else - return false; -} - -void CVideoPlayer::show(int x, int y, SDL_Surface *dst, bool update) -{ - if(current) - current->show(x, y, dst, update); -} - -bool CVideoPlayer::wait() -{ - if(current) - return current->wait(); - else - return false; -} - -int CVideoPlayer::curFrame() const -{ - if(current) - return current->curFrame(); - else - return -1; -} - -int CVideoPlayer::frameCount() const -{ - if(current) - return current->frameCount(); - else - return -1; -} - -bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey) -{ - if(!open(name)) - return false; - - bool ret = playVideo(x, y, dst, stopOnKey); - close(); - return ret; -} - -void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool forceRedraw, bool update ) -{ - if(!current) - return; - - bool w = false; - if(!first) - { - w = wait(); //check if should keep current frame - if(!w) - nextFrame(); - } - else - { - first = false; - } - - - - if(!w) - { - show(x,y,dst,update); - } - else if (forceRedraw) - { - redraw(x, y, dst, update); - } -} - -void CVideoPlayer::redraw( int x, int y, SDL_Surface *dst, bool update ) -{ - if(current) - current->redraw(x, y, dst, update); -} - -bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey) -{ - if(!current) - return false; - - int frame = 0; - while(frame < frameCount()) //play all frames - { - if(stopOnKey && keyDown()) - return false; - - if(!wait()) - { - show(x, y, dst); - nextFrame(); - frame++; - } - SDL_Delay(20); - } - - return true; -} - -#else #ifdef _MSC_VER #pragma comment(lib, "avcodec.lib") @@ -1029,4 +483,3 @@ CVideoPlayer::~CVideoPlayer() #endif -#endif diff --git a/client/CVideoHandler.h b/client/CVideoHandler.h index a300d93b9..a826aefd1 100644 --- a/client/CVideoHandler.h +++ b/client/CVideoHandler.h @@ -43,178 +43,6 @@ public: }; -#if defined(_WIN32) && (_MSC_VER < 1800 || !defined(USE_FFMPEG)) - -#define WIN32_LEAN_AND_MEAN //excludes rarely used stuff from windows headers - delete this line if something is missing -#include - -#pragma pack(push,1) -struct BINK_STRUCT -{ - si32 width; - si32 height; - si32 frameCount; - si32 currentFrame; - si32 lastFrame; - si32 FPSMul; - si32 FPSDiv; - si32 unknown0; - ui8 flags; - ui8 unknown1[260]; - si32 CurPlane; // current plane - void *plane0; // posi32er to plane 0 - void *plane1; // posi32er to plane 1 - si32 unknown2; - si32 unknown3; - si32 yWidth; // Y plane width - si32 yHeight; // Y plane height - si32 uvWidth; // U&V plane width - si32 uvHeight; // U&V plane height -}; -#pragma pack(pop) - -typedef BINK_STRUCT* HBINK; - -class DLLHandler -{ -public: - std::string name; - HINSTANCE dll; - void Instantiate(const char *filename); - const char *GetLibExtension(); - void *FindAddress(const char *symbol); - - DLLHandler(); - virtual ~DLLHandler(); //d-tor -}; - -typedef void*(__stdcall* BinkSetSoundSystem)(void * soundfun, void*); -typedef HBINK(__stdcall* BinkOpen)(HANDLE bikfile, int flags); -typedef void(__stdcall* BinkClose)(HBINK); -//typedef si32(__stdcall* BinkGetPalette)(HBINK); -typedef void(__stdcall* BinkNextFrame)(HBINK); -typedef void(__stdcall* BinkDoFrame)(HBINK); -typedef ui8(__stdcall* BinkWait)(HBINK); -typedef si32(__stdcall* BinkCopyToBuffer)(HBINK, void* buffer, int stride, int height, int x, int y, int mode); - -class CBIKHandler : public DLLHandler, public IVideoPlayer -{ - void allocBuffer(int Bpp = 0); - void freeBuffer(); -public: - HANDLE hBinkFile; - HBINK hBink; - char * buffer; - int bufferSize; - BinkSetSoundSystem binkSetSoundSystem; - BinkOpen binkOpen; - //BinkGetPalette getPalette; - BinkNextFrame binkNextFrame; - BinkDoFrame binkDoFrame; - BinkCopyToBuffer binkCopyToBuffer; - BinkWait binkWait; - BinkClose binkClose; - - CBIKHandler(); - bool open(std::string name); - void close(); - bool nextFrame(); - void show(int x, int y, SDL_Surface *dst, bool update = true); - void redraw(int x, int y, SDL_Surface *dst, bool update = true); //reblits buffer - bool wait(); - int curFrame() const; - int frameCount() const; -}; - -//////////SMK Player /////////////////////////////////////////////////////// - -struct SmackStruct -{ - si32 version; - si32 width; - si32 height; - si32 frameCount; - si32 mspf; - ui8 unk1[88]; - ui8 palette[776]; - si32 currentFrame; // Starting with 0 - ui8 unk[56]; - ui32 fileHandle; // exact type is HANDLE in windows.h -}; - -// defines function pointer types -typedef SmackStruct* (__stdcall* SmackOpen)(void* , ui32, si32 ); -typedef int (__stdcall* SmackDoFrame)( SmackStruct * ); -typedef void (__stdcall * SmackGoto )(SmackStruct *, int frameNumber); -typedef void (__stdcall* SmackNextFrame)(SmackStruct*); -typedef void (__stdcall* SmackClose)(SmackStruct*); -typedef void (__stdcall* SmackToBuffer) (SmackStruct*, int, int, int, int, char *, ui32); -typedef bool (__stdcall* SmackWait)(SmackStruct*); -typedef void (__stdcall* SmackSoundOnOff) (SmackStruct*, bool); -typedef int (__stdcall* SmackVolumePan)(SmackStruct *, int SmackTrack, int volume, int pan); - - - -class CSmackPlayer: public DLLHandler, public IVideoPlayer -{ -public: - SmackOpen ptrSmackOpen; - SmackDoFrame ptrSmackDoFrame; - SmackToBuffer ptrSmackToBuffer; - SmackNextFrame ptrSmackNextFrame; - SmackWait ptrSmackWait; - SmackSoundOnOff ptrSmackSoundOnOff; - SmackClose ptrSmackClose; - SmackVolumePan ptrVolumePan; - - char *buffer, *buf; - SmackStruct* data; - - CSmackPlayer(); - ~CSmackPlayer(); - bool open(std::string name); - void close(); - bool nextFrame(); - void show(int x, int y, SDL_Surface *dst, bool update = true); - void redraw(int x, int y, SDL_Surface *dst, bool update = true); //reblits buffer - bool wait(); - int curFrame() const; - int frameCount() const; -}; - -class CVidHandler; - -class CVideoPlayer : public IMainVideoPlayer -{ -private: - - CSmackPlayer smkPlayer; //for .SMK - CBIKHandler bikPlayer; //for .BIK - IVideoPlayer *current; //points to bik or smk player, appropriate to type of currently played video - - bool first; //are we about to display the first frame (blocks update) -public: - - CVideoPlayer(); //c-tor - ~CVideoPlayer(); //d-tor - - - bool open(std::string name); - void close(); - bool nextFrame(); //move animation to the next frame - void show(int x, int y, SDL_Surface *dst, bool update = true); //blit current frame - void redraw(int x, int y, SDL_Surface *dst, bool update = true); //reblits buffer - void update(int x, int y, SDL_Surface *dst, bool forceRedraw, bool update = true); //moves to next frame if appropriate, and blits it or blits only if redraw paremeter is set true - bool wait(); //true if we should wait before displaying next frame (for keeping FPS) - int curFrame() const; //current frame number <1, framecount> - int frameCount() const; - - bool openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey = false); //opens video, calls playVideo, closes video; returns playVideo result (if whole video has been played) - bool playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey = false); //plays whole opened video; returns: true when whole video has been shown, false when it has been interrupted -}; - -#else - #ifndef DISABLE_VIDEO #include "../lib/filesystem/CInputStream.h" @@ -285,4 +113,4 @@ public: }; #endif -#endif + diff --git a/client/VCMI_client.cbp b/client/VCMI_client.cbp index 5a563e035..2ff9c874d 100644 --- a/client/VCMI_client.cbp +++ b/client/VCMI_client.cbp @@ -104,6 +104,7 @@ + @@ -115,8 +116,13 @@ + + + + +