1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

* playing smk videos on Windows (currently only spellbook animation)

This commit is contained in:
mateuszb 2009-06-22 11:12:40 +00:00
parent c6b11ee917
commit 3e7a180613
3 changed files with 346 additions and 10 deletions

View File

@ -638,30 +638,30 @@ void CSpellWindow::deactivate()
void CSpellWindow::turnPageLeft()
{
#ifndef _WIN32
if (CGI->videoh->open("PGTRNLFT.SMK", pos.x+13, pos.y+14)) {
if (CGI->videoh->open("PGTRNLFT.SMK", pos.x+13, pos.y+15)) {
while(CGI->videoh->nextFrame()) {
SDL_framerateDelay(LOCPLINT->mainFPSmng);
#ifndef _WIN32
SDL_framerateDelay(LOCPLINT->mainFPSmng);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
#endif
}
CGI->videoh->close();
}
#endif
}
void CSpellWindow::turnPageRight()
{
#ifndef _WIN32
if (CGI->videoh->open("PGTRNRGH.SMK", pos.x+13, pos.y+14)) {
if (CGI->videoh->open("PGTRNRGH.SMK", pos.x+13, pos.y+15)) {
while(CGI->videoh->nextFrame()) {
SDL_framerateDelay(LOCPLINT->mainFPSmng);
#ifndef _WIN32
SDL_framerateDelay(LOCPLINT->mainFPSmng);
SDL_framerateDelay(LOCPLINT->mainFPSmng);
#endif
}
CGI->videoh->close();
}
#endif
}
CSpellWindow::SpellArea::SpellArea(SDL_Rect pos, CSpellWindow * owner)

View File

@ -6,6 +6,8 @@
#ifdef _WIN32
#include "../client/SDL_Extensions.h"
void DLLHandler::Instantiate(const char *filename)
{
#ifdef _WIN32
@ -200,6 +202,252 @@ void CBIKHandler::open(std::string name)
//
//end;
//////////SMK Player - Windows ///////////////////////////////////////////////////////
void CRADPlayer::loadProc(char* ptrFunc,char* procName)
{
(FARPROC&)(*ptrFunc) = GetProcAddress(hinstLib, procName);
}
// Reference RSGrapics.RSGetPixelFormat
PixelFormat CRADPlayer::getPixelFormat(TBitmap b)
{
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;
}
void CSmackPlayer::preparePic(TBitmap b)
{
switch (getPixelFormat(b))
{
case pf15bit:
case pf16bit:
break;
default:
b.pixelFormat = pf16bit;
};
}
void CSmackPlayer::nextFrame()
{
loadProc((char*)&ptrSmackNextFrame, "_SmackNextFrame@4");
ptrSmackNextFrame(data);
}
bool CSmackPlayer::wait()
{
loadProc((char*)&ptrSmackWait, "_SmackWait@4");
return ptrSmackWait(data);
}
TBitmap CSmackPlayer::extractFrame(TBitmap b)
{
int i,j;
PixelFormat pf;
TBitmap result;
loadProc((char*)&ptrSmackDoFrame, "_SmackDoFrame@4");
loadProc((char*)&ptrSmackToBuffer, "_SmackToBuffer@28");
i=j=0;
/*
try {
pf = getPixelFormat(b);
i=j=0;
switch(pf){
case pf8bit: i = 1; break;
case pf15bit:
case pf16bit: i=2; break;
default:
// assert(false)
break;
}
switch(pf) {
case pf8bit:
j = 0x10000000;
break;
case pf15bit:
// todo
break;
case pf16bit:
// todo
break;
default:
break;
} */
int v = -b.width*i;
ptrSmackToBuffer(data, 0, 0, v, b.height, (char*)b.buffer, j);
ptrSmackDoFrame(data);
/*
}
catch ( char * msg) {
}*/
result = b;
return result;
}
CVideoPlayer::CVideoPlayer()
{
// Load DLL file
vidh = new CVidHandler(std::string(DATA_DIR "Data" PATHSEPARATOR "VIDEO.VID"));
smkPlayer = new CSmackPlayer;
smkPlayer->hinstLib = LoadLibrary(L"smackw32.dll");
if (smkPlayer->hinstLib == NULL) {
tlog1<<"ERROR: unable to load DLL"<<std::endl;
getchar();
return;
}
tlog0<< "smackw32.dll Loaded"<<std::endl;
smkPlayer->loadProc( (char*)&smkPlayer->ptrSmackOpen, "_SmackOpen@12");
smkPlayer->loadProc((char*)&smkPlayer->ptrSmackDoFrame, "_SmackDoFrame@4");
smkPlayer->loadProc((char*)&smkPlayer->ptrSmackToBuffer, "_SmackToBuffer@28");
smkPlayer->loadProc((char*)&smkPlayer->ptrSmackToBuffer, "_SmackToBuffer@28");
smkPlayer->loadProc((char*)&smkPlayer->ptrSmackSoundOnOff, "_SmackSoundOnOff@8");
smkPlayer->loadProc((char*)&smkPlayer->ptrSmackWait, "_SmackWait@4");
smkPlayer->loadProc((char*)&smkPlayer->ptrSmackNextFrame, "_SmackNextFrame@4");
}
CVideoPlayer::~CVideoPlayer()
{
delete smkPlayer;
delete vidh;
}
bool CVideoPlayer::init()
{
return true;
}
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 postition for later use by 'SmackToBuffer'
xPos = x;
yPos = y;
frame = 0;
return true;
}
void CVideoPlayer::close()
{
delete buffer;
}
bool CVideoPlayer::nextFrame()
{
if(frame < smkPlayer->data->frameCount)
{
++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
// 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;
/*Uint8 b = ((pixel & 0x7c00) >> 10) * 8;
Uint8 g = ((pixel & 0x3e0) >> 5) * 8;
Uint8 r = ((pixel & 0x1F)) * 8;*/
addr--;
/* 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;
}
}
//putpixel(screen, i,j, (Uint32)pixel);
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);
}
else //end of video
{
return false;
}
return true;
}
#else
#include "../client/SDL_Extensions.h"

View File

@ -1,14 +1,12 @@
#ifndef __CVIDEOHANDLER_H__
#define __CVIDEOHANDLER_H__
#include "../global.h"
#ifdef _WIN32
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include <SDL.h>
//
#define BINKNOTHREADEDIO 0x00800000
@ -150,8 +148,98 @@ public:
void close();
};
//////////SMK Player ///////////////////////////////////////////////////////
struct SmackStruct
{
Sint32 version; //
Sint32 width;
Sint32 height;
Sint32 frameCount;
Sint32 mspf;
unsigned char unk1[88];
unsigned char palette[776];
Sint32 currentFrame; // Starting with 0
// 72 - Øè?
// 1060 - interesting
// 1100 - Mute:Bool
unsigned char unk[56];
Uint32 fileHandle; // exact type is HANDLE in windows.h
};
// defines function pointer type
typedef SmackStruct* (__stdcall* SmackOpen)(void* , Uint32, Sint32 );
// todo default value
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 *, Uint32);
typedef bool (__stdcall* SmackWait)(SmackStruct*);
typedef void (__stdcall* SmackSoundOnOff) (SmackStruct*, bool);
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:
Uint32 width;
Uint32 height;
PixelFormat pixelFormat;
BitmapHandleType handleType;
char* buffer;
};
class CRADPlayer
{
public:
HINSTANCE hinstLib;
void loadProc(char* ptrFunc,char* procName);
PixelFormat getPixelFormat(TBitmap);
};
class CSmackPlayer: public CRADPlayer{
public:
SmackOpen ptrSmackOpen;
SmackDoFrame ptrSmackDoFrame;
SmackToBuffer ptrSmackToBuffer;
SmackNextFrame ptrSmackNextFrame;
SmackWait ptrSmackWait;
SmackSoundOnOff ptrSmackSoundOnOff;
SmackStruct* data;
void preparePic(TBitmap b);
TBitmap extractFrame(TBitmap b);
void nextFrame();
bool wait();
};
class CVidHandler;
class CVideoPlayer
{
private:
CVidHandler * vidh; //.vid file handling
CSmackPlayer * smkPlayer;
int frame;
int xPos, yPos;
char * buffer;
char * buf;
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
};
#else