1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-19 21:10:12 +02:00

Finished BIK handler. Refactored CVideoPlayer. Added intro and main menu animation. (Win only).

This commit is contained in:
Michał W. Urbańczyk 2009-06-24 06:56:36 +00:00
parent 6cf3823154
commit 60f7048662
5 changed files with 469 additions and 307 deletions

View File

@ -70,6 +70,67 @@ TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
void processCommand(const std::string &message, CClient *&client);
static void setScreenRes(int w, int h, int bpp, bool fullscreen);
void dispose();
void playIntro();
void init()
{
timeHandler tmh, pomtime;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
int rmask = 0xff000000;int gmask = 0x00ff0000;int bmask = 0x0000ff00;int amask = 0x000000ff;
#else
int rmask = 0x000000ff; int gmask = 0x0000ff00; int bmask = 0x00ff0000; int amask = 0xff000000;
#endif
CSDL_Ext::std32bppSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32, rmask, gmask, bmask, amask);
tlog0 << "\tInitializing minors: " << pomtime.getDif() << std::endl;
TTF_Init();
atexit(TTF_Quit);
TNRB16 = TTF_OpenFont("Fonts" PATHSEPARATOR "tnrb.ttf",16);
GEOR13 = TTF_OpenFont("Fonts" PATHSEPARATOR "georgia.ttf",13);
GEOR16 = TTF_OpenFont("Fonts" PATHSEPARATOR "georgia.ttf",16);
GEORXX = TTF_OpenFont("Fonts" PATHSEPARATOR "tnrb.ttf",22);
GEORM = TTF_OpenFont("Fonts" PATHSEPARATOR "georgia.ttf",10);
if(! (TNRB16 && GEOR16 && GEORXX && GEORM))
{
tlog1 << "One of the fonts couldn't be loaded!\n";
exit(-1);
}
THC tlog0<<"\tInitializing fonts: "<<pomtime.getDif()<<std::endl;
//initializing audio
// Note: because of interface button range, volume can only be a
// multiple of 11, from 0 to 99.
CGI->soundh = new CSoundHandler;
CGI->soundh->init();
CGI->soundh->setVolume(88);
CGI->musich = new CMusicHandler;
CGI->musich->init();
CGI->musich->setVolume(88);
tlog0<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
tlog0<<"Initializing screen, fonts and sound handling: "<<tmh.getDif()<<std::endl;
initDLL(::console,logfile);
CGI->setFromLib();
CGI->soundh->initCreaturesSounds(CGI->creh->creatures);
CGI->soundh->initSpellsSounds(CGI->spellh->spells);
tlog0<<"Initializing VCMI_Lib: "<<tmh.getDif()<<std::endl;
pomtime.getDif();
CGI->curh = new CCursorHandler;
CGI->curh->initCursor();
CGI->curh->show();
tlog0<<"Screen handler: "<<pomtime.getDif()<<std::endl;
pomtime.getDif();
graphics = new Graphics();
graphics->loadHeroAnim();
tlog0<<"\tMain graphics: "<<tmh.getDif()<<std::endl;
tlog0<<"Initializing game graphics: "<<tmh.getDif()<<std::endl;
CMessage::init();
tlog0<<"Message handler: "<<tmh.getDif()<<std::endl;
CPG = new CPreGame(); //main menu and submenus
tlog0<<"Initialization CPreGame (together): "<<tmh.getDif()<<std::endl;
}
#ifndef __GNUC__
int _tmain(int argc, _TCHAR* argv[])
@ -77,9 +138,8 @@ int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char** argv)
#endif
{
tlog0 << "Starting... " << std::endl;
THC timeHandler tmh, total, pomtime;
timeHandler total, pomtime;
CClient *client = NULL;
std::cout.flags(std::ios::unitbuf);
logfile = new std::ofstream("VCMI_Client_log.txt");
@ -95,77 +155,29 @@ int main(int argc, char** argv)
srand ( time(NULL) );
CPG=NULL;
atexit(SDL_Quit);
CGameInfo * cgi = CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler itp.)
CGI = new CGameInfo; //contains all global informations about game (texts, lodHandlers, map handler itp.)
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO)==0)
{
setScreenRes(800,600,conf.cc.bpp,conf.cc.fullscreen);
tlog0 <<"\tInitializing screen: "<<pomtime.getDif() << std::endl;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
int rmask = 0xff000000;int gmask = 0x00ff0000;int bmask = 0x0000ff00;int amask = 0x000000ff;
#else
int rmask = 0x000000ff; int gmask = 0x0000ff00; int bmask = 0x00ff0000; int amask = 0xff000000;
#endif
CSDL_Ext::std32bppSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32, rmask, gmask, bmask, amask);
tlog0 << "\tInitializing minors: " << pomtime.getDif() << std::endl;
TTF_Init();
TNRB16 = TTF_OpenFont("Fonts" PATHSEPARATOR "tnrb.ttf",16);
GEOR13 = TTF_OpenFont("Fonts" PATHSEPARATOR "georgia.ttf",13);
GEOR16 = TTF_OpenFont("Fonts" PATHSEPARATOR "georgia.ttf",16);
GEORXX = TTF_OpenFont("Fonts" PATHSEPARATOR "tnrb.ttf",22);
GEORM = TTF_OpenFont("Fonts" PATHSEPARATOR "georgia.ttf",10);
if(! (TNRB16 && GEOR16 && GEORXX && GEORM))
{
tlog1 << "One of the fonts couldn't be loaded!\n";
throw "One of the fonts couldn't be loaded!\n";
}
atexit(TTF_Quit);
THC tlog0<<"\tInitializing fonts: "<<pomtime.getDif()<<std::endl;
//initializing audio
// Note: because of interface button range, volume can only be a
// multiple of 11, from 0 to 99.
cgi->soundh = new CSoundHandler;
cgi->soundh->init();
cgi->soundh->setVolume(88);
cgi->musich = new CMusicHandler;
cgi->musich->init();
cgi->musich->setVolume(88);
tlog0<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
// Initialize video
cgi->videoh = new CVideoPlayer;
CGI->videoh = new CVideoPlayer;
tlog0<<"\tInitializing video: "<<pomtime.getDif()<<std::endl;
tlog0<<"Initializing screen, fonts and sound handling: "<<tmh.getDif()<<std::endl;
initDLL(::console,logfile);
CGI->setFromLib();
cgi->soundh->initCreaturesSounds(CGI->creh->creatures);
cgi->soundh->initSpellsSounds(CGI->spellh->spells);
tlog0<<"Initializing VCMI_Lib: "<<tmh.getDif()<<std::endl;
pomtime.getDif();
cgi->curh = new CCursorHandler;
cgi->curh->initCursor();
cgi->curh->show();
tlog0<<"Screen handler: "<<pomtime.getDif()<<std::endl;
pomtime.getDif();
graphics = new Graphics();
graphics->loadHeroAnim();
tlog0<<"\tMain graphics: "<<tmh.getDif()<<std::endl;
tlog0<<"Initializing game graphics: "<<tmh.getDif()<<std::endl;
CMessage::init();
tlog0<<"Message handler: "<<tmh.getDif()<<std::endl;
CPreGame * cpg = new CPreGame(); //main menu and submenus
tlog0<<"Initialization CPreGame (together): "<<tmh.getDif()<<std::endl;
//we can properly play intro only in the main thread, so we have to move loading to the separate thread
boost::thread loading(init);
playIntro();
SDL_FillRect(screen,NULL,0);
SDL_Flip(screen);
loading.join();
tlog0<<"Initialization of VCMI (together): "<<total.getDif()<<std::endl;
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
cgi->musich->playMusic(musicBase::mainMenu, -1);
StartInfo *options = new StartInfo(cpg->runLoop());
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
CGI->musich->playMusic(musicBase::mainMenu, -1);
CPG->showMainMenu();
StartInfo *options = new StartInfo(CPG->runLoop());
if(screen->w != conf.cc.resx || screen->h != conf.cc.resy)
{
@ -174,19 +186,19 @@ int main(int argc, char** argv)
CClient cl;
if(options->mode == 0) //new game
{
tmh.getDif();
pomtime.getDif();
char portc[10];
SDL_itoa(conf.cc.port,portc,10);
CClient::runServer(portc);
tlog0<<"Preparing shared memory and starting server: "<<tmh.getDif()<<std::endl;
tlog0<<"Preparing shared memory and starting server: "<<pomtime.getDif()<<std::endl;
tmh.getDif();pomtime.getDif();//reset timers
pomtime.getDif();//reset timers
CConnection *c=NULL;
//wait until server is ready
tlog0<<"Waiting for server... ";
cl.waitForServer();
tlog0 << tmh.getDif()<<std::endl;
tlog0 << pomtime.getDif()<<std::endl;
while(!c)
{
try
@ -200,10 +212,10 @@ int main(int argc, char** argv)
SDL_Delay(2000);
}
}
THC tlog0<<"\tConnecting to the server: "<<tmh.getDif()<<std::endl;
THC tlog0<<"\tConnecting to the server: "<<pomtime.getDif()<<std::endl;
cl.newGame(c,options);
client = &cl;
cgi->musich->stopMusic();
CGI->musich->stopMusic();
boost::thread t(boost::bind(&CClient::run,&cl));
}
else //load game
@ -212,7 +224,7 @@ int main(int argc, char** argv)
boost::algorithm::erase_last(fname,".vlgm1");
cl.load(fname);
client = &cl;
cgi->musich->stopMusic();
CGI->musich->stopMusic();
boost::thread t(boost::bind(&CClient::run,&cl));
}
@ -354,6 +366,18 @@ void processCommand(const std::string &message, CClient *&client)
}
}
//plays intro, ends when intro is over or button has been pressed (handles events)
void playIntro()
{
#ifdef _WIN32
if(CGI->videoh->openAndPlayVideo("3DOLOGO.SMK", 60, 40, screen, true))
{
CGI->videoh->openAndPlayVideo("AZVS.SMK", 60, 80, screen, true);
}
#endif
}
void dispose()
{
delete logfile;

View File

@ -23,6 +23,7 @@
#include <cstdlib>
#include "../lib/Connection.h"
#include "../hch/CMusicHandler.h"
#include "../hch/CVideoHandler.h"
/*
* CPreGame.cpp, part of VCMI engine
*
@ -1593,8 +1594,6 @@ CPreGame::CPreGame()
tlog0<<"\tCPreGame: scenario choice initialization: "<<tmh.getDif()<<std::endl;
initOptions();
tlog0<<"\tCPreGame: scenario options initialization: "<<tmh.getDif()<<std::endl;
showMainMenu();
tlog0<<"\tCPreGame: displaying main menu: "<<tmh.getDif()<<std::endl;
playerName="Player";
}
void CPreGame::initOptions()
@ -1777,7 +1776,7 @@ void CPreGame::showNewMenu()
SDL_BlitSurface(ourNewMenu->credits->ourImages[0].bitmap,NULL,screen,&ourNewMenu->lCredits);
SDL_BlitSurface(ourNewMenu->quit->ourImages[0].bitmap,NULL,screen,&ourNewMenu->lQuit);
//SDL_Flip(screen);
CSDL_Ext::update(screen);
//CSDL_Ext::update(screen);
first = true;
}
void CPreGame::initMainMenu()
@ -1835,7 +1834,7 @@ void CPreGame::showMainMenu()
SDL_BlitSurface(ourMainMenu->credits->ourImages[0].bitmap,NULL,screen,&ourMainMenu->lCredits);
SDL_BlitSurface(ourMainMenu->quit->ourImages[0].bitmap,NULL,screen,&ourMainMenu->lQuit);
//SDL_Flip(screen);
CSDL_Ext::update(screen);
//CSDL_Ext::update(screen);
}
void CPreGame::highlightButton(int which, int on)
{
@ -1870,7 +1869,7 @@ void CPreGame::highlightButton(int which, int on)
}
}
//SDL_Flip(screen);
CSDL_Ext::update(screen);
//CSDL_Ext::update(screen);
}
void CPreGame::showCenBox (std::string data)
{
@ -2054,6 +2053,11 @@ StartInfo CPreGame::runLoop()
SDL_Event sEvent;
ret.turnTime = 0;
#ifdef _WIN32
CGI->videoh->open("ACREDIT.SMK");
CGI->videoh->show(8, 105, screen, false);
#endif
while(run)
{
try
@ -2321,12 +2325,19 @@ StartInfo CPreGame::runLoop()
}
} HANDLE_EXCEPTION
#ifdef _WIN32
if(currentItems())
CGI->videoh->update(8, 105, screen, true, false);
#endif
CGI->curh->draw1();
SDL_Flip(screen);
CGI->curh->draw2();
SDL_Delay(20); //give time for other apps
}
ret.mode = (fromMenu==newGame) ? 0 : 1;
CGI->videoh->close();
return ret;
}
std::string CPreGame::buttonText(int which)
@ -2454,7 +2465,7 @@ void CPreGame::showLoadMenu()
SDL_BlitSurface(ourLoadMenu->credits->ourImages[0].bitmap,NULL,screen,&ourLoadMenu->lCredits);
SDL_BlitSurface(ourLoadMenu->quit->ourImages[0].bitmap,NULL,screen,&ourLoadMenu->lQuit);
//SDL_Flip(screen);
CSDL_Ext::update(screen);
//CSDL_Ext::update(screen);
first = true;
}

View File

@ -639,43 +639,76 @@ void CSpellWindow::deactivate()
void CSpellWindow::turnPageLeft()
{
// Note: video decoders are different, and one is buggy.
#ifdef _WIN32
const int y = pos.y+15;
#else
const int y = pos.y+14;
#endif
if (CGI->videoh->open("PGTRNLFT.SMK", pos.x+13, y)) {
while(CGI->videoh->nextFrame()) {
SDL_framerateDelay(LOCPLINT->mainFPSmng);
#ifndef _WIN32
if (CGI->videoh->open("PGTRNLFT.SMK", pos.x+13, pos.y+14))
{
while(CGI->videoh->nextFrame())
{
SDL_framerateDelay(LOCPLINT->mainFPSmng);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
#endif
}
CGI->videoh->close();
}
#else
CGI->videoh->openAndPlayVideo("PGTRNLFT.SMK", pos.x+13, pos.y+15, screen);
#endif
//#ifdef _WIN32
// const int y = pos.y+15;
//
//#endif
//
// if (CGI->videoh->open("PGTRNLFT.SMK", pos.x+13, y)) {
// while(CGI->videoh->nextFrame()) {
// SDL_framerateDelay(LOCPLINT->mainFPSmng);
//#ifndef _WIN32
// SDL_framerateDelay(LOCPLINT->mainFPSmng);
// SDL_framerateDelay(LOCPLINT->mainFPSmng);
//#endif
// }
// CGI->videoh->close();
// }
}
void CSpellWindow::turnPageRight()
{
// Note: video decoders are different, and one is buggy.
#ifdef _WIN32
const int y = pos.y+15;
#else
const int y = pos.y+14;
#endif
if (CGI->videoh->open("PGTRNRGH.SMK", pos.x+13, y)) {
while(CGI->videoh->nextFrame()) {
SDL_framerateDelay(LOCPLINT->mainFPSmng);
#ifndef _WIN32
if (CGI->videoh->open("PGTRNRGH.SMK", pos.x+13, pos.y+14))
{
while(CGI->videoh->nextFrame())
{
SDL_framerateDelay(LOCPLINT->mainFPSmng);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
#endif
}
CGI->videoh->close();
}
#else
CGI->videoh->openAndPlayVideo("PGTRNRGH.SMK", pos.x+13, pos.y+15, screen);
#endif
//#ifdef _WIN32
// const int y = pos.y+15;
//#else
// const int y = pos.y+14;
//#endif
//
// if (CGI->videoh->open("PGTRNRGH.SMK", pos.x+13, y)) {
// while(CGI->videoh->nextFrame()) {
// SDL_framerateDelay(LOCPLINT->mainFPSmng);
//#ifndef _WIN32
// SDL_framerateDelay(LOCPLINT->mainFPSmng);
// SDL_framerateDelay(LOCPLINT->mainFPSmng);
//#endif
// }
// CGI->videoh->close();
// }
}
CSpellWindow::SpellArea::SpellArea(SDL_Rect pos, CSpellWindow * owner)

View File

@ -7,14 +7,53 @@
#ifdef _WIN32
#include "../client/SDL_Extensions.h"
#include <boost/algorithm/string/predicate.hpp>
void checkForError(bool throwing = true)
{
#ifdef _WIN32
int error = GetLastError();
if(!error)
return;
tlog1 << "Error " << error << " encountered!\n";
std::string msg;
char* pTemp = NULL;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, error, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPSTR)&pTemp, 1, NULL );
tlog1 << "Error: " << pTemp << std::endl;
msg = pTemp;
LocalFree( pTemp );
pTemp = NULL;
if(throwing)
throw msg;
#endif
}
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;
#ifdef _WIN32
dll = LoadLibraryA(filename);
if(!dll)
{
tlog1 << "Failed loading " << filename << std::endl;
checkForError();
}
#else
dll = dlopen(filename,RTLD_LOCAL | RTLD_LAZY);
#endif
@ -22,11 +61,18 @@ void DLLHandler::Instantiate(const char *filename)
void *DLLHandler::FindAddress(const char *symbol)
{
void *ret;
#ifdef _WIN32
return (void*) GetProcAddress(dll,symbol);
ret = (void*) GetProcAddress(dll,symbol);
if(!ret)
{
tlog1 << "Failed to find " << symbol << " in " << name << std::endl;
checkForError();
}
#else
return (void *)dlsym(dll, symbol);
ret = (void *)dlsym(dll, symbol);
#endif
return ret;
}
DLLHandler::~DLLHandler()
@ -34,7 +80,11 @@ DLLHandler::~DLLHandler()
if(dll)
{
#ifdef _WIN32
FreeLibrary(dll);
if(!FreeLibrary(dll))
{
tlog1 << "Failed to free " << name << std::endl;
checkForError();
}
#else
dlclose(dll);
#endif
@ -46,29 +96,22 @@ DLLHandler::DLLHandler()
dll = NULL;
}
void checkForError()
{
#ifdef _WIN32
int error = GetLastError();
if(error)
tlog1 << "Error " << error << " encountered!\n";
#endif
}
CBIKHandler::CBIKHandler()
{
Instantiate("BINKW32.DLL");
binkGetError = FindAddress("_BinkGetError@0");
//binkGetError = FindAddress("_BinkGetError@0");
binkOpen = (BinkOpen)FindAddress("_BinkOpen@8");
binkSetSoundSystem = (BinkSetSoundSystem)FindAddress("_BinkSetSoundSystem@8");
getPalette = (BinkGetPalette)FindAddress("_BinkGetPalette@4");
//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 = NULL;
hBink = NULL;
}
void CBIKHandler::open(std::string name)
@ -86,36 +129,27 @@ void CBIKHandler::open(std::string name)
if(hBinkFile == INVALID_HANDLE_VALUE)
{
tlog1 << "BIK handler: failed to open " << name << std::endl;
checkForError();
return ;
return;
}
void *waveout = FindAddress("_BinkOpenWaveOut@4");
void *waveout = GetProcAddress(dll,"_BinkOpenWaveOut@4");
if(waveout)
binkSetSoundSystem(waveout,NULL);
hBink = binkOpen(hBinkFile, 0x8a800000);
width = hBink->width;
height = hBink->height;
buffer = new char[width * height * 3];
buffer = new char[hBink->width * hBink->width * 3];
}
void CBIKHandler::show( int x, int y, SDL_Surface *dst )
void CBIKHandler::show( int x, int y, SDL_Surface *dst, bool update )
{
int w = hBink->width, h = hBink->height;
//memset(buffer,0,w * h * 3);
binkDoFrame(hBink);
binkCopyToBuffer(hBink, buffer, w*3, h, 0, 0, 0);
char *src = buffer;
char *dest;
for(int i = h; i > 0; i--)
{
dest = (char*)dst->pixels + dst->pitch*(h-i) + x*dst->format->BytesPerPixel;
memcpy(dest,src,3*w);
src += 3*w;
}
SDL_UpdateRect(dst,x,y,hBink->width, hBink->height);
blitBuffer(buffer, x, y, w, h, dst);
if(update)
SDL_UpdateRect(dst, x, y, w, h);
}
void CBIKHandler::nextFrame()
@ -125,6 +159,10 @@ void CBIKHandler::nextFrame()
void CBIKHandler::close()
{
binkClose(hBink);
hBink = NULL;
CloseHandle(hBinkFile);
hBinkFile = NULL;
delete [] buffer;
}
@ -133,80 +171,29 @@ bool CBIKHandler::wait()
return binkWait(hBink);
}
// Reference RSGrapics.RSGetPixelFormat
PixelFormat getPixelFormat(TBitmap &b)
int CBIKHandler::curFrame() const
{
DIBSECTION DS;
DS.dsBmih.biBitCount = 2;
DS.dsBmih.biCompression = 0; //not sure about that
PixelFormat result = b.pixelFormat;
if ( (result!= pfCustom)
|| (b.handleType = bmDDB)
// || (GetObject(b.Handle, SizeOf(DS), @DS) = 0)
)
exit(0);
switch (DS.dsBmih.biBitCount)
{
case 16:
switch (DS.dsBmih.biCompression)
{
case BI_RGB:
result = pf15bit;
break;
case BI_BITFIELDS:
if ( DS.dsBitfields[1]==0x7E0 )
result = pf16bit;
if ( DS.dsBitfields[1]==0x7E0 )
result = pf15bit;
break;
}
break;
case 32:
switch (DS.dsBmih.biCompression)
{
case BI_RGB:
result = pf32bit;
break;
case BI_BITFIELDS:
if ( DS.dsBitfields[1]==0xFF0000 )
result = pf32bit;
break;
}
break;
}
return result;
return hBink->currentFrame;
}
void CSmackPlayer::preparePic(TBitmap &b)
int CBIKHandler::frameCount() const
{
switch (getPixelFormat(b))
{
case pf15bit:
case pf16bit:
break;
default:
b.pixelFormat = pf16bit;
};
return hBink->frameCount;
}
void CSmackPlayer::nextFrame()
{
ptrSmackNextFrame(data);
}
bool CSmackPlayer::wait()
{
return ptrSmackWait(data);
}
void CSmackPlayer::init()
CSmackPlayer::CSmackPlayer()
{
Instantiate("smackw32.dll");
tlog0 << "smackw32.dll loaded" << std::endl;
ptrSmackNextFrame = (SmackNextFrame)FindAddress("_SmackNextFrame@4");
ptrSmackWait = (SmackWait)FindAddress("_SmackWait@4");
@ -214,110 +201,210 @@ void CSmackPlayer::init()
ptrSmackToBuffer = (SmackToBuffer)FindAddress("_SmackToBuffer@28");
ptrSmackOpen = (SmackOpen)FindAddress("_SmackOpen@12");
ptrSmackSoundOnOff = (SmackSoundOnOff)FindAddress("_SmackSoundOnOff@8");
tlog0 << "Functions located" << std::endl;
ptrSmackClose = (SmackClose)FindAddress("_SmackClose@4");
}
CSmackPlayer::~CSmackPlayer()
{
if(data)
close();
}
void CSmackPlayer::close()
{
ptrSmackClose(data);
data = NULL;
delete [] buffer;
buffer = NULL;
}
void CSmackPlayer::open( std::string name )
{
Uint32 flags[2] = {0xff400, 0xfe400};
data = ptrSmackOpen( (void*)name.c_str(), flags[1], -1);
if (!data)
{
tlog1 << "Smack cannot open " << name << std::endl;
return;
}
buffer = new char[data->width*data->height*2];
buf = buffer+data->width*(data->height-1)*2; // adjust pointer position for later use by 'SmackToBuffer'
}
void CSmackPlayer::show( int x, int y, SDL_Surface *dst, bool update)
{
int w = data->width, h = data->height;
int stripe = (-w*2) & (~3);
//put frame to the buffer
ptrSmackToBuffer(data, 0, 0, stripe, w, buf, 0x80000000);
ptrSmackDoFrame(data);
/* 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);
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--;
}
}
if ( SDL_MUSTLOCK(dst) )
{
SDL_UnlockSurface(dst);
}
if(update)
SDL_UpdateRect(dst, x, y, w, h);
}
int CSmackPlayer::curFrame() const
{
return data->currentFrame;
}
int CSmackPlayer::frameCount() const
{
return data->frameCount;
}
CVideoPlayer::CVideoPlayer()
{
vidh = new CVidHandler(std::string(DATA_DIR "Data" PATHSEPARATOR "VIDEO.VID"));
smkPlayer = new CSmackPlayer;
smkPlayer->init();
current = NULL;
}
CVideoPlayer::~CVideoPlayer()
{
delete smkPlayer;
delete vidh;
}
bool CVideoPlayer::init()
void CVideoPlayer::open(std::string name)
{
return true;
if(boost::algorithm::ends_with(name, ".BIK"))
current = &bikPlayer;
else
current = &smkPlayer;
fname = name;
//extract video from video.vid so we can play it
vidh->extract(name, name);
current->open(name);
}
bool CVideoPlayer::open(std::string fname, int x, int y)
{
vidh->extract(fname, fname);
Uint32 flags[2] = {0xff400, 0xfe400};
smkPlayer->data = smkPlayer->ptrSmackOpen( (void*)fname.c_str(), flags[1], -1);
if (smkPlayer->data ==NULL)
{
tlog1<<"No "<<fname<<" file!"<<std::endl;
return false;
}
buffer = new char[smkPlayer->data->width*smkPlayer->data->height*2];
buf = buffer+smkPlayer->data->width*(smkPlayer->data->height-1)*2; // adjust pointer position for later use by 'SmackToBuffer'
xPos = x;
yPos = y;
frame = 0;
return true;
}
void CVideoPlayer::close()
{
delete [] buffer;
}
bool CVideoPlayer::nextFrame()
void CVideoPlayer::close()
{
if(frame < smkPlayer->data->frameCount)
if(!current)
{
++frame;
int stripe = (-smkPlayer->data->width*2) & (~3);
Uint32 unknown = 0x80000000;
smkPlayer->ptrSmackToBuffer(smkPlayer->data , 0, 0, stripe, smkPlayer->data->width, buf, unknown);
smkPlayer->ptrSmackDoFrame(smkPlayer->data );
// now bitmap is in buffer
// but I don't know exactly how to parse these 15bit color and draw it onto 16bit screen
/* Lock the screen for direct access to the pixels */
if ( SDL_MUSTLOCK(screen) )
{
if ( SDL_LockSurface(screen) < 0 )
{
fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
return 0;
}
}
// draw the frame!!
Uint16* addr = (Uint16*) (buffer+smkPlayer->data->width*(smkPlayer->data->height-1)*2-2);
for( int j=0; j<smkPlayer->data->height-1; j++) // why -1 ?
{
for ( int i=smkPlayer->data->width-1; i>=0; i--)
{
Uint16 pixel = *addr;
Uint8 *p = (Uint8 *)screen->pixels + (j+yPos) * screen->pitch + (i + xPos) * screen->format->BytesPerPixel;
p[2] = ((pixel & 0x7c00) >> 10) * 8;
p[1] = ((pixel & 0x3e0) >> 5) * 8;
p[0] = ((pixel & 0x1F)) * 8;
addr--;
}
}
if ( SDL_MUSTLOCK(screen) )
{
SDL_UnlockSurface(screen);
}
/* Update just the part of the display that we've changed */
SDL_UpdateRect(screen, xPos, yPos, smkPlayer->data->width, smkPlayer->data->height);
SDL_Delay(50);
smkPlayer->ptrSmackWait(smkPlayer->data);
smkPlayer->ptrSmackNextFrame(smkPlayer->data);
tlog2 << "Closing no opened player...?" << std::endl;
return;
}
else //end of video
current->close();
current = NULL;
if(!DeleteFileA(fname.c_str()))
{
return false;
tlog1 << "Cannot remove temporarily extracted video file: " << fname;
checkForError(false);
}
fname.clear();
}
void CVideoPlayer::nextFrame()
{
current->nextFrame();
}
void CVideoPlayer::show(int x, int y, SDL_Surface *dst, bool update)
{
current->show(x, y, dst, update);
}
bool CVideoPlayer::wait()
{
return current->wait();
}
int CVideoPlayer::curFrame() const
{
return current->curFrame();
}
int CVideoPlayer::frameCount() const
{
return current->frameCount();
}
bool CVideoPlayer::openAndPlayVideo(std::string name, int x, int y, SDL_Surface *dst, bool stopOnKey)
{
open(name);
bool ret = playVideo(x, y, dst, stopOnKey);
close();
return ret;
}
void CVideoPlayer::update( int x, int y, SDL_Surface *dst, bool redraw, bool update )
{
bool w = wait(); //check if should keep current frame
if(!w)
nextFrame();
if(!w || redraw) //redraw if changed frame or we was told to
show(x,y,dst,update);
}
//reads events and throws on key down
bool keyDown()
{
SDL_Event ev;
while(SDL_PollEvent(&ev))
{
if(ev.type == SDL_KEYDOWN || ev.type == SDL_MOUSEBUTTONDOWN)
return true;
}
return false;
}
bool CVideoPlayer::playVideo(int x, int y, SDL_Surface *dst, bool stopOnKey)
{
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;
}

