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:
parent
c6b11ee917
commit
3e7a180613
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user