瀏覽代碼

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

mateuszb 16 年之前
父節點
當前提交
3e7a180613
共有 3 個文件被更改,包括 346 次插入10 次删除
  1. 6 6
      client/CSpellWindow.cpp
  2. 248 0
      hch/CVideoHandler.cpp
  3. 92 4
      hch/CVideoHandler.h

+ 6 - 6
client/CSpellWindow.cpp

@@ -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)

+ 248 - 0
hch/CVideoHandler.cpp

@@ -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"

+ 92 - 4
hch/CVideoHandler.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