Przeglądaj źródła

Mingw build with ffmpeg
(*) get rid of BIK SMK dlls
(-) missing sound
(-) spellbook is scaled to fullscreen

AlexVinS 11 lat temu
rodzic
commit
c71237bba3
3 zmienionych plików z 7 dodań i 720 usunięć
  1. 0 547
      client/CVideoHandler.cpp
  2. 1 173
      client/CVideoHandler.h
  3. 6 0
      client/VCMI_client.cbp

+ 0 - 547
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<int>(data->width, dst->w - x), h = std::min<int>(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<h-1; j++)	// why -1 ?
-		{
-			for ( int i=w-1; i>=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<h-1; j++)	// why -1 ?
-		{
-			for ( int i=w-1; i>=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<char*>(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<char*>(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

+ 1 - 173
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 <windows.h>
-
-#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
+

+ 6 - 0
client/VCMI_client.cbp

@@ -104,6 +104,7 @@
 			<Add directory="$(#boost.include)" />
 			<Add directory="../include" />
 			<Add directory="../client" />
+			<Add directory="$(#ffmpeg.include)" />
 		</Compiler>
 		<Linker>
 			<Add option="-lole32" />
@@ -115,8 +116,13 @@
 			<Add option="-lboost_thread$(#boost.libsuffix)" />
 			<Add option="-lboost_chrono$(#boost.libsuffix)" />
 			<Add option="-lVCMI_lib" />
+			<Add option="-lavcodec.dll" />
+			<Add option="-lavformat.dll" />
+			<Add option="-lswscale.dll" />
+			<Add option="-lavutil.dll" />
 			<Add directory="$(#boost.lib32)" />
 			<Add directory="../" />
+			<Add directory="$(#ffmpeg.lib)" />
 		</Linker>
 		<Unit filename="../CCallback.cpp" />
 		<Unit filename="../CCallback.h" />