parent
3c5c774e76
commit
bb87d39424
29 changed files with 5456 additions and 0 deletions
|
@ -108,6 +108,9 @@ public:
|
|||
#if PLUGIN_ENABLED_STATIC(GOB)
|
||||
LINK_PLUGIN(GOB)
|
||||
#endif
|
||||
#if PLUGIN_ENABLED_STATIC(GROOVIE)
|
||||
LINK_PLUGIN(GROOVIE)
|
||||
#endif
|
||||
#if PLUGIN_ENABLED_STATIC(IGOR)
|
||||
LINK_PLUGIN(IGOR)
|
||||
#endif
|
||||
|
|
1
configure
vendored
1
configure
vendored
|
@ -89,6 +89,7 @@ add_engine cine "Cinematique evo 1" yes
|
|||
add_engine cruise "Cinematique evo 2" no
|
||||
add_engine drascula "Drascula: The Vampire Strikes Back" yes
|
||||
add_engine gob "Gobli*ns" yes
|
||||
add_engine groovie "Groovie" no
|
||||
add_engine igor "Igor: Objective Uikokahonia" no
|
||||
add_engine kyra "Legend of Kyrandia" yes
|
||||
add_engine lure "Lure of the Temptress" yes
|
||||
|
|
|
@ -42,6 +42,11 @@ DEFINES += -DENABLE_GOB=$(ENABLE_GOB)
|
|||
MODULES += engines/gob
|
||||
endif
|
||||
|
||||
ifdef ENABLE_GROOVIE
|
||||
DEFINES += -DENABLE_GROOVIE=$(ENABLE_GROOVIE)
|
||||
MODULES += engines/groovie
|
||||
endif
|
||||
|
||||
ifdef ENABLE_IGOR
|
||||
DEFINES += -DENABLE_IGOR=$(ENABLE_IGOR)
|
||||
MODULES += engines/igor
|
||||
|
|
314
engines/groovie/cursor.cpp
Normal file
314
engines/groovie/cursor.cpp
Normal file
|
@ -0,0 +1,314 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/cursor.h"
|
||||
#include "groovie/groovie.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
// Cursor Manager
|
||||
|
||||
CursorMan::CursorMan(OSystem *system) :
|
||||
_syst(system), _lastTime(0), _cursor(NULL) {
|
||||
}
|
||||
|
||||
CursorMan::~CursorMan() {
|
||||
// Delete the cursors
|
||||
for (uint cursor = 0; cursor < _cursors.size(); cursor++) {
|
||||
delete _cursors[cursor];
|
||||
}
|
||||
}
|
||||
|
||||
uint8 CursorMan::getStyle() {
|
||||
return _current;
|
||||
}
|
||||
|
||||
void CursorMan::setStyle(uint8 newStyle) {
|
||||
// Reset the animation
|
||||
_lastFrame = 254;
|
||||
_lastTime = 1;
|
||||
|
||||
// Save the new cursor
|
||||
_current = newStyle;
|
||||
_cursor = _cursors[newStyle];
|
||||
|
||||
// Show the first frame
|
||||
_cursor->enable();
|
||||
animate();
|
||||
}
|
||||
|
||||
void CursorMan::animate() {
|
||||
if (_lastTime) {
|
||||
int newTime = _syst->getMillis();
|
||||
if (_lastTime - newTime >= 75) {
|
||||
_lastFrame++;
|
||||
_lastFrame %= _cursor->getFrames();
|
||||
_cursor->showFrame(_lastFrame);
|
||||
_lastTime = _syst->getMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// t7g Cursor
|
||||
|
||||
class Cursor_t7g : public Cursor {
|
||||
public:
|
||||
Cursor_t7g(OSystem *system, uint8 *img, uint8 *pal);
|
||||
|
||||
void enable();
|
||||
void showFrame(uint16 frame);
|
||||
|
||||
private:
|
||||
OSystem *_syst;
|
||||
byte *_img;
|
||||
byte *_pal;
|
||||
};
|
||||
|
||||
Cursor_t7g::Cursor_t7g(OSystem *system, uint8 *img, uint8 *pal) :
|
||||
_syst(system), _pal(pal) {
|
||||
|
||||
_width = img[0];
|
||||
_height = img[1];
|
||||
_numFrames = img[2];
|
||||
uint8 elinor1 = img[3];
|
||||
uint8 elinor2 = img[4];
|
||||
|
||||
_img = img + 5;
|
||||
|
||||
debugC(1, kGroovieDebugCursor | kGroovieDebugAll, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames);
|
||||
debugC(1, kGroovieDebugCursor | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::Cursor: elinor: 0x%02X (%d), 0x%02X (%d)", elinor1, elinor1, elinor2, elinor2);
|
||||
}
|
||||
|
||||
void Cursor_t7g::enable() {
|
||||
// Apply the palette
|
||||
_syst->setCursorPalette(_pal, 0, 32);
|
||||
}
|
||||
|
||||
void Cursor_t7g::showFrame(uint16 frame) {
|
||||
// Set the mouse cursor
|
||||
int offset = _width * _height * frame;
|
||||
_syst->setMouseCursor((const byte *)_img + offset, _width, _height, _width >> 1, _height >> 1, 0);
|
||||
}
|
||||
|
||||
|
||||
// t7g Cursor Manager
|
||||
|
||||
#define NUM_IMGS 9
|
||||
static const uint16 cursorDataOffsets[NUM_IMGS] = {
|
||||
0x0000, 0x182f, 0x3b6d, 0x50cc, 0x6e79, 0x825d, 0x96d7, 0xa455, 0xa776
|
||||
};
|
||||
|
||||
#define NUM_PALS 7
|
||||
//Pals: 0xb794, 0xb7f4, 0xb854, 0xb8b4, 0xb914, 0xb974, 0xb9d4
|
||||
|
||||
#define NUM_STYLES 11
|
||||
// pyramid is cursor 8, eyes are 9 & 10
|
||||
const uint CursorMan_t7g::_cursorImg[NUM_STYLES] = {3, 5, 4, 3, 1, 0, 2, 6, 7, 8, 8};
|
||||
const uint CursorMan_t7g::_cursorPal[NUM_STYLES] = {0, 0, 0, 0, 2, 0, 1, 3, 5, 4, 6};
|
||||
|
||||
CursorMan_t7g::CursorMan_t7g(OSystem *system) :
|
||||
CursorMan(system) {
|
||||
|
||||
// Open the cursors file
|
||||
Common::File robgjd;
|
||||
if (!robgjd.open("rob.gjd")) {
|
||||
error("Groovie::Cursor: Couldn't open rob.gjd");
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the images
|
||||
for (uint imgnum = 0; imgnum < NUM_IMGS; imgnum++) {
|
||||
robgjd.seek(cursorDataOffsets[imgnum]);
|
||||
_images.push_back(loadImage(robgjd));
|
||||
}
|
||||
|
||||
// Load the palettes
|
||||
robgjd.seek(-0x60 * NUM_PALS, SEEK_END);
|
||||
for (uint palnum = 0; palnum < NUM_PALS; palnum++) {
|
||||
_palettes.push_back(loadPalette(robgjd));
|
||||
}
|
||||
|
||||
// Build the cursors
|
||||
for (uint cursor = 0; cursor < NUM_STYLES; cursor++) {
|
||||
Cursor *s = new Cursor_t7g(_syst, _images[_cursorImg[cursor]], _palettes[_cursorPal[cursor]]);
|
||||
_cursors.push_back(s);
|
||||
}
|
||||
|
||||
robgjd.close();
|
||||
}
|
||||
|
||||
CursorMan_t7g::~CursorMan_t7g() {
|
||||
// Delete the images
|
||||
for (uint img = 0; img < _images.size(); img++) {
|
||||
delete[] _images[img];
|
||||
}
|
||||
|
||||
// Delete the palettes
|
||||
for (uint pal = 0; pal < _palettes.size(); pal++) {
|
||||
delete[] _palettes[pal];
|
||||
}
|
||||
}
|
||||
|
||||
byte *CursorMan_t7g::loadImage(Common::File &file) {
|
||||
uint16 decompbytes = 0, offset, i, length;
|
||||
uint8 flagbyte, lengthmask = 0x0F, offsetlen, var_8;
|
||||
byte *cursorStorage = new byte[65536];
|
||||
uint8 *runningcursor = cursorStorage;
|
||||
|
||||
bool finished = false;
|
||||
while (!(finished || file.eos())) {
|
||||
flagbyte = file.readByte();
|
||||
for (i = 1; i <= 8; i++) {
|
||||
if (!file.eos()) {
|
||||
if (flagbyte & 1) {
|
||||
*(runningcursor++) = file.readByte();
|
||||
decompbytes++;
|
||||
} else {
|
||||
var_8 = file.readByte();
|
||||
offsetlen = file.readByte();
|
||||
if (var_8 == 0 && offsetlen == 0) {
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
length = (offsetlen & lengthmask) + 3;
|
||||
offsetlen >>= 4;
|
||||
offset = (offsetlen << 8) + var_8;
|
||||
decompbytes += length;
|
||||
|
||||
for (; length > 0; length--, runningcursor++) {
|
||||
*(runningcursor) = *(runningcursor - offset);
|
||||
}
|
||||
}
|
||||
flagbyte = flagbyte >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cursorStorage;
|
||||
}
|
||||
|
||||
byte *CursorMan_t7g::loadPalette(Common::File &file) {
|
||||
byte *palette = new byte[4 * 32];
|
||||
for (uint8 colournum = 0; colournum < 32; colournum++) {
|
||||
palette[colournum * 4 + 0] = file.readByte();
|
||||
palette[colournum * 4 + 1] = file.readByte();
|
||||
palette[colournum * 4 + 2] = file.readByte();
|
||||
palette[colournum * 4 + 3] = 0;
|
||||
}
|
||||
return palette;
|
||||
}
|
||||
|
||||
|
||||
// v2 Cursor
|
||||
|
||||
class Cursor_v2 : public Cursor {
|
||||
public:
|
||||
Cursor_v2(Common::File &file);
|
||||
|
||||
void enable();
|
||||
void showFrame(uint16 frame);
|
||||
|
||||
private:
|
||||
//byte *_data;
|
||||
};
|
||||
|
||||
Cursor_v2::Cursor_v2(Common::File &file) {
|
||||
_numFrames = file.readUint16LE();
|
||||
_width = file.readUint16LE();
|
||||
_height = file.readUint16LE();
|
||||
|
||||
debugC(1, kGroovieDebugCursor | kGroovieDebugAll, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames);
|
||||
|
||||
uint16 tmp16 = file.readUint16LE();
|
||||
debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "hotspot x?: %d\n", tmp16);
|
||||
tmp16 = file.readUint16LE();
|
||||
debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "hotspot y?: %d\n", tmp16);
|
||||
int loop2count = file.readUint16LE();
|
||||
debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop2count?: %d\n", loop2count);
|
||||
for (int l = 0; l < loop2count; l++) {
|
||||
tmp16 = file.readUint16LE();
|
||||
debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop2a: %d\n", tmp16);
|
||||
tmp16 = file.readUint16LE();
|
||||
debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop2b: %d\n", tmp16);
|
||||
}
|
||||
|
||||
file.seek(0x20 * 3, SEEK_CUR);
|
||||
|
||||
for (int f = 0; f < _numFrames; f++) {
|
||||
uint32 tmp32 = file.readUint32LE();
|
||||
debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop3: %d\n", tmp32);
|
||||
|
||||
//file.seek(tmp32, SEEK_CUR);
|
||||
byte *data = new byte[tmp32];
|
||||
file.read(data, tmp32);
|
||||
//Common::hexdump(data, tmp32);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor_v2::enable() {
|
||||
}
|
||||
|
||||
void Cursor_v2::showFrame(uint16 frame) {
|
||||
}
|
||||
|
||||
|
||||
// v2 Cursor Manager
|
||||
|
||||
CursorMan_v2::CursorMan_v2(OSystem *system) :
|
||||
CursorMan(system) {
|
||||
|
||||
// Open the icons file
|
||||
Common::File iconsFile;
|
||||
if (!iconsFile.open("icons.ph")) {
|
||||
error("Groovie::Cursor: Couldn't open icons.ph");
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify the signature
|
||||
uint32 tmp32 = iconsFile.readUint32LE();
|
||||
uint16 tmp16 = iconsFile.readUint16LE();
|
||||
if (tmp32 != 0x6e6f6369 || tmp16 != 1) {
|
||||
error("Groovie::Cursor: icons.ph signature failed: %04X %d", tmp32, tmp16);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the number of icons
|
||||
uint16 nicons = iconsFile.readUint16LE();
|
||||
|
||||
// Read the icons
|
||||
for (int i = 0; i < nicons; i++) {
|
||||
Cursor *s = new Cursor_v2(iconsFile);
|
||||
_cursors.push_back(s);
|
||||
}
|
||||
|
||||
iconsFile.close();
|
||||
}
|
||||
|
||||
CursorMan_v2::~CursorMan_v2() {
|
||||
}
|
||||
|
||||
} // End of Groovie namespace
|
96
engines/groovie/cursor.h
Normal file
96
engines/groovie/cursor.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_CURSOR_H
|
||||
#define GROOVIE_CURSOR_H
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/file.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class Cursor {
|
||||
public:
|
||||
virtual ~Cursor() {}
|
||||
uint16 getFrames() { return _numFrames; }
|
||||
virtual void enable() = 0;
|
||||
virtual void showFrame(uint16 frame) = 0;
|
||||
|
||||
protected:
|
||||
uint16 _width;
|
||||
uint16 _height;
|
||||
uint16 _numFrames;
|
||||
};
|
||||
|
||||
class CursorMan {
|
||||
public:
|
||||
CursorMan(OSystem *system);
|
||||
virtual ~CursorMan();
|
||||
|
||||
virtual void animate();
|
||||
virtual void setStyle(uint8 newStyle);
|
||||
virtual uint8 getStyle();
|
||||
|
||||
protected:
|
||||
OSystem *_syst;
|
||||
|
||||
// Animation variables
|
||||
uint8 _lastFrame;
|
||||
uint32 _lastTime;
|
||||
|
||||
// Styles
|
||||
Common::Array<Cursor *> _cursors;
|
||||
uint8 _current;
|
||||
Cursor *_cursor;
|
||||
};
|
||||
|
||||
class CursorMan_t7g : public CursorMan {
|
||||
public:
|
||||
CursorMan_t7g(OSystem *system);
|
||||
~CursorMan_t7g();
|
||||
|
||||
private:
|
||||
// Styles data
|
||||
static const uint _cursorImg[];
|
||||
static const uint _cursorPal[];
|
||||
|
||||
// Cursors data
|
||||
Common::Array<byte *> _images;
|
||||
Common::Array<byte *> _palettes;
|
||||
|
||||
// Loading functions
|
||||
byte *loadImage(Common::File &file);
|
||||
byte *loadPalette(Common::File &file);
|
||||
};
|
||||
|
||||
class CursorMan_v2 : public CursorMan {
|
||||
public:
|
||||
CursorMan_v2(OSystem *system);
|
||||
~CursorMan_v2();
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_CURSOR_H
|
145
engines/groovie/debug.cpp
Normal file
145
engines/groovie/debug.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/debug.h"
|
||||
#include "groovie/script.h"
|
||||
#include "groovie/groovie.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
Debugger::Debugger(GroovieEngine *vm) :
|
||||
_vm (vm), _script(&_vm->_script), _syst(_vm->_system) {
|
||||
|
||||
// Register the debugger comands
|
||||
DCmd_Register("step", WRAP_METHOD(Debugger, cmd_step));
|
||||
DCmd_Register("go", WRAP_METHOD(Debugger, cmd_go));
|
||||
DCmd_Register("pc", WRAP_METHOD(Debugger, cmd_pc));
|
||||
DCmd_Register("fg", WRAP_METHOD(Debugger, cmd_fg));
|
||||
DCmd_Register("bg", WRAP_METHOD(Debugger, cmd_bg));
|
||||
DCmd_Register("mem", WRAP_METHOD(Debugger, cmd_mem));
|
||||
DCmd_Register("load", WRAP_METHOD(Debugger, cmd_loadgame));
|
||||
DCmd_Register("save", WRAP_METHOD(Debugger, cmd_savegame));
|
||||
DCmd_Register("playref", WRAP_METHOD(Debugger, cmd_playref));
|
||||
DCmd_Register("dumppal", WRAP_METHOD(Debugger, cmd_dumppal));
|
||||
}
|
||||
|
||||
Debugger::~Debugger() {
|
||||
Common::clearAllSpecialDebugLevels();
|
||||
}
|
||||
|
||||
int Debugger::getNumber(const char *arg) {
|
||||
return strtol(arg, (char **)NULL, 0);
|
||||
}
|
||||
|
||||
bool Debugger::cmd_step(int argc, const char **argv) {
|
||||
_script->step();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_go(int argc, const char **argv) {
|
||||
_script->step();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_fg(int argc, const char **argv) {
|
||||
_vm->_graphicsMan->updateScreen(&_vm->_graphicsMan->_foreground);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_bg(int argc, const char **argv) {
|
||||
_vm->_graphicsMan->updateScreen(&_vm->_graphicsMan->_background);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_pc(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
int val = getNumber(argv[1]);
|
||||
_script->_currentInstruction = val;
|
||||
}
|
||||
DebugPrintf("pc = 0x%04X\n", _script->_currentInstruction);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_mem(int argc, const char **argv) {
|
||||
if (argc >= 2) {
|
||||
int pos = getNumber(argv[1]);
|
||||
uint8 val;
|
||||
if (argc >= 3) {
|
||||
// Set
|
||||
val = getNumber(argv[2]);
|
||||
_script->_variables[pos] = val;
|
||||
} else {
|
||||
// Get
|
||||
val = _script->_variables[pos];
|
||||
}
|
||||
DebugPrintf("mem[0x%04X] = 0x%02X\n", pos, val);
|
||||
} else {
|
||||
DebugPrintf("Syntax: mem <addr> [<val>]\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_loadgame(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
int slot = getNumber(argv[1]);
|
||||
_script->loadgame(slot);
|
||||
} else {
|
||||
DebugPrintf("Syntax: load <slot>\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_savegame(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
int slot = getNumber(argv[1]);
|
||||
_script->savegame(slot);
|
||||
} else {
|
||||
DebugPrintf("Syntax: save <slot>\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_playref(int argc, const char **argv) {
|
||||
if (argc == 2) {
|
||||
int ref = getNumber(argv[1]);
|
||||
_script->playvideofromref(ref);
|
||||
} else {
|
||||
DebugPrintf("Syntax: playref <videorefnum>\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Debugger::cmd_dumppal(int argc, const char **argv) {
|
||||
uint16 i;
|
||||
byte palettedump[256 * 4];
|
||||
_syst->grabPalette(palettedump, 0, 256);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
DebugPrintf("%3d: %3d,%3d,%3d,%3d\n", i, palettedump[(i * 4)], palettedump[(i * 4) + 1], palettedump[(i * 4) + 2], palettedump[(i * 4) + 3]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of Groovie namespace
|
63
engines/groovie/debug.h
Normal file
63
engines/groovie/debug.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_DEBUG_H
|
||||
#define GROOVIE_DEBUG_H
|
||||
|
||||
#include "gui/debugger.h"
|
||||
#include "engines/engine.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class Script;
|
||||
class GroovieEngine;
|
||||
|
||||
class Debugger : public GUI::Debugger {
|
||||
public:
|
||||
Debugger(GroovieEngine *vm);
|
||||
~Debugger();
|
||||
|
||||
private:
|
||||
GroovieEngine *_vm;
|
||||
Script *_script;
|
||||
OSystem *_syst;
|
||||
|
||||
int getNumber(const char *arg);
|
||||
|
||||
bool cmd_step(int argc, const char **argv);
|
||||
bool cmd_go(int argc, const char **argv);
|
||||
bool cmd_pc(int argc, const char **argv);
|
||||
bool cmd_bg(int argc, const char **argv);
|
||||
bool cmd_fg(int argc, const char **argv);
|
||||
bool cmd_mem(int argc, const char **argv);
|
||||
bool cmd_loadgame(int argc, const char **argv);
|
||||
bool cmd_savegame(int argc, const char **argv);
|
||||
bool cmd_playref(int argc, const char **argv);
|
||||
bool cmd_dumppal(int argc, const char **argv);
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_DEBUG_H
|
265
engines/groovie/detection.cpp
Normal file
265
engines/groovie/detection.cpp
Normal file
|
@ -0,0 +1,265 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/savefile.h"
|
||||
|
||||
#include "groovie/groovie.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
//#define GROOVIE_EXPERIMENTAL
|
||||
|
||||
static const PlainGameDescriptor groovieGames[] = {
|
||||
// Games
|
||||
{"t7g", "The 7th Guest"},
|
||||
|
||||
#ifdef GROOVIE_EXPERIMENTAL
|
||||
{"11h", "The 11th Hour: The sequel to The 7th Guest"},
|
||||
{"clandestiny", "Clandestiny"},
|
||||
{"unclehenry", "Uncle Henry's Playhouse"},
|
||||
{"tlc", "Tender Loving Care"},
|
||||
|
||||
// Extras
|
||||
{"making11h", "The Making of The 11th Hour"},
|
||||
{"clantrailer", "Clandestiny Trailer"},
|
||||
#endif
|
||||
|
||||
// Unknown
|
||||
{"groovie", "Groovie engine game"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static const GroovieGameDescription gameDescriptions[] = {
|
||||
|
||||
// The 7th Guest DOS English
|
||||
{
|
||||
{
|
||||
"t7g", "",
|
||||
AD_ENTRY1s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659),
|
||||
Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS
|
||||
},
|
||||
kGroovieT7G, 0
|
||||
},
|
||||
|
||||
// The 7th Guest Mac English
|
||||
{
|
||||
{
|
||||
"t7g", "",
|
||||
AD_ENTRY1s("script.grv", "6e30b54b1f3bc2262cdcf7961db2ae67", 17191),
|
||||
Common::EN_ANY, Common::kPlatformMacintosh, Common::ADGF_NO_FLAGS
|
||||
},
|
||||
kGroovieT7G, 0
|
||||
},
|
||||
|
||||
#ifdef GROOVIE_EXPERIMENTAL
|
||||
// The 11th Hour DOS English
|
||||
{
|
||||
{
|
||||
"11h", "",
|
||||
AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
|
||||
Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS
|
||||
},
|
||||
kGroovieV2, 1
|
||||
},
|
||||
|
||||
// The Making of The 11th Hour DOS English
|
||||
{
|
||||
{
|
||||
"making11h", "",
|
||||
AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
|
||||
Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS
|
||||
},
|
||||
kGroovieV2, 2
|
||||
},
|
||||
|
||||
// Clandestiny Trailer DOS English
|
||||
{
|
||||
{
|
||||
"clantrailer", "",
|
||||
AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
|
||||
Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS
|
||||
},
|
||||
kGroovieV2, 3
|
||||
},
|
||||
|
||||
// Clandestiny DOS English
|
||||
{
|
||||
{
|
||||
"clandestiny", "",
|
||||
AD_ENTRY1s("disk.1", "f79fc1515174540fef6a34132efc4c53", 76),
|
||||
Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS
|
||||
},
|
||||
kGroovieV2, 1
|
||||
},
|
||||
|
||||
// Uncle Henry's Playhouse PC English
|
||||
{
|
||||
{
|
||||
"unclehenry", "",
|
||||
AD_ENTRY1s("disk.1", "0e1b1d3cecc4fc7efa62a968844d1f7a", 72),
|
||||
Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS
|
||||
},
|
||||
kGroovieV2, 1
|
||||
},
|
||||
|
||||
// Tender Loving Care PC English
|
||||
{
|
||||
{
|
||||
"tlc", "",
|
||||
AD_ENTRY1s("disk.1", "32a1afa68478f1f9d2b25eeea427f2e3", 84),
|
||||
Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS
|
||||
},
|
||||
kGroovieV2, 1
|
||||
},
|
||||
#endif
|
||||
|
||||
{AD_TABLE_END_MARKER, kGroovieT7G, 0}
|
||||
};
|
||||
|
||||
static const Common::ADParams detectionParams = {
|
||||
// Pointer to ADGameDescription or its superset structure
|
||||
(const byte *)gameDescriptions,
|
||||
// Size of that superset structure
|
||||
sizeof(GroovieGameDescription),
|
||||
// Number of bytes to compute MD5 sum for
|
||||
5000,
|
||||
// List of all engine targets
|
||||
groovieGames,
|
||||
// Structure for autoupgrading obsolete targets
|
||||
0,
|
||||
// Name of single gameid (optional)
|
||||
0,
|
||||
// List of files for file-based fallback detection (optional)
|
||||
0,
|
||||
// Flags
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
class GroovieMetaEngine : public Common::AdvancedMetaEngine {
|
||||
public:
|
||||
GroovieMetaEngine() : Common::AdvancedMetaEngine(detectionParams) {}
|
||||
|
||||
const char *getName() const {
|
||||
return "Groovie Engine";
|
||||
}
|
||||
|
||||
const char *getCopyright() const {
|
||||
return "Groovie Engine (C) 1990-1996 Trilobyte";
|
||||
}
|
||||
|
||||
bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *gd) const;
|
||||
|
||||
bool hasFeature(MetaEngineFeature f) const;
|
||||
SaveStateList listSaves(const char *target) const;
|
||||
void removeSaveState(const char *target, int slot) const;
|
||||
};
|
||||
|
||||
bool GroovieMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *gd) const {
|
||||
if (gd) {
|
||||
*engine = new GroovieEngine(syst, (GroovieGameDescription *)gd);
|
||||
}
|
||||
return gd != 0;
|
||||
}
|
||||
|
||||
bool GroovieMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsListSaves) ||
|
||||
(f == kSupportsLoadingDuringStartup) ||
|
||||
(f == kSupportsDeleteSave);
|
||||
//(f == kSavesSupportCreationDate)
|
||||
}
|
||||
|
||||
SaveStateList GroovieMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *sfm = g_system->getSavefileManager();
|
||||
SaveStateList list;
|
||||
|
||||
// Get the list of savefiles
|
||||
Common::String pattern = Common::String(target) + ".00?";
|
||||
Common::StringList savefiles = sfm->listSavefiles(pattern.c_str());
|
||||
|
||||
// Sort the list of filenames
|
||||
sort(savefiles.begin(), savefiles.end());
|
||||
|
||||
// Fill the information for the existing savegames
|
||||
Common::StringList::iterator it = savefiles.begin();
|
||||
while (it != savefiles.end()) {
|
||||
int slot = it->lastChar() - '0';
|
||||
if (slot >= 0 && slot <= 9) {
|
||||
Common::InSaveFile *file = sfm->openForLoading(it->c_str());
|
||||
|
||||
// Read the savegame description
|
||||
Common::String description;
|
||||
unsigned char c = 1;
|
||||
for (int i = 0; (c != 0) && (i < 15); i++) {
|
||||
c = file->readByte();
|
||||
switch (c) {
|
||||
case 0:
|
||||
break;
|
||||
case 16: // @
|
||||
c = ' ';
|
||||
break;
|
||||
case 244: // $
|
||||
c = 0;
|
||||
break;
|
||||
default:
|
||||
c += 0x30;
|
||||
}
|
||||
if (c != 0) {
|
||||
description += c;
|
||||
}
|
||||
}
|
||||
delete file;
|
||||
|
||||
list.push_back(SaveStateDescriptor(slot, description));
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void GroovieMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
if (slot < 0 || slot > 9) {
|
||||
// Invalid slot, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
char extension[6];
|
||||
snprintf(extension, sizeof(extension), ".00%01d", slot);
|
||||
|
||||
Common::String filename = target;
|
||||
filename += extension;
|
||||
|
||||
g_system->getSavefileManager()->removeSavefile(filename.c_str());
|
||||
}
|
||||
|
||||
} // End of namespace Groovie
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(GROOVIE)
|
||||
REGISTER_PLUGIN_DYNAMIC(GROOVIE, PLUGIN_TYPE_ENGINE, Groovie::GroovieMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(GROOVIE, PLUGIN_TYPE_ENGINE, Groovie::GroovieMetaEngine);
|
||||
#endif
|
128
engines/groovie/font.cpp
Normal file
128
engines/groovie/font.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "groovie/font.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
Font::Font(OSystem *syst) :
|
||||
_syst(syst), _sphinxfnt(NULL) {
|
||||
|
||||
Common::File fontfile;
|
||||
if (!fontfile.open("sphinx.fnt")) {
|
||||
error("Groovie::Font: Couldn't open sphinx.fnt");
|
||||
}
|
||||
uint16 fontfilesize = fontfile.size();
|
||||
_sphinxfnt = fontfile.readStream(fontfilesize);
|
||||
fontfile.close();
|
||||
}
|
||||
|
||||
Font::~Font() {
|
||||
delete _sphinxfnt;
|
||||
}
|
||||
|
||||
void Font::printstring(char *messagein) {
|
||||
uint16 totalwidth = 0, currxoffset, i;
|
||||
|
||||
char message[15];
|
||||
memset(message, 0, 15);
|
||||
|
||||
// Clear the top bar
|
||||
Common::Rect topbar(640, 80);
|
||||
Graphics::Surface *gamescreen;
|
||||
gamescreen = _syst->lockScreen();
|
||||
gamescreen->fillRect(topbar, 0);
|
||||
_syst->unlockScreen();
|
||||
|
||||
for (i = 0; i < 14; i++) {
|
||||
char chartocopy = messagein[i];
|
||||
if (chartocopy <= 0x00 || chartocopy == 0x24) {
|
||||
break;
|
||||
}
|
||||
message[i] = chartocopy;
|
||||
}
|
||||
Common::rtrim(message);
|
||||
for (i = 0; i < strlen(message); i++) {
|
||||
totalwidth += letterwidth(message[i]);
|
||||
}
|
||||
currxoffset = (640 - totalwidth) / 2;
|
||||
char *currpos = message;
|
||||
while (*(currpos) != 0) {
|
||||
currxoffset += printletter(*(currpos++), currxoffset);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Font::letteroffset(char letter) {
|
||||
uint16 offset;
|
||||
offset = letter;
|
||||
_sphinxfnt->seek(offset);
|
||||
offset = _sphinxfnt->readByte() * 2 + 128;
|
||||
_sphinxfnt->seek(offset);
|
||||
offset = _sphinxfnt->readUint16LE();
|
||||
return offset;
|
||||
}
|
||||
|
||||
uint8 Font::letterwidth(char letter) {
|
||||
uint16 offset = letteroffset(letter);
|
||||
_sphinxfnt->seek(offset);
|
||||
return _sphinxfnt->readByte();
|
||||
}
|
||||
|
||||
uint8 Font::letterheight(char letter) {
|
||||
uint16 offset, width, julia, data, counter = 0;
|
||||
offset = letteroffset(letter);
|
||||
_sphinxfnt->seek(offset);
|
||||
width = _sphinxfnt->readByte();
|
||||
julia = _sphinxfnt->readByte();
|
||||
data = _sphinxfnt->readByte();
|
||||
while (data != 0xFF) {
|
||||
data = _sphinxfnt->readByte();
|
||||
counter++;
|
||||
}
|
||||
if (counter % width != 0) assert("font file corrupt");
|
||||
return counter / width;
|
||||
}
|
||||
|
||||
|
||||
uint8 Font::printletter(char letter, uint16 xoffset) {
|
||||
uint16 offset, width, height, julia;
|
||||
offset = letteroffset(letter);
|
||||
height = letterheight(letter);
|
||||
_sphinxfnt->seek(offset);
|
||||
width = _sphinxfnt->readByte();
|
||||
julia = _sphinxfnt->readByte();
|
||||
|
||||
byte *data = new byte[width * height];
|
||||
_sphinxfnt->read(data, width * height);
|
||||
_syst->copyRectToScreen(data, width, xoffset, 16, width, height);
|
||||
delete data;
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
} // End of Groovie namespace
|
52
engines/groovie/font.h
Normal file
52
engines/groovie/font.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_FONT_H
|
||||
#define GROOVIE_FONT_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class Font {
|
||||
public:
|
||||
Font(OSystem *syst);
|
||||
~Font();
|
||||
void printstring(char *messagein);
|
||||
|
||||
private:
|
||||
OSystem *_syst;
|
||||
Common::MemoryReadStream *_sphinxfnt;
|
||||
|
||||
uint16 letteroffset(char letter);
|
||||
uint8 letterwidth(char letter);
|
||||
uint8 letterheight(char letter);
|
||||
uint8 printletter(char letter, uint16 xoffset);
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_FONT_H
|
161
engines/groovie/graphics.cpp
Normal file
161
engines/groovie/graphics.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/groovie.h"
|
||||
#include "groovie/graphics.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
GraphicsMan::GraphicsMan(GroovieEngine *vm) :
|
||||
_vm(vm), _changed(false), _fading(0) {
|
||||
// Create the game surfaces
|
||||
_foreground.create(640, 320, 1);
|
||||
_background.create(640, 320, 1);
|
||||
}
|
||||
|
||||
GraphicsMan::~GraphicsMan() {
|
||||
// Free the game surfaces
|
||||
_foreground.free();
|
||||
_background.free();
|
||||
}
|
||||
|
||||
void GraphicsMan::update() {
|
||||
if (_fading) {
|
||||
// Set the start time
|
||||
uint32 time = _vm->_system->getMillis() - _fadeStartTime;
|
||||
|
||||
// Scale the time
|
||||
int step = time / 4;
|
||||
if (step > 256) {
|
||||
step = 256;
|
||||
}
|
||||
|
||||
if (_fading == 1) {
|
||||
// Apply the fade in
|
||||
applyFading(step);
|
||||
} else if (_fading == 2) {
|
||||
// Apply the fade out
|
||||
applyFading(256 - step);
|
||||
|
||||
// Clear the buffer when ending the fade out
|
||||
if (step == 256)
|
||||
_foreground.fillRect(Common::Rect::Rect(640, 320), 0);
|
||||
}
|
||||
|
||||
// Check for the end
|
||||
if (step == 256) {
|
||||
_fading = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the screen if needed and reset the status
|
||||
if (_changed) {
|
||||
_vm->_system->updateScreen();
|
||||
_changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsMan::change() {
|
||||
_changed = true;
|
||||
}
|
||||
|
||||
void GraphicsMan::mergeFgAndBg() {
|
||||
uint32 i;
|
||||
byte *countf, *countb;
|
||||
|
||||
countf = (byte *)_foreground.getBasePtr(0, 0);
|
||||
countb = (byte *)_background.getBasePtr(0, 0);
|
||||
for (i = 640 * 320; i; i--) {
|
||||
if (255 == *(countf)) {
|
||||
*(countf) = *(countb);
|
||||
}
|
||||
countf++;
|
||||
countb++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GraphicsMan::updateScreen(Graphics::Surface *source) {
|
||||
_vm->_system->copyRectToScreen((byte *)source->getBasePtr(0, 0), 640, 0, 80, 640, 320);
|
||||
change();
|
||||
}
|
||||
|
||||
bool GraphicsMan::isFading() {
|
||||
return _fading;
|
||||
}
|
||||
|
||||
void GraphicsMan::fadeIn(byte *pal) {
|
||||
// Set the start time
|
||||
_fadeStartTime = _vm->_system->getMillis();
|
||||
|
||||
// Copy the target palette
|
||||
for (int i = 0; i < 256; i++) {
|
||||
_paletteFull[(i * 4) + 0] = pal[(i * 3) + 0];
|
||||
_paletteFull[(i * 4) + 1] = pal[(i * 3) + 1];
|
||||
_paletteFull[(i * 4) + 2] = pal[(i * 3) + 2];
|
||||
}
|
||||
|
||||
// Apply a black palette right now
|
||||
applyFading(0);
|
||||
|
||||
// Set the current fading
|
||||
_fading = 1;
|
||||
}
|
||||
|
||||
void GraphicsMan::fadeOut() {
|
||||
// Set the start time
|
||||
_fadeStartTime = _vm->_system->getMillis();
|
||||
|
||||
// Get the current palette
|
||||
_vm->_system->grabPalette(_paletteFull, 0, 256);
|
||||
|
||||
// Set the current fading
|
||||
_fading = 2;
|
||||
}
|
||||
|
||||
void GraphicsMan::applyFading(int step) {
|
||||
// Calculate the fade factor for the given step
|
||||
int factorR = 256 - (256 - step) * 1;
|
||||
int factorGB = 256 - (256 - step) * 2;
|
||||
|
||||
if (factorR <= 0) factorR = 0;
|
||||
if (factorGB <= 0) factorGB = 0;
|
||||
|
||||
// Calculate the new palette
|
||||
byte newpal[256 * 4];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
newpal[(i * 4) + 0] = (_paletteFull[(i * 4) + 0] * factorR) / 256;
|
||||
newpal[(i * 4) + 1] = (_paletteFull[(i * 4) + 1] * factorGB) / 256;
|
||||
newpal[(i * 4) + 2] = (_paletteFull[(i * 4) + 2] * factorGB) / 256;
|
||||
}
|
||||
|
||||
// Set the screen palette
|
||||
_vm->_system->setPalette(newpal, 0, 256);
|
||||
|
||||
// Request a screen update
|
||||
change();
|
||||
}
|
||||
|
||||
} // End of Groovie namespace
|
65
engines/groovie/graphics.h
Normal file
65
engines/groovie/graphics.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_GRAPHICS_H
|
||||
#define GROOVIE_GRAPHICS_H
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class GroovieEngine;
|
||||
|
||||
class GraphicsMan {
|
||||
public:
|
||||
GraphicsMan(GroovieEngine *vm);
|
||||
~GraphicsMan();
|
||||
|
||||
// Buffers
|
||||
void update();
|
||||
void change();
|
||||
void mergeFgAndBg();
|
||||
void updateScreen(Graphics::Surface *source);
|
||||
Graphics::Surface _foreground; // The main surface that most things are drawn to
|
||||
Graphics::Surface _background; // Used occasionally, mostly (only?) in puzzles
|
||||
|
||||
// Palette fading
|
||||
bool isFading();
|
||||
void fadeIn(byte *pal);
|
||||
void fadeOut();
|
||||
|
||||
private:
|
||||
GroovieEngine *_vm;
|
||||
|
||||
bool _changed;
|
||||
|
||||
// Palette fading
|
||||
void applyFading(int step);
|
||||
int _fading;
|
||||
byte _paletteFull[256 * 4];
|
||||
uint32 _fadeStartTime;
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_GRAPHICS_H
|
272
engines/groovie/groovie.cpp
Normal file
272
engines/groovie/groovie.cpp
Normal file
|
@ -0,0 +1,272 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/events.h"
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "groovie/groovie.h"
|
||||
#include "groovie/music.h"
|
||||
#include "groovie/roq.h"
|
||||
#include "groovie/vdx.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
GroovieEngine::GroovieEngine(OSystem *syst, GroovieGameDescription *gd) :
|
||||
Engine(syst), _gameDescription(gd), _debugger(NULL), _script(this),
|
||||
_resMan(NULL), _cursorMan(NULL), _videoPlayer(NULL), _musicPlayer(NULL),
|
||||
_graphicsMan(NULL), _waitingForInput(false) {
|
||||
|
||||
// Adding the default directories
|
||||
Common::File::addDefaultDirectory(_gameDataDir.getChild("groovie"));
|
||||
Common::File::addDefaultDirectory(_gameDataDir.getChild("media"));
|
||||
Common::File::addDefaultDirectory(_gameDataDir.getChild("system"));
|
||||
|
||||
// Initialize the custom debug levels
|
||||
Common::addSpecialDebugLevel(kGroovieDebugAll, "All", "Debug everything");
|
||||
Common::addSpecialDebugLevel(kGroovieDebugVideo, "Video", "Debug video and audio playback");
|
||||
Common::addSpecialDebugLevel(kGroovieDebugResource, "Resource", "Debug resouce management");
|
||||
Common::addSpecialDebugLevel(kGroovieDebugScript, "Script", "Debug the scripts");
|
||||
Common::addSpecialDebugLevel(kGroovieDebugUnknown, "Unknown", "Report values of unknown data in files");
|
||||
Common::addSpecialDebugLevel(kGroovieDebugHotspots, "Hotspots", "Show the hotspots");
|
||||
Common::addSpecialDebugLevel(kGroovieDebugCursor, "Cursor", "Debug cursor decompression / switching");
|
||||
}
|
||||
|
||||
GroovieEngine::~GroovieEngine() {
|
||||
// Delete the remaining objects
|
||||
delete _debugger;
|
||||
delete _resMan;
|
||||
delete _cursorMan;
|
||||
delete _videoPlayer;
|
||||
delete _musicPlayer;
|
||||
delete _graphicsMan;
|
||||
}
|
||||
|
||||
Common::Error GroovieEngine::init() {
|
||||
// Initialize the graphics
|
||||
_system->beginGFXTransaction();
|
||||
initCommonGFX(true);
|
||||
_system->initSize(640, 480);
|
||||
_system->endGFXTransaction();
|
||||
|
||||
// Create debugger. It requires GFX to be initialized
|
||||
_debugger = new Debugger(this);
|
||||
_script.setDebugger(_debugger);
|
||||
|
||||
// Create the graphics manager
|
||||
_graphicsMan = new GraphicsMan(this);
|
||||
|
||||
// Create the resource and cursor managers and the video player
|
||||
switch (_gameDescription->version) {
|
||||
case kGroovieT7G:
|
||||
_resMan = new ResMan_t7g();
|
||||
_cursorMan = new CursorMan_t7g(_system);
|
||||
_videoPlayer = new VDXPlayer(this);
|
||||
break;
|
||||
case kGroovieV2:
|
||||
_resMan = new ResMan_v2();
|
||||
_cursorMan = new CursorMan_v2(_system);
|
||||
_videoPlayer = new ROQPlayer(this);
|
||||
break;
|
||||
}
|
||||
|
||||
// Create the music player
|
||||
_musicPlayer = new MusicPlayer(this);
|
||||
|
||||
// Load volume levels
|
||||
syncSoundSettings();
|
||||
|
||||
// Get the name of the main script
|
||||
Common::String filename = _gameDescription->desc.filesDescriptions[0].fileName;
|
||||
if (_gameDescription->version == kGroovieT7G) {
|
||||
// Run The 7th Guest's demo if requested
|
||||
if (ConfMan.hasKey("demo_mode") && ConfMan.getBool("demo_mode")) {
|
||||
filename = Common::String("demo.grv");
|
||||
}
|
||||
} else if (_gameDescription->version == kGroovieV2) {
|
||||
// Open the disk index
|
||||
Common::File disk;
|
||||
if (!disk.open(filename)) {
|
||||
error("Couldn't open %s", filename.c_str());
|
||||
return Common::kNoGameDataFoundError;
|
||||
}
|
||||
|
||||
// Search the entry
|
||||
bool found = false;
|
||||
int index = 0;
|
||||
while (!found && !disk.eos()) {
|
||||
Common::String line = disk.readLine();
|
||||
if (line.hasPrefix("title: ")) {
|
||||
// A new entry
|
||||
index++;
|
||||
} else if (line.hasPrefix("boot: ") && index == _gameDescription->indexEntry) {
|
||||
// It's the boot of the entry were looking for,
|
||||
// get the script filename
|
||||
filename = line.c_str() + 6;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find the entry
|
||||
if (!found) {
|
||||
error("Couldn't find entry %d in %s", _gameDescription->indexEntry, filename.c_str());
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the script file extension
|
||||
if (!filename.hasSuffix(".grv")) {
|
||||
error("%s isn't a valid script filename", filename.c_str());
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
|
||||
// Load the script
|
||||
if (!_script.loadScript(filename)) {
|
||||
error("Couldn't load the script file %s", filename.c_str());
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
|
||||
// Should I load a saved game?
|
||||
if (ConfMan.hasKey("save_slot")) {
|
||||
// Get the requested slot
|
||||
int slot = ConfMan.getInt("save_slot");
|
||||
_script.directGameLoad(slot);
|
||||
}
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error GroovieEngine::go() {
|
||||
// Check that the game files and the audio tracks aren't together run from
|
||||
// the same cd
|
||||
|
||||
checkCD();
|
||||
|
||||
// Initialize the CD
|
||||
int cd_num = ConfMan.getInt("cdrom");
|
||||
if (cd_num >= 0)
|
||||
_system->openCD(cd_num);
|
||||
|
||||
while (!shouldQuit()) {
|
||||
// Show the debugger if required
|
||||
if (_debugger->isAttached()) {
|
||||
_debugger->onFrame();
|
||||
}
|
||||
|
||||
// If there's still a script error after debugging, end the execution
|
||||
if (_script.haveError()) {
|
||||
quitGame();
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle input
|
||||
Common::Event ev;
|
||||
while (_eventMan->pollEvent(ev)) {
|
||||
switch (ev.type) {
|
||||
case Common::EVENT_KEYDOWN:
|
||||
// CTRL-D: Attach the debugger
|
||||
if ((ev.kbd.flags & Common::KBD_CTRL) && ev.kbd.keycode == Common::KEYCODE_d)
|
||||
_debugger->attach();
|
||||
|
||||
// Send the event to the scripts
|
||||
_script.setKbdChar(ev.kbd.ascii);
|
||||
|
||||
// Continue the script execution to handle the key
|
||||
_waitingForInput = false;
|
||||
break;
|
||||
|
||||
case Common::EVENT_MOUSEMOVE:
|
||||
// Continue the script execution, the mouse
|
||||
// pointer may fall inside a hotspot now
|
||||
_waitingForInput = false;
|
||||
break;
|
||||
|
||||
case Common::EVENT_LBUTTONDOWN:
|
||||
// Send the event to the scripts
|
||||
_script.setMouseClick();
|
||||
|
||||
// Continue the script execution to handle
|
||||
// the click
|
||||
_waitingForInput = false;
|
||||
break;
|
||||
|
||||
case Common::EVENT_QUIT:
|
||||
quitGame();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_waitingForInput) {
|
||||
// Still waiting for input, just update the mouse and wait a bit more
|
||||
_cursorMan->animate();
|
||||
_system->updateScreen();
|
||||
_system->delayMillis(50);
|
||||
} else if (_graphicsMan->isFading()) {
|
||||
// We're waiting for a fading to end, let the CPU rest
|
||||
// for a while and continue
|
||||
_system->delayMillis(30);
|
||||
} else {
|
||||
// Everything's fine, execute another script step
|
||||
_script.step();
|
||||
}
|
||||
|
||||
// Update the screen if required
|
||||
_graphicsMan->update();
|
||||
}
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool GroovieEngine::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsRTL) ||
|
||||
(f == kSupportsLoadingDuringRuntime);
|
||||
}
|
||||
|
||||
void GroovieEngine::syncSoundSettings() {
|
||||
_musicPlayer->setUserVolume(ConfMan.getInt("music_volume"));
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("speech_volume"));
|
||||
}
|
||||
|
||||
bool GroovieEngine::canLoadGameStateCurrently() {
|
||||
// TODO: verify the engine has been initialized
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::Error GroovieEngine::loadGameState(int slot) {
|
||||
_script.directGameLoad(slot);
|
||||
|
||||
// TODO: Use specific error codes
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
void GroovieEngine::waitForInput() {
|
||||
_waitingForInput = true;
|
||||
}
|
||||
|
||||
} // End of namespace Groovie
|
103
engines/groovie/groovie.h
Normal file
103
engines/groovie/groovie.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_H
|
||||
#define GROOVIE_H
|
||||
|
||||
#include "common/advancedDetector.h"
|
||||
#include "engines/engine.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "groovie/cursor.h"
|
||||
#include "groovie/debug.h"
|
||||
#include "groovie/graphics.h"
|
||||
#include "groovie/player.h"
|
||||
#include "groovie/resource.h"
|
||||
#include "groovie/script.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class MusicPlayer;
|
||||
|
||||
enum kDebugLevels {
|
||||
kGroovieDebugAll = 1 << 0,
|
||||
kGroovieDebugVideo = 1 << 1,
|
||||
kGroovieDebugResource = 1 << 2,
|
||||
kGroovieDebugScript = 1 << 3,
|
||||
kGroovieDebugUnknown = 1 << 4,
|
||||
kGroovieDebugHotspots = 1 << 5,
|
||||
kGroovieDebugCursor = 1 << 6,
|
||||
kGroovieDebugMIDI = 1 << 7
|
||||
// the current limitation is 32 debug levels (1 << 31 is the last one)
|
||||
};
|
||||
|
||||
enum kEngineVersion {
|
||||
kGroovieT7G,
|
||||
kGroovieV2
|
||||
};
|
||||
|
||||
struct GroovieGameDescription {
|
||||
Common::ADGameDescription desc;
|
||||
|
||||
kEngineVersion version; // Version of the engine
|
||||
int indexEntry; // The index of the entry in disk.1 for V2 games
|
||||
};
|
||||
|
||||
class GroovieEngine : public Engine {
|
||||
public:
|
||||
GroovieEngine(OSystem *syst, GroovieGameDescription *gd);
|
||||
~GroovieEngine();
|
||||
|
||||
protected:
|
||||
Common::Error init();
|
||||
Common::Error go();
|
||||
|
||||
public:
|
||||
bool hasFeature(EngineFeature f) const;
|
||||
|
||||
bool canLoadGameStateCurrently();
|
||||
Common::Error loadGameState(int slot);
|
||||
void syncSoundSettings();
|
||||
|
||||
Debugger *getDebugger() { return _debugger; }
|
||||
|
||||
void waitForInput();
|
||||
|
||||
Script _script;
|
||||
ResMan *_resMan;
|
||||
CursorMan *_cursorMan;
|
||||
VideoPlayer *_videoPlayer;
|
||||
MusicPlayer *_musicPlayer;
|
||||
GraphicsMan *_graphicsMan;
|
||||
|
||||
private:
|
||||
GroovieGameDescription *_gameDescription;
|
||||
Debugger *_debugger;
|
||||
bool _waitingForInput;
|
||||
};
|
||||
|
||||
} // End of namespace Groovie
|
||||
|
||||
#endif // GROOVIE_H
|
99
engines/groovie/lzss.cpp
Normal file
99
engines/groovie/lzss.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/lzss.h"
|
||||
|
||||
#define OUT_BUFF_SIZE 131072
|
||||
#define COMP_THRESH 3 // Compression not attempted if string to be compressed is less than 3 long
|
||||
|
||||
LzssReadStream::LzssReadStream(Common::ReadStream *indata, uint8 lengthmask, uint8 lengthbits) {
|
||||
/*
|
||||
TODO: Nasty hack. Make a buffer bigger than I'll ever need... probably.
|
||||
What should *really* happen is I should define a whole new type of stream
|
||||
that gets lzss decompressed on the fly
|
||||
*/
|
||||
_outLzssBufData = (uint8 *)malloc(OUT_BUFF_SIZE);
|
||||
_size = decodeLZSS(indata, lengthmask, lengthbits);
|
||||
_pos = 0;
|
||||
}
|
||||
|
||||
LzssReadStream::~LzssReadStream() {
|
||||
free(_outLzssBufData);
|
||||
}
|
||||
|
||||
uint32 LzssReadStream::decodeLZSS(Common::ReadStream *in, uint8 lengthmask, uint8 lengthbits) {
|
||||
uint32 N = 1 << (16 - lengthbits); /* History buffer size */
|
||||
byte *histbuff = new byte[N]; /* History buffer */
|
||||
memset(histbuff, 0, N);
|
||||
uint32 outstreampos = 0;
|
||||
uint32 bufpos = 0;
|
||||
|
||||
while (!in->eos()) {
|
||||
byte flagbyte = in->readByte();
|
||||
for (uint32 i = 1; i <= 8; i++) {
|
||||
if (!in->eos()) {
|
||||
if ((flagbyte & 1) == 0) {
|
||||
uint32 offsetlen = in->readUint16LE();
|
||||
if (offsetlen == 0) {
|
||||
break;
|
||||
}
|
||||
uint32 length = (offsetlen & lengthmask) + COMP_THRESH;
|
||||
uint32 offset = (bufpos - (offsetlen >> lengthbits)) & (N - 1);
|
||||
for (uint32 j = 0; j < length; j++) {
|
||||
byte tempa = histbuff[(offset + j) & (N - 1)];
|
||||
_outLzssBufData[outstreampos++] = tempa;
|
||||
histbuff[bufpos] = tempa;
|
||||
bufpos = (bufpos + 1) & (N - 1);
|
||||
}
|
||||
} else {
|
||||
byte tempa = in->readByte();
|
||||
if (in->eos()) {
|
||||
break;
|
||||
}
|
||||
_outLzssBufData[outstreampos++] = tempa;
|
||||
histbuff[bufpos] = tempa;
|
||||
bufpos = (bufpos + 1) & (N - 1);
|
||||
}
|
||||
flagbyte = flagbyte >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] histbuff;
|
||||
return outstreampos;
|
||||
}
|
||||
|
||||
bool LzssReadStream::eos() const {
|
||||
return _pos >= _size;
|
||||
}
|
||||
|
||||
uint32 LzssReadStream::read(void *buf, uint32 size) {
|
||||
if (size > _size - _pos)
|
||||
size = _size - _pos;
|
||||
|
||||
memcpy(buf, &_outLzssBufData[_pos], size);
|
||||
_pos += size;
|
||||
|
||||
return size;
|
||||
}
|
42
engines/groovie/lzss.h
Normal file
42
engines/groovie/lzss.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
class LzssReadStream : public Common::ReadStream {
|
||||
private:
|
||||
uint8 *_outLzssBufData;
|
||||
uint32 _size;
|
||||
uint32 _pos;
|
||||
|
||||
uint32 decodeLZSS(Common::ReadStream *in, uint8 lengthmask, uint8 lengthbits);
|
||||
|
||||
public:
|
||||
LzssReadStream(Common::ReadStream *indata, uint8 lengthmask, uint8 lengthbits);
|
||||
~LzssReadStream();
|
||||
|
||||
bool eos() const;
|
||||
uint32 read(void *buf, uint32 size);
|
||||
};
|
24
engines/groovie/module.mk
Normal file
24
engines/groovie/module.mk
Normal file
|
@ -0,0 +1,24 @@
|
|||
MODULE := engines/groovie
|
||||
|
||||
MODULE_OBJS := \
|
||||
cursor.o \
|
||||
debug.o \
|
||||
detection.o \
|
||||
font.o \
|
||||
graphics.o \
|
||||
groovie.o \
|
||||
lzss.o \
|
||||
music.o \
|
||||
player.o \
|
||||
resource.o \
|
||||
roq.o \
|
||||
script.o \
|
||||
vdx.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_GROOVIE), DYNAMIC_PLUGIN)
|
||||
PLUGIN := 1
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
211
engines/groovie/music.cpp
Normal file
211
engines/groovie/music.cpp
Normal file
|
@ -0,0 +1,211 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/music.h"
|
||||
#include "groovie/resource.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
MusicPlayer::MusicPlayer(GroovieEngine *vm) :
|
||||
_vm(vm), _midiParser(NULL), _data(NULL), _driver(NULL),
|
||||
_backgroundFileRef(0) {
|
||||
// Create the parser
|
||||
_midiParser = MidiParser::createParser_XMIDI();
|
||||
|
||||
// Create the driver
|
||||
int driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
|
||||
_driver = createMidi(driver);
|
||||
_driver->open();
|
||||
|
||||
// Initialize the channel volumes
|
||||
for (int i = 0; i < 0x10; i++) {
|
||||
_chanVolumes[i] = 0x7F;
|
||||
}
|
||||
|
||||
// Set the parser's driver
|
||||
_midiParser->setMidiDriver(this);
|
||||
|
||||
// Set the timer rate
|
||||
_midiParser->setTimerRate(_driver->getBaseTempo());
|
||||
}
|
||||
|
||||
MusicPlayer::~MusicPlayer() {
|
||||
// Unload the parser
|
||||
unload();
|
||||
delete _midiParser;
|
||||
|
||||
// Unload the MIDI Driver
|
||||
_driver->close();
|
||||
delete _driver;
|
||||
}
|
||||
|
||||
void MusicPlayer::playSong(uint16 fileref) {
|
||||
// Play the referenced file once
|
||||
play(fileref, false);
|
||||
}
|
||||
|
||||
void MusicPlayer::setBackgroundSong(uint16 fileref) {
|
||||
_backgroundFileRef = fileref;
|
||||
}
|
||||
|
||||
void MusicPlayer::setUserVolume(uint16 volume) {
|
||||
// Save the new user volume
|
||||
_userVolume = volume;
|
||||
if (_userVolume > 0x100) _userVolume = 0x100;
|
||||
|
||||
// Apply it to all the channels
|
||||
for (int i = 0; i < 0x10; i++) {
|
||||
updateChanVolume(i);
|
||||
}
|
||||
//FIXME: AdlibPercussionChannel::controlChange() is empty
|
||||
//(can't set the volume for the percusion channel)
|
||||
}
|
||||
|
||||
void MusicPlayer::setGameVolume(uint16 volume, uint16 time) {
|
||||
//TODO: Implement volume fading
|
||||
debugC(5, kGroovieDebugMIDI | kGroovieDebugAll, "setting game volume: %d, %d\n", volume, time);
|
||||
|
||||
// Save the new game volume
|
||||
_gameVolume = volume;
|
||||
if (_gameVolume > 100) _gameVolume = 100;
|
||||
|
||||
// Apply it to all the channels
|
||||
for (int i = 0; i < 0x10; i++) {
|
||||
updateChanVolume(i);
|
||||
}
|
||||
}
|
||||
|
||||
void MusicPlayer::updateChanVolume(byte channel) {
|
||||
// Generate a MIDI Control change message for the volume
|
||||
uint32 b = 0x7B0;
|
||||
|
||||
// Specify the channel
|
||||
b |= (channel & 0xF);
|
||||
|
||||
// Scale by the user and game volumes
|
||||
uint32 val = (_chanVolumes[channel] * _userVolume * _gameVolume) / 0x100 / 100;
|
||||
val &= 0x7F;
|
||||
|
||||
// Send it to the driver
|
||||
_driver->send(b | (val << 16));
|
||||
}
|
||||
|
||||
bool MusicPlayer::play(uint16 fileref, bool loop) {
|
||||
// Unload the previous song
|
||||
unload();
|
||||
|
||||
// Set the looping option
|
||||
_midiParser->property(MidiParser::mpAutoLoop, loop);
|
||||
|
||||
// Load the new file
|
||||
return load(fileref);
|
||||
}
|
||||
|
||||
bool MusicPlayer::load(uint16 fileref) {
|
||||
// Open the song resource
|
||||
Common::SeekableReadStream *xmidiFile = _vm->_resMan->open(fileref);
|
||||
if (!xmidiFile) {
|
||||
error("Groovie::Music: Couldn't resource 0x%04X", fileref);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the whole file to memory
|
||||
int length = xmidiFile->size();
|
||||
_data = new byte[length];
|
||||
xmidiFile->read(_data, length);
|
||||
delete xmidiFile;
|
||||
|
||||
// Start parsing the data
|
||||
if (!_midiParser->loadMusic(_data, length)) {
|
||||
error("Groovie::Music: Invalid XMI file");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Activate the timer source
|
||||
_driver->setTimerCallback(_midiParser, MidiParser::timerCallback);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MusicPlayer::unload() {
|
||||
// Unload the parser
|
||||
_midiParser->unloadMusic();
|
||||
|
||||
// Unload the xmi file
|
||||
delete[] _data;
|
||||
_data = NULL;
|
||||
}
|
||||
|
||||
int MusicPlayer::open() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MusicPlayer::close() {}
|
||||
|
||||
void MusicPlayer::send(uint32 b) {
|
||||
if ((b & 0xFFF0) == 0x07B0) { // Volume change
|
||||
// Save the specific channel volume
|
||||
byte chan = b & 0xF;
|
||||
_chanVolumes[chan] = (b >> 16) & 0x7F;
|
||||
|
||||
// Send the updated value
|
||||
updateChanVolume(chan);
|
||||
|
||||
return;
|
||||
}
|
||||
_driver->send(b);
|
||||
}
|
||||
|
||||
void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
|
||||
switch (type) {
|
||||
case 0x2F:
|
||||
// End of Track, play the background song
|
||||
if (_backgroundFileRef) {
|
||||
play(_backgroundFileRef, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_driver->metaEvent(type, data, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MusicPlayer::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
|
||||
_driver->setTimerCallback(timer_param, timer_proc);
|
||||
}
|
||||
|
||||
uint32 MusicPlayer::getBaseTempo(void) {
|
||||
return _driver->getBaseTempo();
|
||||
}
|
||||
|
||||
MidiChannel *MusicPlayer::allocateChannel() {
|
||||
return _driver->allocateChannel();
|
||||
}
|
||||
|
||||
MidiChannel *MusicPlayer::getPercussionChannel() {
|
||||
return _driver->getPercussionChannel();
|
||||
}
|
||||
|
||||
} // End of Groovie namespace
|
78
engines/groovie/music.h
Normal file
78
engines/groovie/music.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_MUSIC_H
|
||||
#define GROOVIE_MUSIC_H
|
||||
|
||||
#include "groovie/groovie.h"
|
||||
|
||||
#include "sound/mididrv.h"
|
||||
#include "sound/midiparser.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class MusicPlayer : public MidiDriver {
|
||||
public:
|
||||
MusicPlayer(GroovieEngine *vm);
|
||||
~MusicPlayer();
|
||||
void playSong(uint16 fileref);
|
||||
void setBackgroundSong(uint16 fileref);
|
||||
|
||||
// Volume
|
||||
void setUserVolume(uint16 volume);
|
||||
void setGameVolume(uint16 volume, uint16 time);
|
||||
private:
|
||||
uint16 _userVolume;
|
||||
uint16 _gameVolume;
|
||||
byte _chanVolumes[0x10];
|
||||
void updateChanVolume(byte channel);
|
||||
|
||||
public:
|
||||
// MidiDriver interface
|
||||
int open();
|
||||
void close();
|
||||
void send(uint32 b);
|
||||
void metaEvent(byte type, byte *data, uint16 length);
|
||||
void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
|
||||
uint32 getBaseTempo(void);
|
||||
MidiChannel *allocateChannel();
|
||||
MidiChannel *getPercussionChannel();
|
||||
|
||||
private:
|
||||
GroovieEngine *_vm;
|
||||
byte *_data;
|
||||
MidiParser *_midiParser;
|
||||
MidiDriver *_driver;
|
||||
|
||||
uint16 _backgroundFileRef;
|
||||
|
||||
bool play(uint16 fileref, bool loop);
|
||||
bool load(uint16 fileref);
|
||||
void unload();
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_MUSIC_H
|
98
engines/groovie/player.cpp
Normal file
98
engines/groovie/player.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/groovie.h"
|
||||
#include "groovie/player.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
VideoPlayer::VideoPlayer(GroovieEngine *vm) :
|
||||
_vm(vm), _syst(vm->_system), _file(NULL), _audioStream(NULL) {
|
||||
}
|
||||
|
||||
bool VideoPlayer::load(Common::SeekableReadStream *file, uint16 flags) {
|
||||
_file = file;
|
||||
_flags = flags;
|
||||
_audioStream = NULL;
|
||||
|
||||
uint16 fps = loadInternal();
|
||||
|
||||
if (fps != 0) {
|
||||
_millisBetweenFrames = 1000 / fps;
|
||||
_begunPlaying = false;
|
||||
return true;
|
||||
} else {
|
||||
_file = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoPlayer::playFrame() {
|
||||
bool end = true;
|
||||
|
||||
// Process the next frame while the file is open
|
||||
if (_file) {
|
||||
end = playFrameInternal();
|
||||
}
|
||||
|
||||
// The file has been completely processed
|
||||
if (end) {
|
||||
_file = NULL;
|
||||
|
||||
// Wait for pending audio
|
||||
if (_audioStream) {
|
||||
if (_audioStream->endOfData()) {
|
||||
// Mark the audio stream as finished (no more data will be appended)
|
||||
_audioStream->finish();
|
||||
} else {
|
||||
// Don't end if there's still audio playing
|
||||
end = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
void VideoPlayer::waitFrame() {
|
||||
uint32 currTime = _syst->getMillis();
|
||||
if (!_begunPlaying) {
|
||||
_begunPlaying = true;
|
||||
_lastFrameTime = currTime;
|
||||
} else {
|
||||
uint32 millisDiff = currTime - _lastFrameTime;
|
||||
if (millisDiff < _millisBetweenFrames) {
|
||||
debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::Player: Delaying %d (currTime=%d, _lastFrameTime=%d, millisDiff=%d, _millisBetweenFrame=%d)",
|
||||
_millisBetweenFrames - millisDiff, currTime, _lastFrameTime, millisDiff, _millisBetweenFrames);
|
||||
_syst->delayMillis(_millisBetweenFrames - millisDiff);
|
||||
currTime = _syst->getMillis();
|
||||
debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::Player: Finished delay at %d", currTime);
|
||||
}
|
||||
debugC(6, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::Player: Frame displayed at %d (%f FPS)", currTime, 1000.0 / (currTime - _lastFrameTime));
|
||||
_lastFrameTime = currTime;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of Groovie namespace
|
68
engines/groovie/player.h
Normal file
68
engines/groovie/player.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_PLAYER_H
|
||||
#define GROOVIE_PLAYER_H
|
||||
|
||||
#include "common/system.h"
|
||||
#include "sound/audiostream.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class GroovieEngine;
|
||||
|
||||
class VideoPlayer {
|
||||
public:
|
||||
VideoPlayer(GroovieEngine *vm);
|
||||
virtual ~VideoPlayer() {}
|
||||
|
||||
bool load(Common::SeekableReadStream *file, uint16 flags);
|
||||
bool playFrame();
|
||||
virtual void setOrigin(int16 x, int16 y) {};
|
||||
|
||||
protected:
|
||||
// To be implemented by subclasses
|
||||
virtual uint16 loadInternal() = 0;
|
||||
virtual bool playFrameInternal() = 0;
|
||||
|
||||
GroovieEngine *_vm;
|
||||
OSystem *_syst;
|
||||
Common::SeekableReadStream *_file;
|
||||
uint16 _flags;
|
||||
Audio::AppendableAudioStream *_audioStream;
|
||||
|
||||
private:
|
||||
// Synchronization stuff
|
||||
bool _begunPlaying;
|
||||
uint16 _millisBetweenFrames;
|
||||
uint32 _lastFrameTime;
|
||||
|
||||
protected:
|
||||
void waitFrame();
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_PLAYER_H
|
240
engines/groovie/resource.cpp
Normal file
240
engines/groovie/resource.cpp
Normal file
|
@ -0,0 +1,240 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/groovie.h"
|
||||
#include "groovie/resource.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
// ResMan
|
||||
|
||||
Common::SeekableReadStream *ResMan::open(uint16 fileRef) {
|
||||
// Get the information about the resource
|
||||
ResInfo resInfo;
|
||||
if (!getResInfo(fileRef, resInfo)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Do we know the name of the required GJD?
|
||||
if (resInfo.gjd >= _gjds.size()) {
|
||||
error("Groovie::Resource: Unknown GJD %d", resInfo.gjd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
debugC(1, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Opening resource 0x%04X (%s, %d, %d)", fileRef, _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size);
|
||||
|
||||
// Does it exist?
|
||||
if (!Common::File::exists(_gjds[resInfo.gjd])) {
|
||||
error("Groovie::Resource: %s not found", _gjds[resInfo.gjd].c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Open the pack file
|
||||
Common::File *gjdFile = new Common::File();
|
||||
if (!gjdFile->open(_gjds[resInfo.gjd].c_str())) {
|
||||
delete gjdFile;
|
||||
error("Groovie::Resource: Couldn't open %s", _gjds[resInfo.gjd].c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Save the used gjd file (except xmi and gamwav)
|
||||
if (resInfo.gjd < 19) {
|
||||
_lastGjd = resInfo.gjd;
|
||||
}
|
||||
|
||||
// Returning the resource substream
|
||||
return new Common::SeekableSubReadStream(gjdFile, resInfo.offset, resInfo.offset + resInfo.size, true);
|
||||
}
|
||||
|
||||
|
||||
// ResMan_t7g
|
||||
|
||||
static const char t7g_gjds[][0x15] = {"at", "b", "ch", "d", "dr", "fh", "ga", "hdisk", "htbd", "intro", "jhek", "k", "la", "li", "mb", "mc", "mu", "n", "p", "xmi", "gamwav"};
|
||||
|
||||
ResMan_t7g::ResMan_t7g() {
|
||||
for (int i = 0; i < 0x15; i++) {
|
||||
// Prepare the filename
|
||||
Common::String filename = t7g_gjds[i];
|
||||
filename += ".gjd";
|
||||
|
||||
// Append it to the list of GJD files
|
||||
_gjds.push_back(filename);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 ResMan_t7g::getRef(Common::String name, Common::String scriptname) {
|
||||
// Get the name of the RL file
|
||||
Common::String rlFileName(t7g_gjds[_lastGjd]);
|
||||
rlFileName += ".rl";
|
||||
|
||||
// Open the RL file
|
||||
Common::File rlFile;
|
||||
if (!rlFile.open(rlFileName)) {
|
||||
error("Groovie::Resource: Couldn't open %s", rlFileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 resNum;
|
||||
bool found = false;
|
||||
for (resNum = 0; !found && !rlFile.ioFailed(); resNum++) {
|
||||
// Read the resource name
|
||||
char readname[12];
|
||||
rlFile.read(readname, 12);
|
||||
|
||||
// Test whether it's the resource we're searching
|
||||
Common::String resname(readname, 12);
|
||||
if (resname.hasPrefix(name.c_str())) {
|
||||
debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource %12s matches %s", readname, name.c_str());
|
||||
found = true;
|
||||
}
|
||||
|
||||
// Skip the rest of resource information
|
||||
rlFile.read(readname, 8);
|
||||
}
|
||||
|
||||
// Close the RL file
|
||||
rlFile.close();
|
||||
|
||||
// Verify we really found the resource
|
||||
if (!found) {
|
||||
error("Groovie::Resource: Couldn't find resource %s in %s", name.c_str(), rlFileName.c_str());
|
||||
return (uint16)-1;
|
||||
}
|
||||
|
||||
return (_lastGjd << 10) | (resNum - 1);
|
||||
}
|
||||
|
||||
bool ResMan_t7g::getResInfo(uint16 fileRef, ResInfo &resInfo) {
|
||||
// Calculate the GJD and the resource number
|
||||
resInfo.gjd = fileRef >> 10;
|
||||
uint16 resNum = fileRef & 0x3FF;
|
||||
|
||||
// Get the name of the RL file
|
||||
Common::String rlFileName(t7g_gjds[resInfo.gjd]);
|
||||
rlFileName += ".rl";
|
||||
|
||||
// Open the RL file
|
||||
Common::File rlFile;
|
||||
if (!rlFile.open(rlFileName)) {
|
||||
error("Groovie::Resource: Couldn't open %s", rlFileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Seek to the position of the desired resource
|
||||
rlFile.seek(resNum * 20);
|
||||
if (rlFile.eos()) {
|
||||
rlFile.close();
|
||||
error("Groovie::Resource: Invalid resource number: 0x%04X (%s)", resNum, rlFileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the resource name (just for debugging purposes)
|
||||
char resname[12];
|
||||
rlFile.read(resname, 12);
|
||||
debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %12s", resname);
|
||||
|
||||
// Read the resource information
|
||||
resInfo.offset = rlFile.readUint32LE();
|
||||
resInfo.size = rlFile.readUint32LE();
|
||||
|
||||
// Close the resource RL file
|
||||
rlFile.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ResMan_v2
|
||||
|
||||
ResMan_v2::ResMan_v2() {
|
||||
Common::File indexfile;
|
||||
|
||||
// Open the GJD index file
|
||||
if (!indexfile.open("gjd.gjd")) {
|
||||
error("Groovie::Resource: Couldn't open gjd.gjd");
|
||||
return;
|
||||
}
|
||||
|
||||
Common::String line = indexfile.readLine();
|
||||
while (!indexfile.eos() && !line.empty()) {
|
||||
// Get the name before the space
|
||||
Common::String filename;
|
||||
for (const char *cur = line.c_str(); *cur != ' '; cur++) {
|
||||
filename += *cur;
|
||||
}
|
||||
|
||||
// Append it to the list of GJD files
|
||||
if (!filename.empty()) {
|
||||
_gjds.push_back(filename);
|
||||
}
|
||||
|
||||
// Read the next line
|
||||
line = indexfile.readLine();
|
||||
}
|
||||
|
||||
// Close the GJD index file
|
||||
indexfile.close();
|
||||
}
|
||||
|
||||
uint16 ResMan_v2::getRef(Common::String name, Common::String scriptname) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ResMan_v2::getResInfo(uint16 fileRef, ResInfo &resInfo) {
|
||||
// Open the RL file
|
||||
Common::File rlFile;
|
||||
if (!rlFile.open("dir.rl")) {
|
||||
error("Groovie::Resource: Couldn't open dir.rl");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Seek to the position of the desired resource
|
||||
rlFile.seek(fileRef * 32);
|
||||
if (rlFile.eos()) {
|
||||
rlFile.close();
|
||||
error("Groovie::Resource: Invalid resource number: 0x%04X", fileRef);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the resource information
|
||||
rlFile.readUint32LE(); // Unknown
|
||||
resInfo.offset = rlFile.readUint32LE();
|
||||
resInfo.size = rlFile.readUint32LE();
|
||||
resInfo.gjd = rlFile.readUint16LE();
|
||||
|
||||
// Read the resource name (just for debugging purposes)
|
||||
char resname[12];
|
||||
rlFile.read(resname, 12);
|
||||
debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %12s", resname);
|
||||
|
||||
// 6 padding bytes? (it looks like they're always 0)
|
||||
|
||||
// Close the resource RL file
|
||||
rlFile.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of Groovie namespace
|
71
engines/groovie/resource.h
Normal file
71
engines/groovie/resource.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_RESOURCE_H
|
||||
#define GROOVIE_RESOURCE_H
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
struct ResInfo {
|
||||
uint16 gjd;
|
||||
uint32 offset;
|
||||
uint32 size;
|
||||
};
|
||||
|
||||
class ResMan {
|
||||
public:
|
||||
virtual ~ResMan() {};
|
||||
|
||||
Common::SeekableReadStream *open(uint16 fileRef);
|
||||
virtual uint16 getRef(Common::String name, Common::String scriptname = "") = 0;
|
||||
|
||||
protected:
|
||||
Common::Array<Common::String> _gjds;
|
||||
virtual bool getResInfo(uint16 fileRef, ResInfo &resInfo) = 0;
|
||||
|
||||
uint16 _lastGjd;
|
||||
};
|
||||
|
||||
class ResMan_t7g : public ResMan {
|
||||
public:
|
||||
ResMan_t7g();
|
||||
~ResMan_t7g() {};
|
||||
|
||||
uint16 getRef(Common::String name, Common::String scriptname);
|
||||
bool getResInfo(uint16 fileRef, ResInfo &resInfo);
|
||||
};
|
||||
|
||||
class ResMan_v2 : public ResMan {
|
||||
public:
|
||||
ResMan_v2();
|
||||
~ResMan_v2() {};
|
||||
|
||||
uint16 getRef(Common::String name, Common::String scriptname);
|
||||
bool getResInfo(uint16 fileRef, ResInfo &resInfo);
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_RESOURCE_H
|
403
engines/groovie/roq.cpp
Normal file
403
engines/groovie/roq.cpp
Normal file
|
@ -0,0 +1,403 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/groovie.h"
|
||||
#include "groovie/roq.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
ROQPlayer::ROQPlayer(GroovieEngine *vm) :
|
||||
VideoPlayer(vm) {
|
||||
}
|
||||
|
||||
ROQPlayer::~ROQPlayer() {
|
||||
}
|
||||
|
||||
uint16 ROQPlayer::loadInternal() {
|
||||
// Begin reading the file
|
||||
debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Loading video");
|
||||
|
||||
// Read the file header
|
||||
ROQBlockHeader blockHeader;
|
||||
if (!readBlockHeader(blockHeader)) {
|
||||
return 0;
|
||||
}
|
||||
if (blockHeader.type != 0x1084 || blockHeader.size != 0 || blockHeader.param != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Hardcoded FPS
|
||||
return 25;
|
||||
}
|
||||
|
||||
bool ROQPlayer::playFrameInternal() {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Playing frame");
|
||||
|
||||
// Process the needed blocks until the next video frame
|
||||
bool endframe = false;
|
||||
while (!endframe && !_file->eos()) {
|
||||
endframe = processBlock();
|
||||
}
|
||||
|
||||
// Wait until the current frame can be shown
|
||||
waitFrame();
|
||||
|
||||
// Update the screen
|
||||
_syst->updateScreen();
|
||||
|
||||
// Return whether the video has ended
|
||||
return _file->eos();
|
||||
}
|
||||
|
||||
bool ROQPlayer::readBlockHeader(ROQBlockHeader &blockHeader) {
|
||||
if (_file->eos()) {
|
||||
return false;
|
||||
} else {
|
||||
blockHeader.type = _file->readUint16LE();
|
||||
blockHeader.size = _file->readUint32LE();
|
||||
blockHeader.param = _file->readUint16LE();
|
||||
|
||||
debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Block type = 0x%02X", blockHeader.type);
|
||||
debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Block size = 0x%08X", blockHeader.size);
|
||||
debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Block param = 0x%04X", blockHeader.param);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ROQPlayer::processBlock() {
|
||||
// Read the header of the block
|
||||
ROQBlockHeader blockHeader;
|
||||
if (!readBlockHeader(blockHeader)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
bool endframe = false;
|
||||
switch (blockHeader.type) {
|
||||
case 0x1001: // Video info
|
||||
ok = processBlockInfo(blockHeader);
|
||||
break;
|
||||
case 0x1002: // Quad codebook definition
|
||||
ok = processBlockQuadCodebook(blockHeader);
|
||||
break;
|
||||
case 0x1011: // Quad vector quantised video frame
|
||||
ok = processBlockQuadVector(blockHeader);
|
||||
endframe = true;
|
||||
break;
|
||||
case 0x1012: // Still image (JPEG)
|
||||
ok = processBlockStill(blockHeader);
|
||||
endframe = true;
|
||||
break;
|
||||
case 0x1013: // Hang
|
||||
//warning("Groovie::ROQ: Hang block (skipped)");
|
||||
break;
|
||||
case 0x1020: // Mono sound samples
|
||||
ok = processBlockSoundMono(blockHeader);
|
||||
break;
|
||||
case 0x1021: // Stereo sound samples
|
||||
ok = processBlockSoundStereo(blockHeader);
|
||||
break;
|
||||
case 0x1030: // Audio container
|
||||
ok = processBlockAudioContainer(blockHeader);
|
||||
break;
|
||||
default:
|
||||
error("Groovie::ROQ: Unknown block type: 0x%04X", blockHeader.type);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
// End the frame when the graphics have been modified or when there's an error
|
||||
return endframe || !ok;
|
||||
}
|
||||
|
||||
bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing info block");
|
||||
|
||||
// Verify the block header
|
||||
if (blockHeader.type != 0x1001 || blockHeader.size != 8 || blockHeader.param != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16 tmp;
|
||||
tmp = _file->readUint16LE();
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "w = %d\n", tmp);
|
||||
if (tmp != 640) {
|
||||
return false;
|
||||
}
|
||||
tmp = _file->readUint16LE();
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "h = %d\n", tmp);
|
||||
if (tmp != 320) {
|
||||
return false;
|
||||
}
|
||||
tmp = _file->readUint16LE();
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "unk1 = %d\n", tmp);
|
||||
if (tmp != 8) {
|
||||
return false;
|
||||
}
|
||||
tmp = _file->readUint16LE();
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "unk2 = %d\n", tmp);
|
||||
if (tmp != 4) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ROQPlayer::processBlockQuadCodebook(ROQBlockHeader &blockHeader) {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad codebook block");
|
||||
|
||||
// Get the number of 2x2 pixel blocks
|
||||
_num2blocks = blockHeader.param >> 8;
|
||||
if (_num2blocks == 0) {
|
||||
_num2blocks = 256;
|
||||
}
|
||||
|
||||
// Get the number of 4x4 pixel blocks
|
||||
_num4blocks = blockHeader.param & 0xFF;
|
||||
if (_num4blocks == 0 && (blockHeader.size > (uint32)_num2blocks * 6)) {
|
||||
_num4blocks = 256;
|
||||
}
|
||||
|
||||
_file->skip(_num2blocks * 6);
|
||||
_file->skip(_num4blocks * 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ROQPlayer::processBlockQuadVector(ROQBlockHeader &blockHeader) {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad vector block");
|
||||
_file->skip(blockHeader.size);
|
||||
return true;
|
||||
|
||||
// Get the mean motion vectors
|
||||
//byte Mx = blockHeader.param >> 8;
|
||||
//byte My = blockHeader.param & 0xFF;
|
||||
|
||||
int32 ends =_file->pos() + blockHeader.size;
|
||||
int numblocks = (640 / 8) * (320 / 8);
|
||||
for (int j = 0; j < numblocks && ends > _file->pos(); j++) {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "doing block %d/%d\n", j, numblocks);
|
||||
uint16 codingType = _file->readUint16LE();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
switch (codingType >> 14) {
|
||||
case 0: // MOT: Skip block
|
||||
//printf("coding type 0\n");
|
||||
break;
|
||||
case 1: { // FCC: Copy an existing block
|
||||
//printf("coding type 1\n");
|
||||
byte argument;
|
||||
argument = _file->readByte();
|
||||
//byte Dx = Mx + (argument >> 4);
|
||||
//byte Dy = My + (argument & 0x0F);
|
||||
// Dx = X + 8 - (argument >> 4) - Mx
|
||||
// Dy = Y + 8 - (argument & 0x0F) - My
|
||||
break;
|
||||
}
|
||||
case 2: { // SLD: Quad vector quantisation
|
||||
//printf("coding type 2\n");
|
||||
byte argument = _file->readByte();
|
||||
if (argument > _num4blocks) {
|
||||
//error("invalid 4x4 block %d of %d", argument, _num4blocks);
|
||||
}
|
||||
// Upsample the 4x4 pixel block
|
||||
break;
|
||||
}
|
||||
case 3: // CCC:
|
||||
//printf("coding type 3:\n");
|
||||
processBlockQuadVectorSub(blockHeader);
|
||||
break;
|
||||
}
|
||||
codingType <<= 2;
|
||||
}
|
||||
}
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Should have ended at %d, and has ended at %d\n", ends, _file->pos());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ROQPlayer::processBlockQuadVectorSub(ROQBlockHeader &blockHeader) {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad vector sub block");
|
||||
|
||||
// Get the mean motion vectors
|
||||
//byte Mx = blockHeader.param >> 8;
|
||||
//byte My = blockHeader.param & 0xFF;
|
||||
|
||||
uint16 codingType = _file->readUint16LE();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
switch (codingType >> 14) {
|
||||
case 0: // MOT: Skip block
|
||||
//printf("coding type 0\n");
|
||||
break;
|
||||
case 1: { // FCC: Copy an existing block
|
||||
//printf("coding type 1\n");
|
||||
byte argument;
|
||||
argument = _file->readByte();
|
||||
//byte Dx = Mx + (argument >> 4);
|
||||
//byte Dy = My + (argument & 0x0F);
|
||||
// Dx = X + 8 - (argument >> 4) - Mx
|
||||
// Dy = Y + 8 - (argument & 0x0F) - My
|
||||
break;
|
||||
}
|
||||
case 2: { // SLD: Quad vector quantisation
|
||||
//printf("coding type 2\n");
|
||||
byte argument = _file->readByte();
|
||||
if (argument > _num2blocks) {
|
||||
//error("invalid 2x2 block: %d of %d", argument, _num2blocks);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
//printf("coding type 3\n");
|
||||
_file->readByte();
|
||||
_file->readByte();
|
||||
_file->readByte();
|
||||
_file->readByte();
|
||||
break;
|
||||
}
|
||||
codingType <<= 2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing still (JPEG) block");
|
||||
//Common::ReadStream *jpegData = new Common::SubReadStream(_file, blockHeader.size);
|
||||
//Graphics::JPEG jpegFrame;
|
||||
//jpegFrame.read(jpegData);
|
||||
/*
|
||||
Common::File save;
|
||||
save.open("dump.jpg", Common::File::kFileWriteMode);
|
||||
save.write(data, blockHeader.size);
|
||||
save.close();
|
||||
*/
|
||||
error("JPEG!");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ROQPlayer::processBlockSoundMono(ROQBlockHeader &blockHeader) {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing mono sound block");
|
||||
|
||||
// Verify the block header
|
||||
if (blockHeader.type != 0x1020) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the audio stream if needed
|
||||
if (!_audioStream) {
|
||||
byte flags = Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_AUTOFREE;
|
||||
#ifdef SCUMM_LITTLE_ENDIAN
|
||||
flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
|
||||
#endif
|
||||
_audioStream = Audio::makeAppendableAudioStream(22050, flags);
|
||||
Audio::SoundHandle sound_handle;
|
||||
::g_engine->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &sound_handle, _audioStream);
|
||||
}
|
||||
|
||||
// Create the audio buffer
|
||||
int16 *buffer = new int16[blockHeader.size];
|
||||
|
||||
// Initialize the prediction with the block parameter
|
||||
int16 prediction = blockHeader.param ^ 0x8000;
|
||||
|
||||
// Process the data
|
||||
for (uint16 i = 0; i < blockHeader.size; i++) {
|
||||
int16 data = _file->readByte();
|
||||
if (data < 0x80) {
|
||||
prediction += data * data;
|
||||
} else {
|
||||
data -= 0x80;
|
||||
prediction -= data * data;
|
||||
}
|
||||
buffer[i] = prediction;
|
||||
}
|
||||
|
||||
// Queue the read buffer
|
||||
_audioStream->queueBuffer((byte *)buffer, blockHeader.size * 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ROQPlayer::processBlockSoundStereo(ROQBlockHeader &blockHeader) {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing stereo sound block");
|
||||
|
||||
// Verify the block header
|
||||
if (blockHeader.type != 0x1021) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the audio stream if needed
|
||||
if (!_audioStream) {
|
||||
byte flags = Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_STEREO;
|
||||
#ifdef SCUMM_LITTLE_ENDIAN
|
||||
flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
|
||||
#endif
|
||||
_audioStream = Audio::makeAppendableAudioStream(22050, flags);
|
||||
Audio::SoundHandle sound_handle;
|
||||
::g_engine->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &sound_handle, _audioStream);
|
||||
}
|
||||
|
||||
// Create the audio buffer
|
||||
int16 *buffer = new int16[blockHeader.size];
|
||||
|
||||
// Initialize the prediction with the block parameter
|
||||
int16 predictionLeft = (blockHeader.param & 0xFF00) ^ 0x8000;
|
||||
int16 predictionRight = (blockHeader.param << 8) ^ 0x8000;
|
||||
bool left = true;
|
||||
|
||||
// Process the data
|
||||
for (uint16 i = 0; i < blockHeader.size; i++) {
|
||||
int16 data = _file->readByte();
|
||||
if (left) {
|
||||
if (data < 0x80) {
|
||||
predictionLeft += data * data;
|
||||
} else {
|
||||
data -= 0x80;
|
||||
predictionLeft -= data * data;
|
||||
}
|
||||
buffer[i] = predictionLeft;
|
||||
} else {
|
||||
if (data < 0x80) {
|
||||
predictionRight += data * data;
|
||||
} else {
|
||||
data -= 0x80;
|
||||
predictionRight -= data * data;
|
||||
}
|
||||
buffer[i] = predictionRight;
|
||||
}
|
||||
left = !left;
|
||||
}
|
||||
|
||||
// Queue the read buffer
|
||||
_audioStream->queueBuffer((byte *)buffer, blockHeader.size * 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ROQPlayer::processBlockAudioContainer(ROQBlockHeader &blockHeader) {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing audio container block: 0x%04X", blockHeader.param);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of Groovie namespace
|
69
engines/groovie/roq.h
Normal file
69
engines/groovie/roq.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_ROQ_H
|
||||
#define GROOVIE_ROQ_H
|
||||
|
||||
#include "groovie/player.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class GroovieEngine;
|
||||
|
||||
struct ROQBlockHeader {
|
||||
uint16 type;
|
||||
uint32 size;
|
||||
uint16 param;
|
||||
};
|
||||
|
||||
class ROQPlayer : public VideoPlayer {
|
||||
public:
|
||||
ROQPlayer(GroovieEngine *vm);
|
||||
~ROQPlayer();
|
||||
|
||||
protected:
|
||||
uint16 loadInternal();
|
||||
bool playFrameInternal();
|
||||
|
||||
private:
|
||||
bool readBlockHeader(ROQBlockHeader &blockHeader);
|
||||
|
||||
bool processBlock();
|
||||
bool processBlockInfo(ROQBlockHeader &blockHeader);
|
||||
bool processBlockQuadCodebook(ROQBlockHeader &blockHeader);
|
||||
bool processBlockQuadVector(ROQBlockHeader &blockHeader);
|
||||
bool processBlockQuadVectorSub(ROQBlockHeader &blockHeader);
|
||||
bool processBlockStill(ROQBlockHeader &blockHeader);
|
||||
bool processBlockSoundMono(ROQBlockHeader &blockHeader);
|
||||
bool processBlockSoundStereo(ROQBlockHeader &blockHeader);
|
||||
bool processBlockAudioContainer(ROQBlockHeader &blockHeader);
|
||||
|
||||
uint16 _num2blocks;
|
||||
uint16 _num4blocks;
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_ROQ_H
|
1566
engines/groovie/script.cpp
Normal file
1566
engines/groovie/script.cpp
Normal file
File diff suppressed because it is too large
Load diff
211
engines/groovie/script.h
Normal file
211
engines/groovie/script.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_SCRIPT_H
|
||||
#define GROOVIE_SCRIPT_H
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
#include "groovie/font.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class GroovieEngine;
|
||||
|
||||
class Script {
|
||||
friend class Debugger;
|
||||
|
||||
public:
|
||||
Script(GroovieEngine *vm);
|
||||
~Script();
|
||||
|
||||
void setDebugger(Debugger *debugger);
|
||||
|
||||
bool loadScript(Common::String scriptfile);
|
||||
void directGameLoad(int slot);
|
||||
void step();
|
||||
|
||||
void setMouseClick();
|
||||
void setKbdChar(uint8 c);
|
||||
|
||||
bool haveError();
|
||||
|
||||
private:
|
||||
GroovieEngine *_vm;
|
||||
|
||||
Common::RandomSource _random;
|
||||
|
||||
bool _firstbit;
|
||||
|
||||
// Script filename (for debugging purposes)
|
||||
Common::String _scriptFile;
|
||||
Common::String _savedScriptFile;
|
||||
|
||||
// Code
|
||||
byte *_code;
|
||||
uint16 _currentInstruction;
|
||||
byte *_savedCode;
|
||||
uint16 _savedInstruction;
|
||||
|
||||
// Variables
|
||||
byte _variables[0x400];
|
||||
byte _savedVariables[0x180];
|
||||
|
||||
// Stack
|
||||
uint16 _stack[0x20];
|
||||
uint8 _stacktop;
|
||||
uint8 _savedStacktop;
|
||||
|
||||
// Input
|
||||
bool _mouseClicked;
|
||||
bool _eventMouseClicked;
|
||||
uint8 _kbdChar;
|
||||
uint8 _eventKbdChar;
|
||||
uint16 _inputLoopAddress;
|
||||
int16 _inputAction;
|
||||
uint8 _newCursorStyle;
|
||||
uint16 _hotspotTopAction;
|
||||
uint16 _hotspotTopCursor;
|
||||
uint16 _hotspotBottomAction;
|
||||
uint16 _hotspotBottomCursor;
|
||||
uint16 _hotspotRightAction;
|
||||
uint16 _hotspotLeftAction;
|
||||
uint16 _hotspotCursorOldX;
|
||||
uint16 _hotspotCursorOldY;
|
||||
|
||||
// Video
|
||||
Font *_font;
|
||||
Common::SeekableReadStream *_videoFile;
|
||||
uint16 _videoRef;
|
||||
uint16 _bitflags;
|
||||
|
||||
// Debugging
|
||||
Debugger *_debugger;
|
||||
Common::String _debugString;
|
||||
void error(const char *msg);
|
||||
bool _error;
|
||||
|
||||
// Helper functions
|
||||
uint8 readScript8bits();
|
||||
uint16 readScript16bits();
|
||||
uint32 readScript32bits();
|
||||
uint16 readScript8or16bits();
|
||||
uint8 readScriptChar(bool allow7C, bool limitVal, bool limitVar);
|
||||
uint8 readScriptVar();
|
||||
uint16 getVideoRefString();
|
||||
|
||||
bool hotspot(Common::Rect rect, uint16 addr, uint8 cursor);
|
||||
|
||||
void loadgame(uint slot);
|
||||
void savegame(uint slot);
|
||||
bool playvideofromref(uint16 fileref);
|
||||
|
||||
// Opcodes
|
||||
typedef void (Script::*OpcodeFunc)();
|
||||
static OpcodeFunc _opcodes[];
|
||||
|
||||
void o_invalid();
|
||||
|
||||
void o_nop();
|
||||
void o_nop8();
|
||||
void o_nop16();
|
||||
void o_nop32();
|
||||
void o_nop8or16();
|
||||
|
||||
void o_playsong();
|
||||
void o_bf9on();
|
||||
void o_palfadeout();
|
||||
void o_bf8on();
|
||||
void o_bf6on();
|
||||
void o_bf7on();
|
||||
void o_setbackgroundsong();
|
||||
void o_videofromref();
|
||||
void o_bf5on();
|
||||
void o_inputloopstart();
|
||||
void o_keyboardaction();
|
||||
void o_hotspot_rect();
|
||||
void o_hotspot_left();
|
||||
void o_hotspot_right();
|
||||
void o_hotspot_center();
|
||||
void o_hotspot_current();
|
||||
void o_inputloopend();
|
||||
void o_random();
|
||||
void o_jmp();
|
||||
void o_loadstring();
|
||||
void o_ret();
|
||||
void o_call();
|
||||
void o_sleep();
|
||||
void o_strcmpnejmp_var();
|
||||
void o_copybgtofg();
|
||||
void o_strcmpnejmp();
|
||||
void o_xor_obfuscate();
|
||||
void o_vdxtransition();
|
||||
void o_swap();
|
||||
void o_inc();
|
||||
void o_dec();
|
||||
void o_strcmpeqjmp();
|
||||
void o_mov();
|
||||
void o_add();
|
||||
void o_videofromstring1();
|
||||
void o_videofromstring2();
|
||||
void o_stopmidi();
|
||||
void o_endscript();
|
||||
void o_sethotspottop();
|
||||
void o_sethotspotbottom();
|
||||
void o_loadgame();
|
||||
void o_savegame();
|
||||
void o_hotspotbottom_4();
|
||||
void o_midivolume();
|
||||
void o_jne();
|
||||
void o_loadstringvar();
|
||||
void o_chargreatjmp();
|
||||
void o_bf7off();
|
||||
void o_charlessjmp();
|
||||
void o_copyrecttobg();
|
||||
void o_restorestkpnt();
|
||||
void o_obscureswap();
|
||||
void o_printstring();
|
||||
void o_hotspot_slot();
|
||||
void o_checkvalidsaves();
|
||||
void o_resetvars();
|
||||
void o_mod();
|
||||
void o_loadscript();
|
||||
void o_setvideoorigin();
|
||||
void o_sub();
|
||||
void o_othello();
|
||||
void o_returnscript();
|
||||
void o_sethotspotright();
|
||||
void o_sethotspotleft();
|
||||
void o_getcd();
|
||||
void o_opcode4D();
|
||||
void o_hotspot_outrect();
|
||||
void o_stub56();
|
||||
void o_stub59();
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_SCRIPT_H
|
522
engines/groovie/vdx.cpp
Normal file
522
engines/groovie/vdx.cpp
Normal file
|
@ -0,0 +1,522 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/groovie.h"
|
||||
#include "groovie/lzss.h"
|
||||
#include "groovie/vdx.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#define TILE_SIZE 4 // Size of each tile on the image: only ever seen 4 so far
|
||||
#define VDX_IDENT 0x9267 // 37479
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
VDXPlayer::VDXPlayer(GroovieEngine *vm) :
|
||||
VideoPlayer(vm), _origX(0), _origY(0), _flagOnePrev(false),
|
||||
_fg(&_vm->_graphicsMan->_foreground), _bg(&_vm->_graphicsMan->_background) {
|
||||
}
|
||||
|
||||
VDXPlayer::~VDXPlayer() {
|
||||
//delete _audioStream;
|
||||
}
|
||||
|
||||
void VDXPlayer::setOrigin(int16 x, int16 y) {
|
||||
_origX = x;
|
||||
_origY = y;
|
||||
}
|
||||
|
||||
uint16 VDXPlayer::loadInternal() {
|
||||
uint32 engine_level = kGroovieDebugVideo | kGroovieDebugAll;
|
||||
if ((gDebugLevel == 11) || (Common::getEnabledSpecialDebugLevels() & engine_level)) {
|
||||
int8 i;
|
||||
debugN(1, "Groovie::VDX: New VDX: bitflags are ");
|
||||
for (i = 11; i >= 0; i--) {
|
||||
debugN(1, "%d", _flags & (1 << i)? 1 : 0);
|
||||
if (i % 4 == 0) {
|
||||
debugN(1, " ");
|
||||
}
|
||||
}
|
||||
debug(1, " ");
|
||||
}
|
||||
// Flags:
|
||||
// - 1 Puzzle piece? Skip palette, don't redraw full screen, draw still to b/ack buffer
|
||||
// - 2 Transparent colour is 0xFF
|
||||
// - 5 Skip still chunks
|
||||
// - 7
|
||||
// - 8 Just show the first frame
|
||||
// - 9 Start a palette fade in
|
||||
_flagZero = ((_flags & (1 << 0)) != 0);
|
||||
_flagOne = ((_flags & (1 << 1)) != 0);
|
||||
_flag2Byte = (_flags & (1 << 2)) ? 0xFF : 0x00;
|
||||
_flagThree = ((_flags & (1 << 3)) != 0);
|
||||
_flagFour = ((_flags & (1 << 4)) != 0);
|
||||
_flagFive = ((_flags & (1 << 5)) != 0);
|
||||
_flagSix = ((_flags & (1 << 6)) != 0);
|
||||
_flagSeven = ((_flags & (1 << 7)) != 0);
|
||||
_flagEight = ((_flags & (1 << 8)) != 0);
|
||||
_flagNine = ((_flags & (1 << 9)) != 0);
|
||||
|
||||
if (_flagOnePrev && !_flagOne && !_flagEight) {
|
||||
_flagSeven = true;
|
||||
}
|
||||
|
||||
// Save _flagOne for the next video
|
||||
_flagOnePrev = _flagOne;
|
||||
|
||||
//_flagTransparent = _flagOne;
|
||||
_flagFirstFrame = _flagEight;
|
||||
//_flagSkipPalette = _flagSeven;
|
||||
_flagSkipPalette = false;
|
||||
//_flagSkipStill = _flagFive || _flagSeven;
|
||||
//_flagUpdateStill = _flagNine || _flagSix;
|
||||
|
||||
// Begin reading the file
|
||||
debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Playing video");
|
||||
|
||||
if (_file->readUint16LE() != VDX_IDENT) {
|
||||
error("Groovie::VDX: This does not appear to be a 7th guest vxd file");
|
||||
return 0;
|
||||
} else {
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: VDX file identified correctly");
|
||||
}
|
||||
|
||||
uint16 tmp;
|
||||
|
||||
// Skip unknown data: 6 bytes, ref Martine
|
||||
tmp = _file->readUint16LE();
|
||||
debugC(2, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Martine1 = 0x%04X", tmp);
|
||||
tmp = _file->readUint16LE();
|
||||
debugC(2, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Martine2 = 0x%04X", tmp);
|
||||
tmp = _file->readUint16LE();
|
||||
debugC(2, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Martine3 (FPS?) = %d", tmp);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool VDXPlayer::playFrameInternal() {
|
||||
byte currRes = 0x80;
|
||||
while (!_file->eos() && currRes == 0x80) {
|
||||
currRes = _file->readByte();
|
||||
|
||||
// Skip unknown data: 1 byte, ref Edward
|
||||
byte tmp = _file->readByte();
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Edward = 0x%04X", tmp);
|
||||
|
||||
uint32 compSize = _file->readUint32LE();
|
||||
uint8 lengthmask = _file->readByte();
|
||||
uint8 lengthbits = _file->readByte();
|
||||
|
||||
// Read the chunk data and decompress if needed
|
||||
Common::ReadStream *vdxData = new Common::SubReadStream(_file, compSize);
|
||||
if (lengthmask && lengthbits) {
|
||||
Common::ReadStream *decompData = new LzssReadStream(vdxData, lengthmask, lengthbits);
|
||||
delete vdxData;
|
||||
vdxData = decompData;
|
||||
}
|
||||
|
||||
// Use the current chunk
|
||||
switch (currRes) {
|
||||
case 0x00:
|
||||
debugC(6, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Replay frame");
|
||||
break;
|
||||
case 0x20:
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Still frame");
|
||||
getStill(vdxData);
|
||||
break;
|
||||
case 0x25:
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Animation frame");
|
||||
getDelta(vdxData);
|
||||
break;
|
||||
case 0x80:
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Sound resource");
|
||||
chunkSound(vdxData);
|
||||
break;
|
||||
default:
|
||||
error("Groovie::VDX: Invalid resource type: %d", currRes);
|
||||
}
|
||||
delete vdxData;
|
||||
}
|
||||
|
||||
// Wait until the current frame can be shown
|
||||
waitFrame();
|
||||
|
||||
// TODO: Move it to a better place
|
||||
// Update the screen
|
||||
if (currRes == 0x25) {
|
||||
//if (_flagSeven) {
|
||||
//_vm->_graphicsMan->mergeFgAndBg();
|
||||
//}
|
||||
_vm->_graphicsMan->updateScreen(_bg);
|
||||
}
|
||||
|
||||
// Report the end of the video if we reached the end of the file or if we
|
||||
// just wanted to play one frame.
|
||||
return _file->eos() || _flagFirstFrame;
|
||||
}
|
||||
|
||||
static const uint16 vdxBlockMapLookup[] = {
|
||||
0xc800, 0xec80, 0xfec8, 0xffec, 0xfffe, 0x3100, 0x7310, 0xf731, 0xff73, 0xfff7, 0x6c80, 0x36c8, 0x136c, 0x6310, 0xc631, 0x8c63,
|
||||
0xf000, 0xff00, 0xfff0, 0x1111, 0x3333, 0x7777, 0x6666, 0xcccc, 0x0ff0, 0x00ff, 0xffcc, 0x0076, 0xff33, 0x0ee6, 0xccff, 0x6770,
|
||||
0x33ff, 0x6ee0, 0x4800, 0x2480, 0x1248, 0x0024, 0x0012, 0x2100, 0x4210, 0x8421, 0x0042, 0x0084, 0xf888, 0x0044, 0x0032, 0x111f,
|
||||
0x22e0, 0x4c00, 0x888f, 0x4470, 0x2300, 0xf111, 0x0e22, 0x00c4, 0xf33f, 0xfccf, 0xff99, 0x99ff, 0x4444, 0x2222, 0xccee, 0x7733,
|
||||
0x00f8, 0x00f1, 0x00bb, 0x0cdd, 0x0f0f, 0x0f88, 0x13f1, 0x19b3, 0x1f80, 0x226f, 0x27ec, 0x3077, 0x3267, 0x37e4, 0x38e3, 0x3f90,
|
||||
0x44cf, 0x4cd9, 0x4c99, 0x5555, 0x603f, 0x6077, 0x6237, 0x64c9, 0x64cd, 0x6cd9, 0x70ef, 0x0f00, 0x00f0, 0x0000, 0x4444, 0x2222
|
||||
};
|
||||
|
||||
void VDXPlayer::getDelta(Common::ReadStream *in) {
|
||||
uint16 j, k, l;
|
||||
uint32 offset;
|
||||
uint8 currOpCode, param1, param2, param3;
|
||||
|
||||
// Get the size of the local palette
|
||||
j = in->readUint16LE();
|
||||
|
||||
// Load the palette if it isn't empty
|
||||
if (j) {
|
||||
uint16 palBitField[16];
|
||||
int flag = 1, palIndex;
|
||||
|
||||
// Load the bit field
|
||||
for (l = 0; l < 16; l++) {
|
||||
palBitField[l] = in->readUint16LE();
|
||||
}
|
||||
|
||||
// Load the actual palette
|
||||
for (l = 0; l < 16; l++) {
|
||||
flag = 1 << 15;
|
||||
for (j = 0; j < 16; j++) {
|
||||
palIndex = (l * 16) + j;
|
||||
|
||||
if (flag & palBitField[l]) {
|
||||
for (k = 0; k < 3; k++) {
|
||||
_palBuf[(palIndex * 3) + k] = in->readByte();
|
||||
}
|
||||
}
|
||||
flag = flag >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the palette
|
||||
if (!_flagSix && !_flagSeven) {
|
||||
setPalette(_palBuf);
|
||||
}
|
||||
}
|
||||
currOpCode = in->readByte();
|
||||
|
||||
/* j now becomes the current block line we're dealing with */
|
||||
j = 0;
|
||||
offset = 0;
|
||||
while (!in->eos()) {
|
||||
byte colours[16];
|
||||
if (currOpCode < 0x60) {
|
||||
param1 = in->readByte();
|
||||
param2 = in->readByte();
|
||||
expandColourMap(colours, vdxBlockMapLookup[currOpCode], param1, param2);
|
||||
decodeBlockDelta(offset, colours, 640);
|
||||
offset += TILE_SIZE;
|
||||
} else if (currOpCode > 0x7f) {
|
||||
param1 = in->readByte();
|
||||
param2 = in->readByte();
|
||||
param3 = in->readByte();
|
||||
expandColourMap(colours, (param1 << 8) + currOpCode, param2, param3);
|
||||
decodeBlockDelta(offset, colours, 640);
|
||||
offset += TILE_SIZE;
|
||||
} else switch (currOpCode) {
|
||||
case 0x60: /* Fill tile with the 16 colours given as parameters */
|
||||
for (l = 0; l < 16; l++) {
|
||||
colours[l] = in->readByte();
|
||||
}
|
||||
decodeBlockDelta(offset, colours, 640);
|
||||
offset += TILE_SIZE;
|
||||
break;
|
||||
case 0x61: /* Skip to the end of this line, next block is start of next */
|
||||
/* Note this is used at the end of EVERY line */
|
||||
j++;
|
||||
offset = j * TILE_SIZE * 640;
|
||||
break;
|
||||
case 0x62:
|
||||
case 0x63:
|
||||
case 0x64:
|
||||
case 0x65:
|
||||
case 0x66:
|
||||
case 0x67:
|
||||
case 0x68:
|
||||
case 0x69:
|
||||
case 0x6a:
|
||||
case 0x6b: /* Skip next param1 blocks (within line) */
|
||||
offset += (currOpCode - 0x62) * TILE_SIZE;
|
||||
break;
|
||||
case 0x6c:
|
||||
case 0x6d:
|
||||
case 0x6e:
|
||||
case 0x6f:
|
||||
case 0x70:
|
||||
case 0x71:
|
||||
case 0x72:
|
||||
case 0x73:
|
||||
case 0x74:
|
||||
case 0x75: /* Next param1 blocks are filled with colour param2 */
|
||||
param1 = currOpCode - 0x6b;
|
||||
param2 = in->readByte();
|
||||
for (l = 0; l < 16; l++) {
|
||||
colours[l] = param2;
|
||||
}
|
||||
for (k = 0; k < param1; k++) {
|
||||
decodeBlockDelta(offset, colours, 640);
|
||||
offset += TILE_SIZE;
|
||||
}
|
||||
break;
|
||||
case 0x76:
|
||||
case 0x77:
|
||||
case 0x78:
|
||||
case 0x79:
|
||||
case 0x7a:
|
||||
case 0x7b:
|
||||
case 0x7c:
|
||||
case 0x7d:
|
||||
case 0x7e:
|
||||
case 0x7f: /* Next bytes contain colours to fill the next param1 blocks in the current line*/
|
||||
param1 = currOpCode - 0x75;
|
||||
for (k = 0; k < param1; k++) {
|
||||
param2 = in->readByte();
|
||||
for (l = 0; l < 16; l++) {
|
||||
colours[l] = param2;
|
||||
}
|
||||
decodeBlockDelta(offset, colours, 640);
|
||||
offset += TILE_SIZE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error("Groovie::VDX: Broken somehow");
|
||||
}
|
||||
currOpCode = in->readByte();
|
||||
}
|
||||
}
|
||||
|
||||
void VDXPlayer::getStill(Common::ReadStream *in) {
|
||||
uint16 numXTiles = in->readUint16LE();
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: numXTiles=%d", numXTiles);
|
||||
uint16 numYTiles = in->readUint16LE();
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: numYTiles=%d", numYTiles);
|
||||
|
||||
// It's skipped in the original:
|
||||
uint16 colourDepth = in->readUint16LE();
|
||||
debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: colourDepth=%d", colourDepth);
|
||||
|
||||
uint16 imageWidth = TILE_SIZE * numXTiles;
|
||||
|
||||
uint8 mask = 0;
|
||||
byte *buf;
|
||||
if (_flagOne) {
|
||||
// Paint to the foreground
|
||||
buf = (byte *)_fg->getBasePtr(0, 0);
|
||||
if (_flag2Byte) {
|
||||
mask = 0xff;
|
||||
} else {
|
||||
mask = 0;
|
||||
}
|
||||
|
||||
// TODO: Verify this is the right procedure. Couldn't find it on the
|
||||
// disassembly, but it's required to work properly
|
||||
_flagFirstFrame = true;
|
||||
} else {
|
||||
// Paint to the background
|
||||
buf = (byte *)_bg->getBasePtr(0, 0);
|
||||
}
|
||||
|
||||
// Read the palette
|
||||
in->read(_palBuf, 3 * 256);
|
||||
|
||||
if (_flagSeven) {
|
||||
_flagFive = true;
|
||||
}
|
||||
|
||||
// Skip the frame when flag 5 is set, unless flag 1 is set
|
||||
if (!_flagFive || _flagOne) {
|
||||
|
||||
byte colours[16];
|
||||
for (uint16 j = 0; j < numYTiles; j++) {
|
||||
for (uint16 i = 0; i < numXTiles; i++) { /* Tile number */
|
||||
uint8 colour1 = in->readByte();
|
||||
uint8 colour0 = in->readByte();
|
||||
uint16 colourMap = in->readUint16LE();
|
||||
expandColourMap(colours, colourMap, colour1, colour0);
|
||||
decodeBlockStill(buf + j * TILE_SIZE * imageWidth + i * TILE_SIZE, colours, 640, mask);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the palette
|
||||
if (_flagNine) {
|
||||
// Flag 9 starts a fade in
|
||||
fadeIn(_palBuf);
|
||||
} else {
|
||||
if (!_flagOne && !_flagSeven) {
|
||||
// Actually apply the palette
|
||||
setPalette(_palBuf);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_flagOne) {
|
||||
_vm->_graphicsMan->updateScreen(_bg);
|
||||
}
|
||||
/*
|
||||
if (_flagSix) {
|
||||
if (_flagOne) {
|
||||
_vm->_graphicsMan->updateScreen(_fg);
|
||||
} else {
|
||||
_vm->_graphicsMan->updateScreen(_bg);
|
||||
}
|
||||
_flagSix = 0;
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
// Skip the remaining data
|
||||
debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Skipping still frame");
|
||||
while (!in->eos()) {
|
||||
in->readByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VDXPlayer::expandColourMap(byte *out, uint16 colourMap, uint8 colour1, uint8 colour0) {
|
||||
int flag = 1 << 15;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
// Set the corresponding colour
|
||||
out[i] = (colourMap & flag) ? colour1 : colour0;
|
||||
|
||||
// Update the flag to test the next colour
|
||||
flag >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void VDXPlayer::decodeBlockStill(byte *buf, byte *colours, uint16 imageWidth, uint8 mask) {
|
||||
for (int y = 0; y < TILE_SIZE; y++) {
|
||||
for (int x = 0; x < TILE_SIZE; x++) {
|
||||
if (_flagOne) {
|
||||
// 0xff pixels don't modify the buffer
|
||||
if (*colours != 0xff) {
|
||||
// Write the colour
|
||||
*buf = *colours | mask;
|
||||
// Note: if the mask is 0, it paints the image
|
||||
// else, it paints the image's mask using 0xff
|
||||
}
|
||||
} else {
|
||||
*buf = *colours;
|
||||
}
|
||||
|
||||
// Point to the next colour
|
||||
colours++;
|
||||
|
||||
// Point to the next pixel
|
||||
buf++;
|
||||
}
|
||||
|
||||
// Point to the start of the next line
|
||||
buf += imageWidth - TILE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colours, uint16 imageWidth) {
|
||||
byte *fgBuf = (byte *)_fg->getBasePtr(0, 0) + offset;
|
||||
//byte *bgBuf = (byte *)_bg->getBasePtr(0, 0) + offset;
|
||||
|
||||
byte *dest;
|
||||
// TODO: Verify just the else block is required
|
||||
//if (_flagOne) {
|
||||
// Paint to the foreground
|
||||
//dest = (byte *)_fg->getBasePtr(0, 0) + offset;
|
||||
//} else {
|
||||
dest = (byte *)_bg->getBasePtr(0, 0) + offset;
|
||||
//}
|
||||
|
||||
int32 off = _origX + _origY * imageWidth;
|
||||
for (int y = 0; y < TILE_SIZE; y++) {
|
||||
for (int x = 0; x < TILE_SIZE; x++) {
|
||||
if (_flagSeven) {
|
||||
if (fgBuf[off] != 0xff) {
|
||||
if (*colours == 0xff) {
|
||||
dest[off] = fgBuf[off];
|
||||
} else {
|
||||
dest[off] = *colours;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Paint directly
|
||||
dest[off] = *colours;
|
||||
}
|
||||
colours++;
|
||||
off++;
|
||||
}
|
||||
|
||||
// Prepare the offset of the next line
|
||||
off += imageWidth - TILE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void VDXPlayer::chunkSound(Common::ReadStream *in) {
|
||||
if (!_audioStream) {
|
||||
_audioStream = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_UNSIGNED | Audio::Mixer::FLAG_AUTOFREE);
|
||||
Audio::SoundHandle sound_handle;
|
||||
::g_engine->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &sound_handle, _audioStream);
|
||||
}
|
||||
|
||||
byte *data = new byte[60000];
|
||||
int chunksize = in->read(data, 60000);
|
||||
_audioStream->queueBuffer(data, chunksize);
|
||||
}
|
||||
|
||||
void VDXPlayer::fadeIn(uint8 *targetpal) {
|
||||
// Don't do anything if we're asked to skip palette changes
|
||||
if (_flagSkipPalette)
|
||||
return;
|
||||
|
||||
// TODO: Is it required? If so, move to an appropiate place
|
||||
// Copy the foreground to the background
|
||||
memcpy((byte *)_vm->_graphicsMan->_foreground.getBasePtr(0, 0), (byte *)_vm->_graphicsMan->_background.getBasePtr(0, 0), 640 * 320);
|
||||
|
||||
// Start a fadein
|
||||
_vm->_graphicsMan->fadeIn(targetpal);
|
||||
|
||||
// Show the background
|
||||
_vm->_graphicsMan->updateScreen(_bg);
|
||||
}
|
||||
|
||||
void VDXPlayer::setPalette(uint8 *palette) {
|
||||
if (_flagSkipPalette)
|
||||
return;
|
||||
|
||||
uint8 palBuf[4 * 256];
|
||||
debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Setting palette");
|
||||
for (int i = 0; i < 256; i++) {
|
||||
palBuf[(i * 4) + 0] = palette[(i * 3) + 0];
|
||||
palBuf[(i * 4) + 1] = palette[(i * 3) + 1];
|
||||
palBuf[(i * 4) + 2] = palette[(i * 3) + 2];
|
||||
palBuf[(i * 4) + 3] = 0;
|
||||
}
|
||||
_syst->setPalette(palBuf, 0, 256);
|
||||
}
|
||||
|
||||
} // End of Groovie namespace
|
81
engines/groovie/vdx.h
Normal file
81
engines/groovie/vdx.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GROOVIE_VDX_H
|
||||
#define GROOVIE_VDX_H
|
||||
|
||||
#include "groovie/player.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
class VDXPlayer : public VideoPlayer {
|
||||
public:
|
||||
VDXPlayer(GroovieEngine *vm);
|
||||
~VDXPlayer();
|
||||
void setOrigin(int16 x, int16 y);
|
||||
|
||||
protected:
|
||||
uint16 loadInternal();
|
||||
bool playFrameInternal();
|
||||
|
||||
private:
|
||||
Graphics::Surface *_fg, *_bg;
|
||||
uint8 _palBuf[3 * 256];
|
||||
|
||||
// Origin
|
||||
int16 _origX, _origY;
|
||||
|
||||
// Video flags
|
||||
bool _flagZero;
|
||||
bool _flagOne;
|
||||
bool _flagOnePrev;
|
||||
byte _flag2Byte;
|
||||
bool _flagThree;
|
||||
bool _flagFour;
|
||||
bool _flagFive;
|
||||
bool _flagSix;
|
||||
bool _flagSeven;
|
||||
bool _flagEight;
|
||||
bool _flagNine;
|
||||
|
||||
bool _flagSkipStill;
|
||||
bool _flagSkipPalette;
|
||||
bool _flagFirstFrame;
|
||||
bool _flagTransparent;
|
||||
bool _flagUpdateStill;
|
||||
|
||||
void getStill(Common::ReadStream *in);
|
||||
void getDelta(Common::ReadStream *in);
|
||||
void expandColourMap(byte *out, uint16 colourMap, uint8 colour1, uint8 colour0);
|
||||
void decodeBlockStill(byte *buf, byte *colours, uint16 imageWidth, uint8 mask);
|
||||
void decodeBlockDelta(uint32 offset, byte *colours, uint16 imageWidth);
|
||||
void chunkSound(Common::ReadStream *in);
|
||||
void setPalette(uint8 *palette);
|
||||
void fadeIn(uint8 *palette);
|
||||
};
|
||||
|
||||
} // End of Groovie namespace
|
||||
|
||||
#endif // GROOVIE_VDX_H
|
Loading…
Add table
Add a link
Reference in a new issue