mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
913 lines
23 KiB
C++
913 lines
23 KiB
C++
#include <stdlib.h>
|
|
|
|
#ifdef __LINUX__
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/uio.h>
|
|
|
|
#define O_BINARY 0
|
|
#endif
|
|
|
|
#include "DDAccess.h"
|
|
|
|
#ifdef WIN32
|
|
#include <MMSystem.h>
|
|
#include <io.h>
|
|
#include "dsound.h"
|
|
#endif
|
|
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
|
|
#include "movie.h"
|
|
#include "mvelibw.h"
|
|
#include "pserror.h"
|
|
#include "renderer.h"
|
|
#include "application.h"
|
|
#include "ddio.h"
|
|
#include "ddvid.h"
|
|
#include "grtext.h"
|
|
#include "mem.h"
|
|
#include "bitmap.h"
|
|
#include "gamefont.h"
|
|
#include "game.h"
|
|
|
|
namespace {
|
|
MovieFrameCallback_fp Movie_callback = NULL;
|
|
char MovieDir[512];
|
|
char SoundCardName[512];
|
|
ushort CurrentPalette[256];
|
|
int Movie_bm_handle = -1;
|
|
uint Movie_current_framenum = 0;
|
|
bool Movie_looping = false;
|
|
|
|
#ifndef NO_MOVIES
|
|
|
|
#ifdef WIN32
|
|
class MovieSoundBuffer : public ISysSoundBuffer {
|
|
private:
|
|
LPDIRECTSOUNDBUFFER m_pBuffer;
|
|
|
|
public:
|
|
MovieSoundBuffer(LPDIRECTSOUNDBUFFER buffer) : m_pBuffer(buffer) {}
|
|
|
|
////////////////////////////
|
|
// Release
|
|
////////////////////////////
|
|
// Releases the memory associated with a sound buffer. This pointer is
|
|
// no longer valid after return.
|
|
//
|
|
// Returns:
|
|
// -1 : Invalid Parameter
|
|
// 0 : Ok!
|
|
int Release() {
|
|
m_pBuffer->Release();
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////
|
|
// SetVolume
|
|
//////////////////////////////
|
|
// Sets the volume of a buffer.
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : Cannot set volume
|
|
// -2 : Invalid parameters
|
|
int SetVolume(signed long vol) { return m_pBuffer->SetVolume(vol); }
|
|
|
|
///////////////////////////
|
|
// SetPan
|
|
///////////////////////////
|
|
// Sets the pan of a buffer.
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : Cannot set pan
|
|
// -2 : Invalid parameters
|
|
int SetPan(signed long pan) { return m_pBuffer->SetPan(pan); }
|
|
|
|
/////////////////////////
|
|
// Stop
|
|
/////////////////////////
|
|
// Stops a buffer from playing
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int Stop() { return m_pBuffer->Stop(); }
|
|
|
|
/////////////////////////
|
|
// Play
|
|
/////////////////////////
|
|
// Starts a buffer playing (or changes the flags for a buffer currently
|
|
// playing).
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int Play(unsigned int flags) {
|
|
DWORD dsFlags = (flags & LNXSND_LOOPING) ? DSBPLAY_LOOPING : 0;
|
|
return m_pBuffer->Play(0, 0, dsFlags);
|
|
}
|
|
|
|
////////////////////////////
|
|
// GetCaps
|
|
////////////////////////////
|
|
// Get the capabilities of a sound buffer
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int GetCaps(SysSoundCaps *caps) {
|
|
DSBCAPS dsCaps;
|
|
dsCaps.dwSize = sizeof(dsCaps);
|
|
int res = m_pBuffer->GetCaps(&dsCaps);
|
|
if (res != 0)
|
|
return res;
|
|
|
|
caps->dwBufferBytes = dsCaps.dwBufferBytes;
|
|
caps->dwFlags = dsCaps.dwFlags;
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////
|
|
// GetStatus
|
|
//////////////////////////////
|
|
// Returns the status of a buffer
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int GetStatus(unsigned int *status) { return m_pBuffer->GetStatus(reinterpret_cast<LPDWORD>(status)); }
|
|
|
|
///////////////////////////////////////
|
|
// GetCurrentPosition
|
|
///////////////////////////////////////
|
|
// Returns the current play and write positions of the buffer
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int GetCurrentPosition(unsigned int *ppos, unsigned int *wpos) {
|
|
return m_pBuffer->GetCurrentPosition(reinterpret_cast<LPDWORD>(ppos), reinterpret_cast<LPDWORD>(wpos));
|
|
}
|
|
|
|
///////////////////////////////////////
|
|
// SetCurrentPosition
|
|
///////////////////////////////////////
|
|
// Sets the current play position of the buffer
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int SetCurrentPosition(unsigned int pos) { return m_pBuffer->SetCurrentPosition(pos); }
|
|
|
|
/////////////////////////
|
|
// Lock
|
|
/////////////////////////
|
|
// Locks the given buffer, returning pointer(s) to the buffer(s) along with
|
|
// available the size of the buffer(s) for writing.
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int Lock(unsigned int pos, unsigned int numbytes, void **ptr1, unsigned int *numbytes1, void **ptr2,
|
|
unsigned int *numbytes2, unsigned int flags) {
|
|
return m_pBuffer->Lock(pos, numbytes, ptr1, reinterpret_cast<LPDWORD>(numbytes1), ptr2,
|
|
reinterpret_cast<LPDWORD>(numbytes2), flags);
|
|
}
|
|
|
|
///////////////////////////
|
|
// Unlock
|
|
///////////////////////////
|
|
// Unlocks a buffer.
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int Unlock(void *ptr1, unsigned int num1, void *ptr2, unsigned int num2) {
|
|
return m_pBuffer->Unlock(ptr1, num1, ptr2, num2);
|
|
}
|
|
};
|
|
|
|
class MovieSoundDevice : public ISoundDevice {
|
|
private:
|
|
LPDIRECTSOUND m_ds;
|
|
|
|
public:
|
|
MovieSoundDevice() : m_ds(NULL) {}
|
|
|
|
void SetDirectSound(LPDIRECTSOUND ds) { m_ds = ds; }
|
|
|
|
LPDIRECTSOUND GetDirectSound() { return m_ds; }
|
|
|
|
///////////////////////////////
|
|
// CreateSoundBuffer
|
|
///////////////////////////////
|
|
// Creates a sound buffer to be used with mixing and output.
|
|
//
|
|
// Returns:
|
|
// -1 : Invalid Parameter
|
|
// -2 : Out of memory
|
|
// 0 : Ok!
|
|
int CreateSoundBuffer(SysSoundBufferDesc *lbdesc, ISysSoundBuffer **lsndb) {
|
|
if (m_ds == NULL)
|
|
return -1;
|
|
|
|
DSBUFFERDESC dsBufferDesc;
|
|
dsBufferDesc.dwSize = sizeof(dsBufferDesc);
|
|
dsBufferDesc.dwFlags = lbdesc->dwFlags;
|
|
dsBufferDesc.dwBufferBytes = lbdesc->dwBufferBytes;
|
|
dsBufferDesc.dwReserved = 0;
|
|
dsBufferDesc.lpwfxFormat = reinterpret_cast<LPWAVEFORMATEX>(lbdesc->lpwfxFormat);
|
|
|
|
LPDIRECTSOUNDBUFFER dsSndBuffer = NULL;
|
|
int res = m_ds->CreateSoundBuffer(&dsBufferDesc, &dsSndBuffer, NULL);
|
|
if (res != DS_OK) {
|
|
*lsndb = NULL;
|
|
return res;
|
|
}
|
|
|
|
*lsndb = new MovieSoundBuffer(dsSndBuffer);
|
|
return res;
|
|
}
|
|
};
|
|
|
|
#else
|
|
|
|
class MovieSoundBuffer : public ISysSoundBuffer {
|
|
private:
|
|
LnxSoundBuffer *m_pBuffer;
|
|
|
|
public:
|
|
LnxSoundBuffer *GetLnxBuffer() { return m_pBuffer; }
|
|
MovieSoundBuffer(LnxSoundBuffer *buffer) : m_pBuffer(buffer) {}
|
|
|
|
////////////////////////////
|
|
// Release
|
|
////////////////////////////
|
|
// Releases the memory associated with a sound buffer. This pointer is
|
|
// no longer valid after return.
|
|
//
|
|
// Returns:
|
|
// -1 : Invalid Parameter
|
|
// 0 : Ok!
|
|
int Release() {
|
|
return LnxSoundBuffer_Release(m_pBuffer);
|
|
// m_pBuffer->Release();
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////
|
|
// SetVolume
|
|
//////////////////////////////
|
|
// Sets the volume of a buffer.
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : Cannot set volume
|
|
// -2 : Invalid parameters
|
|
int SetVolume(signed long vol) { return LnxSoundBuffer_SetVolume(m_pBuffer, vol); }
|
|
|
|
///////////////////////////
|
|
// SetPan
|
|
///////////////////////////
|
|
// Sets the pan of a buffer.
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : Cannot set pan
|
|
// -2 : Invalid parameters
|
|
int SetPan(signed long pan) { return LnxSoundBuffer_SetPan(m_pBuffer, pan); }
|
|
|
|
/////////////////////////
|
|
// Stop
|
|
/////////////////////////
|
|
// Stops a buffer from playing
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int Stop() { return LnxSoundBuffer_Stop(m_pBuffer); }
|
|
|
|
/////////////////////////
|
|
// Play
|
|
/////////////////////////
|
|
// Starts a buffer playing (or changes the flags for a buffer currently
|
|
// playing).
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int Play(unsigned int flags) {
|
|
unsigned int dsFlags = (flags & LNXSND_LOOPING) ? LNXSND_LOOPING : 0;
|
|
return LnxSoundBuffer_Play(m_pBuffer, dsFlags);
|
|
}
|
|
|
|
////////////////////////////
|
|
// GetCaps
|
|
////////////////////////////
|
|
// Get the capabilities of a sound buffer
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int GetCaps(SysSoundCaps *caps) { return LnxSoundBuffer_GetCaps(m_pBuffer, (LinuxSoundCaps *)caps); }
|
|
|
|
//////////////////////////////
|
|
// GetStatus
|
|
//////////////////////////////
|
|
// Returns the status of a buffer
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int GetStatus(unsigned int *status) { return LnxSoundBuffer_GetStatus(m_pBuffer, status); }
|
|
|
|
///////////////////////////////////////
|
|
// GetCurrentPosition
|
|
///////////////////////////////////////
|
|
// Returns the current play and write positions of the buffer
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int GetCurrentPosition(unsigned int *ppos, unsigned int *wpos) {
|
|
|
|
return LnxSoundBuffer_GetCurrentPosition(m_pBuffer, ppos, wpos);
|
|
}
|
|
|
|
///////////////////////////////////////
|
|
// SetCurrentPosition
|
|
///////////////////////////////////////
|
|
// Sets the current play position of the buffer
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int SetCurrentPosition(unsigned int pos) { return LnxSoundBuffer_SetCurrentPosition(m_pBuffer, pos); }
|
|
|
|
/////////////////////////
|
|
// Lock
|
|
/////////////////////////
|
|
// Locks the given buffer, returning pointer(s) to the buffer(s) along with
|
|
// available the size of the buffer(s) for writing.
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int Lock(unsigned int pos, unsigned int numbytes, void **ptr1, unsigned int *numbytes1, void **ptr2,
|
|
unsigned int *numbytes2, unsigned int flags) {
|
|
return LnxSoundBuffer_Lock(m_pBuffer, pos, numbytes, ptr1, numbytes1, ptr2, numbytes2, flags);
|
|
}
|
|
|
|
///////////////////////////
|
|
// Unlock
|
|
///////////////////////////
|
|
// Unlocks a buffer.
|
|
//
|
|
// Returns:
|
|
// 0 : no error
|
|
// -1 : invalid parameters
|
|
int Unlock(void *ptr1, unsigned int num1, void *ptr2, unsigned int num2) {
|
|
return LnxSoundBuffer_Unlock(m_pBuffer, ptr1, num1, ptr2, num2);
|
|
}
|
|
};
|
|
class MovieSoundDevice : public ISoundDevice {
|
|
private:
|
|
LnxSoundDevice m_ds;
|
|
|
|
public:
|
|
MovieSoundDevice() {}
|
|
|
|
void SetDirectSound(LnxSoundDevice ds) { m_ds = ds; }
|
|
|
|
LnxSoundDevice GetDirectSound() { return m_ds; }
|
|
|
|
///////////////////////////////
|
|
// CreateSoundBuffer
|
|
///////////////////////////////
|
|
// Creates a sound buffer to be used with mixing and output.
|
|
//
|
|
// Returns:
|
|
// -1 : Invalid Parameter
|
|
// -2 : Out of memory
|
|
// 0 : Ok!
|
|
int CreateSoundBuffer(SysSoundBufferDesc *lbdesc, ISysSoundBuffer **lsndb) {
|
|
LnxSoundBuffer *sb = NULL;
|
|
int ret = LnxSound_CreateSoundBuffer(&m_ds, (LnxBufferDesc *)lbdesc, (LnxSoundBuffer **)&sb);
|
|
if (ret == 0) {
|
|
ISysSoundBuffer *p = (ISysSoundBuffer *)new MovieSoundBuffer(sb);
|
|
*lsndb = p;
|
|
} else {
|
|
lsndb = NULL;
|
|
}
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
#endif
|
|
} // namespace
|
|
|
|
void *CallbackAlloc(unsigned int size);
|
|
void CallbackFree(void *p);
|
|
unsigned int CallbackFileRead(int hFile, void *pBuffer, unsigned int bufferCount);
|
|
void InitializePalette();
|
|
void CallbackSetPalette(unsigned char *pBuffer, unsigned int start, unsigned int count);
|
|
void CallbackShowFrame(unsigned char *buf, unsigned int bufw, unsigned int bufh, unsigned int sx, unsigned int sy,
|
|
unsigned int w, unsigned int h, unsigned int dstx, unsigned int dsty, unsigned int hicolor);
|
|
|
|
#ifndef NO_MOVIES
|
|
bool mve_InitSound(oeApplication *app, MovieSoundDevice &device);
|
|
void mve_CloseSound(MovieSoundDevice &device);
|
|
#endif
|
|
|
|
// sets the directory where movies are stored
|
|
int mve_Init(const char *dir, const char *sndcard) {
|
|
#ifndef NO_MOVIES
|
|
strcpy(MovieDir, dir);
|
|
strcpy(SoundCardName, sndcard);
|
|
return MVELIB_NOERROR;
|
|
#else
|
|
return MVELIB_INIT_ERROR;
|
|
#endif
|
|
}
|
|
|
|
// callback called per frame of playback of movies.
|
|
void mve_SetCallback(MovieFrameCallback_fp callBack) {
|
|
#ifndef NO_MOVIES
|
|
Movie_callback = callBack;
|
|
#endif
|
|
}
|
|
|
|
// used to tell movie library how to render movies.
|
|
void mve_SetRenderProperties(short x, short y, short w, short h, renderer_type type, bool hicolor) {}
|
|
|
|
// plays a movie using the current screen.
|
|
int mve_PlayMovie(const char *pMovieName, oeApplication *pApp) {
|
|
#ifndef NO_MOVIES
|
|
// open movie file.
|
|
int hFile = open(pMovieName, O_RDONLY | O_BINARY);
|
|
if (hFile == -1) {
|
|
mprintf((0, "MOVIE: Unable to open %s\n", pMovieName));
|
|
return MVELIB_FILE_ERROR;
|
|
}
|
|
|
|
// determine the movie type
|
|
const char *pExtension = strrchr(pMovieName, '.');
|
|
bool highColor = (pExtension != NULL && stricmp(pExtension, ".mv8") != 0);
|
|
|
|
// setup
|
|
MVE_rmFastMode(MVE_RM_NORMAL);
|
|
MVE_sfCallbacks(CallbackShowFrame);
|
|
MVE_memCallbacks(CallbackAlloc, CallbackFree);
|
|
MVE_ioCallbacks(CallbackFileRead);
|
|
MVE_sfSVGA(640, 480, 480, 0, NULL, 0, 0, NULL, highColor ? 1 : 0);
|
|
MVE_palCallbacks(CallbackSetPalette);
|
|
InitializePalette();
|
|
Movie_bm_handle = -1;
|
|
|
|
MovieSoundDevice soundDevice;
|
|
if (!mve_InitSound(pApp, soundDevice)) {
|
|
mprintf((0, "Failed to initialize sound\n"));
|
|
close(hFile);
|
|
return MVELIB_INIT_ERROR;
|
|
}
|
|
|
|
int result = MVE_rmPrepMovie(hFile, -1, -1, 0);
|
|
if (result != 0) {
|
|
mprintf((0, "PrepMovie result = %d\n", result));
|
|
close(hFile);
|
|
mve_CloseSound(soundDevice);
|
|
return MVELIB_INIT_ERROR;
|
|
}
|
|
|
|
bool aborted = false;
|
|
Movie_current_framenum = 0;
|
|
while ((result = MVE_rmStepMovie()) == 0) {
|
|
// let the OS do its thing
|
|
pApp->defer();
|
|
|
|
// check for bail
|
|
int key = ddio_KeyInKey();
|
|
if (key == KEY_ESC) {
|
|
aborted = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// free our bitmap
|
|
if (Movie_bm_handle != -1) {
|
|
bm_FreeBitmap(Movie_bm_handle);
|
|
Movie_bm_handle = -1;
|
|
}
|
|
|
|
// close our file handle
|
|
close(hFile);
|
|
|
|
// determine the return code
|
|
int err = MVELIB_NOERROR;
|
|
if (aborted) {
|
|
err = MVELIB_PLAYBACK_ABORTED;
|
|
} else if (result != MVE_ERR_EOF) {
|
|
err = MVELIB_PLAYBACK_ERROR;
|
|
}
|
|
|
|
// cleanup and shutdown
|
|
MVE_rmEndMovie();
|
|
MVE_ReleaseMem();
|
|
|
|
// reset sound
|
|
mve_CloseSound(soundDevice);
|
|
|
|
// return out
|
|
return err;
|
|
#else
|
|
return MVELIB_INIT_ERROR;
|
|
#endif
|
|
}
|
|
|
|
void *CallbackAlloc(unsigned int size) { return mem_malloc(size); }
|
|
|
|
void CallbackFree(void *p) { mem_free(p); }
|
|
|
|
unsigned int CallbackFileRead(int hFile, void *pBuffer, unsigned int bufferCount) {
|
|
unsigned int numRead = read(hFile, pBuffer, bufferCount);
|
|
return (numRead == bufferCount) ? 1 : 0;
|
|
}
|
|
|
|
void InitializePalette() {
|
|
for (int i = 0; i < 256; ++i) {
|
|
CurrentPalette[i] = OPAQUE_FLAG | GR_RGB16(0, 0, 0);
|
|
}
|
|
}
|
|
|
|
void CallbackSetPalette(unsigned char *pBuffer, unsigned int start, unsigned int count) {
|
|
#ifndef NO_MOVIES
|
|
pBuffer += start * 3;
|
|
|
|
for (unsigned int i = 0; i < count; ++i) {
|
|
unsigned int r = pBuffer[0] << 2;
|
|
unsigned int g = pBuffer[1] << 2;
|
|
unsigned int b = pBuffer[2] << 2;
|
|
pBuffer += 3;
|
|
|
|
CurrentPalette[start + i] = OPAQUE_FLAG | GR_RGB16(r, g, b);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int NextPow2(int n) {
|
|
n--;
|
|
n |= n >> 1;
|
|
n |= n >> 2;
|
|
n |= n >> 4;
|
|
n |= n >> 8;
|
|
n |= n >> 16;
|
|
n++;
|
|
return n;
|
|
}
|
|
|
|
#ifndef NO_MOVIES
|
|
void BlitToMovieBitmap(unsigned char *buf, unsigned int bufw, unsigned int bufh, unsigned int hicolor,
|
|
bool usePow2Texture, int &texW, int &texH) {
|
|
// get some sizes
|
|
int drawWidth = hicolor ? (bufw >> 1) : bufw;
|
|
int drawHeight = bufh;
|
|
|
|
if (usePow2Texture) {
|
|
int wPow2 = NextPow2(drawWidth);
|
|
int hPow2 = NextPow2(drawHeight);
|
|
int texSize = (wPow2 > hPow2) ? wPow2 : hPow2;
|
|
texW = texSize;
|
|
texH = texSize;
|
|
} else {
|
|
texW = drawWidth;
|
|
texH = drawHeight;
|
|
}
|
|
|
|
if (Movie_bm_handle == -1) {
|
|
// Allocate our bitmap
|
|
Movie_bm_handle = bm_AllocBitmap(texW, texH, 0);
|
|
}
|
|
|
|
unsigned short *pPixelData = (ushort *)bm_data(Movie_bm_handle, 0);
|
|
GameBitmaps[Movie_bm_handle].flags |= BF_CHANGED;
|
|
if (hicolor) {
|
|
unsigned short *wBuf = (unsigned short *)buf;
|
|
for (int y = 0; y < drawHeight; ++y) {
|
|
for (int x = 0; x < drawWidth; ++x) {
|
|
unsigned short col16 = *wBuf++;
|
|
unsigned int b = ((col16 >> 11) & 0x1F) << 3;
|
|
unsigned int g = ((col16 >> 5) & 0x3F) << 2;
|
|
unsigned int r = ((col16 >> 0) & 0x1F) << 3;
|
|
pPixelData[x] = OPAQUE_FLAG | GR_RGB16(r, g, b);
|
|
}
|
|
|
|
pPixelData += texW;
|
|
}
|
|
} else {
|
|
for (int y = 0; y < drawHeight; ++y) {
|
|
for (int x = 0; x < drawWidth; ++x) {
|
|
unsigned char palIndex = *buf++;
|
|
pPixelData[x] = CurrentPalette[palIndex];
|
|
}
|
|
|
|
pPixelData += texW;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallbackShowFrame(unsigned char *buf, unsigned int bufw, unsigned int bufh, unsigned int sx, unsigned int sy,
|
|
unsigned int w, unsigned int h, unsigned int dstx, unsigned int dsty, unsigned int hicolor) {
|
|
// prepare our bitmap
|
|
int texW, texH;
|
|
BlitToMovieBitmap(buf, bufw, bufh, hicolor, true, texW, texH);
|
|
|
|
// calculate UVs from texture
|
|
int drawWidth = hicolor ? (bufw >> 1) : bufw;
|
|
int drawHeight = bufh;
|
|
float u = float(drawWidth - 1) / float(texW - 1);
|
|
float v = float(drawHeight - 1) / float(texH - 1);
|
|
|
|
StartFrame(0, 0, 640, 480, false);
|
|
|
|
rend_ClearScreen(GR_BLACK);
|
|
rend_SetAlphaType(AT_CONSTANT);
|
|
rend_SetAlphaValue(255);
|
|
rend_SetLighting(LS_NONE);
|
|
rend_SetColorModel(CM_MONO);
|
|
rend_SetOverlayType(OT_NONE);
|
|
rend_SetWrapType(WT_CLAMP);
|
|
rend_SetFiltering(0);
|
|
rend_SetZBufferState(0);
|
|
rend_DrawScaledBitmap(dstx, dsty, dstx + drawWidth, dsty + drawHeight, Movie_bm_handle, 0.0f, 0.0f, u, v);
|
|
rend_SetFiltering(1);
|
|
rend_SetZBufferState(1);
|
|
|
|
// call our callback
|
|
if (Movie_callback != NULL) {
|
|
Movie_callback(dstx, dsty, Movie_current_framenum);
|
|
}
|
|
++Movie_current_framenum;
|
|
|
|
EndFrame();
|
|
|
|
rend_Flip();
|
|
}
|
|
#endif
|
|
|
|
unsigned int mve_SequenceStart(const char *mvename, int *fhandle, oeApplication *app, bool looping) {
|
|
#ifndef NO_MOVIES
|
|
|
|
int hfile = open(mvename, O_RDONLY | O_BINARY);
|
|
|
|
if (hfile == -1) {
|
|
mprintf((1, "MOVIE: Unable to open %s\n", mvename));
|
|
*fhandle = -1;
|
|
return 0;
|
|
}
|
|
|
|
// setup
|
|
MVE_rmFastMode(MVE_RM_NORMAL);
|
|
MVE_memCallbacks(CallbackAlloc, CallbackFree);
|
|
MVE_ioCallbacks(CallbackFileRead);
|
|
InitializePalette();
|
|
Movie_bm_handle = -1;
|
|
Movie_looping = looping;
|
|
|
|
// let the render know we will be copying bitmaps to framebuffer (or something)
|
|
rend_SetFrameBufferCopyState(true);
|
|
|
|
*fhandle = hfile;
|
|
return (unsigned int)MVE_frOpen(CallbackFileRead, hfile, NULL);
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
unsigned int mve_SequenceFrame(unsigned int handle, int fhandle, bool sequence, int *bm_handle) {
|
|
#ifndef NO_MOVIES
|
|
if (bm_handle) {
|
|
*bm_handle = -1;
|
|
}
|
|
|
|
if (handle == -1) {
|
|
return (unsigned int)(-1);
|
|
}
|
|
|
|
static unsigned sw = 0, sh = 0, hicolor = 0;
|
|
int err = 0;
|
|
|
|
reread_frame:
|
|
|
|
// get the next frame of data
|
|
unsigned char *pBuffer = NULL;
|
|
err = MVE_frGet((MVE_frStream)handle, &pBuffer, &sw, &sh, &hicolor);
|
|
|
|
// refresh our palette
|
|
{
|
|
unsigned int palstart = 0;
|
|
unsigned int palcount = 0;
|
|
unsigned char *pal = NULL;
|
|
MVE_frPal((MVE_frStream)handle, &pal, &palstart, &palcount);
|
|
CallbackSetPalette(pal, palstart, palcount);
|
|
}
|
|
|
|
if (err == 0) {
|
|
// blit to bitmap
|
|
int texW, texH;
|
|
BlitToMovieBitmap(pBuffer, sw, sh, hicolor, false, texW, texH);
|
|
|
|
if (bm_handle) {
|
|
*bm_handle = Movie_bm_handle;
|
|
}
|
|
|
|
return handle;
|
|
}
|
|
|
|
if (Movie_looping && err == MVE_ERR_EOF) {
|
|
MVE_frClose((MVE_frStream)handle);
|
|
#ifdef WIN32
|
|
_lseek(fhandle, 0, SEEK_SET);
|
|
#else
|
|
lseek(fhandle, 0, SEEK_SET);
|
|
#endif
|
|
handle = (unsigned int)MVE_frOpen(CallbackFileRead, fhandle, NULL);
|
|
sequence = true;
|
|
goto reread_frame;
|
|
}
|
|
|
|
return (unsigned int)(-1);
|
|
#else
|
|
return (unsigned int)(-1);
|
|
#endif
|
|
}
|
|
|
|
bool mve_SequenceClose(unsigned int hMovie, int hFile) {
|
|
#ifndef NO_MOVIES
|
|
if (hMovie == -1)
|
|
return false;
|
|
|
|
MVE_frClose((MVE_frStream)hMovie);
|
|
MVE_ReleaseMem();
|
|
close(hFile);
|
|
|
|
// free our bitmap
|
|
if (Movie_bm_handle != -1) {
|
|
bm_FreeBitmap(Movie_bm_handle);
|
|
Movie_bm_handle = -1;
|
|
}
|
|
|
|
// We're no longer needing this
|
|
rend_SetFrameBufferCopyState(false);
|
|
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void mve_Puts(short x, short y, ddgr_color col, const char *txt) {
|
|
grtext_SetFont(BRIEFING_FONT);
|
|
grtext_SetColor(col);
|
|
grtext_SetAlpha(255);
|
|
grtext_SetFlags(GRTEXTFLAG_SHADOW);
|
|
grtext_CenteredPrintf(0, y, txt);
|
|
grtext_Flush();
|
|
}
|
|
|
|
void mve_ClearRect(short x1, short y1, short x2, short y2) {
|
|
// Note: I can not figure out how to clear, and then write over it with text. It always covers my text!
|
|
// rend_FillRect( GR_BLACK, x1, y1, x2, y2 );
|
|
}
|
|
|
|
#ifndef NO_MOVIES
|
|
#ifdef WIN32
|
|
// Internal function to enumerate sound devices
|
|
BOOL CALLBACK DSEnumCallback(LPGUID lp_guid, LPCSTR lpstr_description, LPCSTR lpstr_module, LPVOID lp_Context) {
|
|
GUID FAR *lp_ret_guid = (GUID FAR *)lp_Context;
|
|
|
|
if (SoundCardName[0]) {
|
|
if (strcmp(lpstr_description, SoundCardName) == 0) {
|
|
if (lp_guid) {
|
|
memmove(lp_ret_guid, lp_guid, sizeof(GUID));
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool mve_InitSound(oeApplication *app, MovieSoundDevice &device) {
|
|
// Perform Direct Sound Initialization
|
|
device.SetDirectSound(NULL);
|
|
|
|
GUID *pguid = NULL;
|
|
GUID card_guid, zero_card_guid;
|
|
ZeroMemory(&card_guid, sizeof(GUID));
|
|
ZeroMemory(&zero_card_guid, sizeof(GUID));
|
|
HRESULT hr = DirectSoundEnumerate(DSEnumCallback, &card_guid);
|
|
if (hr == DS_OK) {
|
|
if (memcmp(&card_guid, &zero_card_guid, sizeof(GUID)) != 0) {
|
|
pguid = &card_guid;
|
|
}
|
|
}
|
|
|
|
LPDIRECTSOUND lpDS;
|
|
if (DirectSoundCreate(pguid, &lpDS, NULL) != DS_OK) {
|
|
return false;
|
|
}
|
|
|
|
HWND hWnd = (HWND)((oeWin32Application *)app)->m_hWnd;
|
|
hr = lpDS->SetCooperativeLevel(hWnd, DSSCL_EXCLUSIVE);
|
|
if (hr != DS_OK) {
|
|
lpDS->Release();
|
|
return false;
|
|
}
|
|
|
|
bool use_22k_sound = false;
|
|
|
|
// Start Mixer
|
|
LPDIRECTSOUNDBUFFER lpPrimaryBuffer;
|
|
DSBUFFERDESC dsbd;
|
|
memset(&dsbd, 0, sizeof(DSBUFFERDESC));
|
|
dsbd.dwSize = sizeof(DSBUFFERDESC);
|
|
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
|
hr = lpDS->CreateSoundBuffer(&dsbd, &lpPrimaryBuffer, NULL);
|
|
if (hr == DS_OK) {
|
|
// set format to 44khz if requested.
|
|
WAVEFORMATEX fmt;
|
|
fmt.cbSize = sizeof(fmt);
|
|
fmt.wFormatTag = WAVE_FORMAT_PCM;
|
|
fmt.nChannels = 2;
|
|
fmt.wBitsPerSample = 16;
|
|
fmt.nSamplesPerSec = use_22k_sound ? 22050 : 44100;
|
|
fmt.nBlockAlign = fmt.nChannels * (fmt.wBitsPerSample / 8);
|
|
fmt.nAvgBytesPerSec = ((DWORD)fmt.nSamplesPerSec) * ((DWORD)fmt.nBlockAlign);
|
|
hr = lpPrimaryBuffer->SetFormat(&fmt);
|
|
if (hr != DS_OK) {
|
|
lpPrimaryBuffer->Release();
|
|
lpDS->Release();
|
|
lpDS = NULL;
|
|
return false;
|
|
}
|
|
|
|
hr = lpPrimaryBuffer->Play(0, 0, DSBPLAY_LOOPING);
|
|
if (hr != DS_OK) {
|
|
lpPrimaryBuffer->Release();
|
|
lpDS->Release();
|
|
return false;
|
|
}
|
|
|
|
lpPrimaryBuffer->Release();
|
|
} else {
|
|
lpDS->Release();
|
|
return false;
|
|
}
|
|
|
|
device.SetDirectSound(lpDS);
|
|
MVE_sndInit(&device);
|
|
|
|
return true;
|
|
}
|
|
|
|
void mve_CloseSound(MovieSoundDevice &device) {
|
|
LPDIRECTSOUND ds = device.GetDirectSound();
|
|
if (ds) {
|
|
ds->Release();
|
|
device.SetDirectSound(NULL);
|
|
}
|
|
}
|
|
#else
|
|
bool mve_InitSound(oeApplication *app, MovieSoundDevice &device) {
|
|
|
|
LnxSoundDevice snddev;
|
|
bool use_22k_sound = false;
|
|
snddev.freq = use_22k_sound ? 22050 : 44100;
|
|
snddev.bit_depth = 16;
|
|
snddev.channels = 2;
|
|
snddev.bps = snddev.freq * snddev.channels * snddev.bit_depth / 8;
|
|
|
|
device.SetDirectSound(snddev);
|
|
|
|
MVE_sndInit(&device);
|
|
|
|
return true;
|
|
}
|
|
|
|
void mve_CloseSound(MovieSoundDevice &device) {
|
|
// TODO: close the driver out
|
|
}
|
|
#endif
|
|
|
|
#endif
|