2008-04-20 14:43:56 +00:00
|
|
|
#include "made/pmvplayer.h"
|
|
|
|
|
|
|
|
namespace Made {
|
|
|
|
|
|
|
|
PmvPlayer::PmvPlayer(OSystem *system, Audio::Mixer *mixer) : _fd(NULL), _system(system), _mixer(mixer) {
|
|
|
|
}
|
|
|
|
|
|
|
|
PmvPlayer::~PmvPlayer() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void PmvPlayer::play(const char *filename) {
|
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
_abort = false;
|
|
|
|
_surface = NULL;
|
2008-04-20 14:43:56 +00:00
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
_fd = new Common::File();
|
|
|
|
_fd->open(filename);
|
2008-04-20 14:43:56 +00:00
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
uint32 chunkType, chunkSize;
|
2008-04-20 14:43:56 +00:00
|
|
|
|
|
|
|
readChunk(chunkType, chunkSize); // "MOVE"
|
2008-04-20 15:36:40 +00:00
|
|
|
readChunk(chunkType, chunkSize); // "MHED"
|
2008-04-20 14:43:56 +00:00
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
// TODO: Evaluate header
|
|
|
|
//_fd->skip(0x3A);
|
2008-04-20 14:43:56 +00:00
|
|
|
|
|
|
|
uint frameDelay = _fd->readUint16LE();
|
|
|
|
_fd->skip(10);
|
|
|
|
uint soundFreq = _fd->readUint16LE();
|
|
|
|
// FIXME: weird frequencies... (11127 or 22254)
|
|
|
|
//if (soundFreq == 11127) soundFreq = 11025;
|
|
|
|
//if (soundFreq == 22254) soundFreq = 22050;
|
|
|
|
|
|
|
|
int unk;
|
|
|
|
|
|
|
|
for (int i = 0; i < 22; i++) {
|
|
|
|
unk = _fd->readUint16LE();
|
|
|
|
debug(2, "%i ", unk);
|
|
|
|
}
|
|
|
|
debug(2, "\n");
|
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
_mixer->stopAll();
|
2008-04-20 14:43:56 +00:00
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
_audioStream = Audio::makeAppendableAudioStream(soundFreq, Audio::Mixer::FLAG_UNSIGNED);
|
2008-04-20 14:43:56 +00:00
|
|
|
_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream);
|
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
// Read palette
|
|
|
|
_fd->read(_palette, 768);
|
|
|
|
updatePalette();
|
2008-04-20 14:43:56 +00:00
|
|
|
|
|
|
|
//FILE *raw = fopen("track.raw", "wb");
|
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
while (!_abort && !_fd->eof()) {
|
2008-04-20 14:43:56 +00:00
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
readChunk(chunkType, chunkSize);
|
2008-04-20 14:43:56 +00:00
|
|
|
|
|
|
|
if (_fd->eof())
|
|
|
|
break;
|
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
byte *frameData = new byte[chunkSize];
|
|
|
|
_fd->read(frameData, chunkSize);
|
2008-04-20 14:43:56 +00:00
|
|
|
|
|
|
|
byte *audioData = frameData + READ_LE_UINT32(frameData + 8) - 8;
|
2008-04-20 17:15:31 +00:00
|
|
|
chunkSize = READ_LE_UINT16(audioData + 4);
|
2008-04-20 14:43:56 +00:00
|
|
|
uint16 chunkCount = READ_LE_UINT16(audioData + 6);
|
|
|
|
|
|
|
|
if (chunkCount > 50) break; // FIXME: this is a hack
|
|
|
|
|
|
|
|
debug(2, "chunkCount = %d; chunkSize = %d\n", chunkCount, chunkSize);
|
|
|
|
|
|
|
|
uint32 soundSize = chunkCount * chunkSize;
|
2008-04-20 15:36:40 +00:00
|
|
|
byte *soundData = new byte[soundSize];
|
|
|
|
decompressSound(audioData + 8, soundData, chunkSize, chunkCount);
|
|
|
|
_audioStream->queueBuffer(soundData, soundSize);
|
|
|
|
|
|
|
|
//fwrite(soundData, soundSize, 1, raw);
|
|
|
|
|
|
|
|
byte *imageData = frameData + READ_LE_UINT32(frameData + 12) - 8;
|
|
|
|
|
|
|
|
uint32 frameNum = READ_LE_UINT32(frameData);
|
|
|
|
uint16 width = READ_LE_UINT16(imageData + 8);
|
|
|
|
uint16 height = READ_LE_UINT16(imageData + 10);
|
|
|
|
uint16 cmdOffs = READ_LE_UINT16(imageData + 12);
|
|
|
|
uint16 pixelOffs = READ_LE_UINT16(imageData + 16);
|
|
|
|
uint16 maskOffs = READ_LE_UINT16(imageData + 20);
|
|
|
|
uint16 lineSize = READ_LE_UINT16(imageData + 24);
|
|
|
|
|
|
|
|
debug(2, "width = %d; height = %d; cmdOffs = %04X; pixelOffs = %04X; maskOffs = %04X; lineSize = %d\n",
|
|
|
|
width, height, cmdOffs, pixelOffs, maskOffs, lineSize);
|
|
|
|
|
|
|
|
if (!_surface) {
|
|
|
|
_surface = new Graphics::Surface();
|
|
|
|
_surface->create(width, height, 1);
|
|
|
|
}
|
2008-04-20 14:43:56 +00:00
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
decompressImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize, frameNum > 0);
|
2008-04-20 14:43:56 +00:00
|
|
|
|
|
|
|
handleEvents();
|
2008-04-20 15:36:40 +00:00
|
|
|
updateScreen();
|
2008-04-20 14:43:56 +00:00
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
delete[] frameData;
|
2008-04-20 14:43:56 +00:00
|
|
|
|
|
|
|
_system->delayMillis(frameDelay);
|
2008-04-20 15:36:40 +00:00
|
|
|
}
|
2008-04-20 14:43:56 +00:00
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
_audioStream->finish();
|
|
|
|
_mixer->stopAll();
|
|
|
|
|
|
|
|
//delete _audioStream;
|
|
|
|
delete _fd;
|
|
|
|
delete _surface;
|
2008-04-20 14:43:56 +00:00
|
|
|
|
|
|
|
//fclose(raw);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void PmvPlayer::readChunk(uint32 &chunkType, uint32 &chunkSize) {
|
2008-04-20 15:36:40 +00:00
|
|
|
chunkType = _fd->readUint32BE();
|
|
|
|
chunkSize = _fd->readUint32LE();
|
2008-04-20 14:43:56 +00:00
|
|
|
|
2008-04-20 15:36:40 +00:00
|
|
|
debug(2, "chunkType = %c%c%c%c; chunkSize = %d\n",
|
|
|
|
(chunkType >> 24) & 0xFF, (chunkType >> 16) & 0xFF, (chunkType >> 8) & 0xFF, chunkType & 0xFF,
|
|
|
|
chunkSize);
|
2008-04-20 14:43:56 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void PmvPlayer::handleEvents() {
|
|
|
|
Common::Event event;
|
|
|
|
while (_system->getEventManager()->pollEvent(event)) {
|
2008-04-20 16:18:50 +00:00
|
|
|
switch (event.type) {
|
|
|
|
case Common::EVENT_KEYDOWN:
|
|
|
|
if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
|
|
|
|
_abort = true;
|
|
|
|
break;
|
|
|
|
case Common::EVENT_QUIT:
|
|
|
|
// TODO: Exit more gracefully
|
|
|
|
g_system->quit();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2008-04-20 14:43:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PmvPlayer::updatePalette() {
|
2008-04-20 15:36:40 +00:00
|
|
|
byte colors[1024];
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
|
|
colors[i * 4 + 0] = _palette[i * 3 + 0];
|
|
|
|
colors[i * 4 + 1] = _palette[i * 3 + 1];
|
|
|
|
colors[i * 4 + 2] = _palette[i * 3 + 2];
|
|
|
|
colors[i * 4 + 3] = 0;
|
|
|
|
}
|
|
|
|
_system->setPalette(colors, 0, 256);
|
2008-04-20 14:43:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PmvPlayer::updateScreen() {
|
2008-04-20 15:36:40 +00:00
|
|
|
_system->copyRectToScreen((const byte*)_surface->pixels, _surface->pitch, 0, 0, _surface->w, _surface->h);
|
|
|
|
_system->updateScreen();
|
2008-04-20 14:43:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|