View File

@ -50,57 +50,53 @@ public:
typedef void*(__stdcall* BinkSetSoundSystem)(void * soundfun, void*);
typedef HBINK(__stdcall* BinkOpen)(HANDLE bikfile, int flags);
typedef si32(__stdcall* BinkGetPalette)(HBINK);
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 IVideoPlayer
{
public:
virtual void open(std::string name)=0;
virtual void close()=0;
virtual void nextFrame()=0;
virtual void show(int x, int y, SDL_Surface *dst, bool update = true)=0;
virtual bool wait()=0;
virtual int curFrame() const =0;
virtual int frameCount() const =0;
};
class CBIKHandler : public DLLHandler
class CBIKHandler : public DLLHandler, public IVideoPlayer
{
public:
int newmode;
HANDLE hBinkFile;
HBINK hBink;
char * buffer;
BinkSetSoundSystem binkSetSoundSystem;
BinkOpen binkOpen;
BinkGetPalette getPalette;
//BinkGetPalette getPalette;
BinkNextFrame binkNextFrame;
BinkDoFrame binkDoFrame;
BinkCopyToBuffer binkCopyToBuffer;
BinkWait binkWait;
void * waveOutOpen, * binkGetError;
int width, height;
BinkClose binkClose;
CBIKHandler();
void open(std::string name);
void close();
void nextFrame();
void show(int x, int y, SDL_Surface *dst);
void show(int x, int y, SDL_Surface *dst, bool update = true);
bool wait();
int curFrame() const;
int frameCount() const;
};
//////////SMK Player ///////////////////////////////////////////////////////
typedef enum { bmDIB, bmDDB} BitmapHandleType;
typedef enum { pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit, pf32bit, pfCustom} PixelFormat;
typedef enum {tmAuto, tmFixed} TransparentMode;
class TBitmap
{
public:
ui32 width;
ui32 height;
PixelFormat pixelFormat;
BitmapHandleType handleType;
char* buffer;
};
struct SmackStruct
{
si32 version;
@ -127,7 +123,7 @@ typedef void (__stdcall* SmackSoundOnOff) (SmackStruct*, bool);
class CSmackPlayer: public DLLHandler
class CSmackPlayer: public DLLHandler, public IVideoPlayer
{
public:
SmackOpen ptrSmackOpen;
@ -136,39 +132,50 @@ public:
SmackNextFrame ptrSmackNextFrame;
SmackWait ptrSmackWait;
SmackSoundOnOff ptrSmackSoundOnOff;
SmackClose ptrSmackClose;
char *buffer, *buf;
SmackStruct* data;
void init();
void preparePic(TBitmap &b);
TBitmap extractFrame(TBitmap &b);
CSmackPlayer();
~CSmackPlayer();
void open(std::string name);
void close();
void nextFrame();
bool wait();
void show(int x, int y, SDL_Surface *dst, bool update = true);
bool wait();
int curFrame() const;
int frameCount() const;
};
class CVidHandler;
class CVideoPlayer
class CVideoPlayer : public IVideoPlayer
{
private:
CVidHandler * vidh; //.vid file handling
CSmackPlayer * smkPlayer;
int frame;
int xPos, yPos;
char * buffer;
char * buf;
CSmackPlayer smkPlayer; //for .SMK
CBIKHandler bikPlayer; //for .BIK
IVideoPlayer *current; //points to bik or smk player, appropriate to type of currently played video
std::string fname; //name of current video file (empty if idle)
public:
CVideoPlayer(); //c-tor
~CVideoPlayer(); //d-tor
bool init();
bool open(std::string fname, int x, int y); //x, y -> position where animation should be displayed on the screen
void close();
bool nextFrame(); // display next frame
void open(std::string name);
void close();
void nextFrame(); //move animation to the next frame
void show(int x, int y, SDL_Surface *dst, bool update = true); //blit current frame
void update(int x, int y, SDL_Surface *dst, bool redraw, 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