SAGA2: More work on Dinotopia

This commit is contained in:
Filippos Karapetis 2021-10-17 23:13:36 +03:00
parent 1c439e3add
commit 18ec7c853e
21 changed files with 213 additions and 115 deletions

View File

@ -27,6 +27,7 @@
#include "common/debug.h"
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/dispnode.h"
#include "saga2/tile.h"
#include "saga2/motion.h"
@ -3370,11 +3371,13 @@ int16 GetRandomBetween(int start, int end) {
}
void updateActorStates() {
// TODO: updateActorStates() for Dino
if (g_vm->getGameId() == GID_DINO)
return;
if (g_vm->_act->_actorStatesPaused) return;
int32 actorIndex;
actorIndex = g_vm->_act->_baseActorIndex = (g_vm->_act->_baseActorIndex + 1) & ActorManager::kEvalRateMask;
int32 actorIndex = g_vm->_act->_baseActorIndex = (g_vm->_act->_baseActorIndex + 1) & ActorManager::kEvalRateMask;
while (actorIndex < kActorCount) {
Actor *a = g_vm->_act->_actorList[actorIndex];
@ -3466,6 +3469,11 @@ void initActors() {
delete stream;
if (g_vm->getGameId() == GID_DINO) {
warning("TODO: initActors() for Dino");
return;
}
for (i = 0; i < resourceActorCount; i++) {
// Initialize the actors with the resource data
Actor *a = new Actor(resourceActorList[i]);

View File

@ -30,6 +30,7 @@
#include "audio/decoders/raw.h"
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/audio.h"
#include "saga2/fta.h"
#include "saga2/shorten.h"
@ -123,13 +124,15 @@ void startAudio() {
g_vm->_audio->initAudioInterface(musicRes);
// kludgy in memory click sounds
g_vm->_audio->_clickSizes[0] = 0;
g_vm->_audio->_clickSizes[1] = soundRes->size(MKTAG('C', 'L', 'K', 1));
g_vm->_audio->_clickSizes[2] = soundRes->size(MKTAG('C', 'L', 'K', 2));
g_vm->_audio->_clickData[0] = NULL;
g_vm->_audio->_clickData[1] = (uint8 *)LoadResource(soundRes, MKTAG('C', 'L', 'K', 1), "Click 1");
g_vm->_audio->_clickData[2] = (uint8 *)LoadResource(soundRes, MKTAG('C', 'L', 'K', 2), "Click 2");
if (g_vm->getGameId() == GID_FTA2) {
// kludgy in memory click sounds
g_vm->_audio->_clickSizes[0] = 0;
g_vm->_audio->_clickSizes[1] = soundRes->size(MKTAG('C', 'L', 'K', 1));
g_vm->_audio->_clickSizes[2] = soundRes->size(MKTAG('C', 'L', 'K', 2));
g_vm->_audio->_clickData[0] = NULL;
g_vm->_audio->_clickData[1] = (uint8 *)LoadResource(soundRes, MKTAG('C', 'L', 'K', 1), "Click 1");
g_vm->_audio->_clickData[2] = (uint8 *)LoadResource(soundRes, MKTAG('C', 'L', 'K', 2), "Click 2");
}
}
void cleanupAudio() {

View File

@ -217,7 +217,7 @@ void resumeCalender() {
//-----------------------------------------------------------------------
// Update the global calender
void updateCalender() {
void updateCalendar() {
if (!g_vm->_calender->_calenderPaused) g_vm->_calender->update();
}

View File

@ -100,7 +100,7 @@ public:
Calender management functions
* ===================================================================== */
void updateCalender();
void updateCalendar();
void pauseCalender();
void resumeCalender();

View File

@ -25,6 +25,7 @@
*/
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/objects.h"
#include "saga2/contain.h"
#include "saga2/grabinfo.h"
@ -1647,6 +1648,11 @@ ContainerNode *OpenMindContainer(PlayerActorID player, int16 open, int16 type) {
* ===================================================================== */
void initContainers() {
if (g_vm->getGameId() == GID_DINO) {
warning("TODO: initContainers() for Dino");
return;
}
if (containerRes == NULL)
containerRes = resFile->newContext(MKTAG('C', 'O', 'N', 'T'), "cont.resources");
@ -1755,6 +1761,10 @@ void cleanupContainerNodes() {
}
void updateContainerWindows() {
// TODO: updateContainerWindows() for Dino
if (g_vm->getGameId() == GID_DINO)
return;
g_vm->_cnm->doDeferredActions();
}

View File

@ -62,7 +62,7 @@ static const SAGA2GameDescription gameDescriptions[] = {
{"dinodata.hrs", GAME_RESOURCEFILE, "45aa7026d441dd69957385c25d2fd33e", 2698},
{"dino.hrs", GAME_OBJRESOURCEFILE, "7cf3665887a4a18e2fff6938a954c050", 66018},
{"scripts.hrs", GAME_SCRIPTFILE, "d405841a249a365cf92fc65dd52fb953", 164181},
{"dinosnd.hrs", GAME_SOUNDFILE | GAME_VOICEFILE, "dcf4ade416614b8a64f99dacfd3bd071", 199163997},
{"dinosnd.hrs", GAME_SOUNDFILE, "dcf4ade416614b8a64f99dacfd3bd071", 199163997},
{"dinoimag.hrs", GAME_IMAGEFILE, "d24d80676f7afcfaca0b61c95056044f", 42342931},
AD_LISTEND
},
@ -82,7 +82,7 @@ static const SAGA2GameDescription gameDescriptions[] = {
{"dinodata.hrs", GAME_RESOURCEFILE, "45aa7026d441dd69957385c25d2fd33e", 2698},
{"dino.hrs", GAME_OBJRESOURCEFILE, "7cf3665887a4a18e2fff6938a954c050", 66018},
{"scripts.hrs", GAME_SCRIPTFILE, "d405841a249a365cf92fc65dd52fb953", 164181},
{"dinosnd.hrs", GAME_SOUNDFILE | GAME_VOICEFILE, "27a57517be881ad9e0f671901486356e", 228642994},
{"dinosnd.hrs", GAME_SOUNDFILE, "27a57517be881ad9e0f671901486356e", 228642994},
{"dinoimag.hrs", GAME_IMAGEFILE, "d24d80676f7afcfaca0b61c95056044f", 42448562},
AD_LISTEND
},

View File

@ -26,6 +26,7 @@
#include "saga2/saga2.h"
#include "saga2/blitters.h"
#include "saga2/detection.h"
#include "saga2/spelshow.h"
#include "saga2/player.h"
#include "saga2/sensor.h"
@ -164,9 +165,12 @@ void DisplayNodeList::draw() {
objectSet = objectSprites;
if (objectSet == NULL)
error("Object sprites have been dumped!\n");
spellSet = spellSprites;
if (spellSet == NULL)
error("Spell sprites have been dumped!\n");
if (g_vm->getGameId() == GID_FTA2) {
spellSet = spellSprites;
if (spellSet == NULL)
error("Spell sprites have been dumped!\n");
}
for (dn = DisplayNodeList::head; dn; dn = dn->nextDisplayed) {
if (dn->type == nodeTypeEffect)
@ -338,18 +342,11 @@ void DisplayNode::updateObject(const int32 deltaTime) {
//-----------------------------------------------------------------------
// Draw sprites for normal objects
#if DINO
const int maxSpriteWidth = 320,
maxSpriteHeight = 320,
maxSpriteBaseLine = 50;
#else
const int maxSpriteWidth = 32,
maxSpriteHeight = 120,
maxSpriteBaseLine = 16;
#endif
void DisplayNode::drawObject() {
const int maxSpriteWidth = (g_vm->getGameId() == GID_FTA2) ? 32 : 320;
const int maxSpriteHeight = (g_vm->getGameId() == GID_FTA2) ? 120 : 320;
const int maxSpriteBaseLine = (g_vm->getGameId() == GID_FTA2) ? 16 : 50;
ColorTable mainColors, // colors for object
leftColors, // colors for left-hand object
rightColors; // colors for right-hand object

View File

@ -25,6 +25,7 @@
*/
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/floating.h"
#include "saga2/objects.h"
#include "saga2/imagcach.h"
@ -182,6 +183,11 @@ void DecoratedWindow::setDecorations(
decorations = new WindowDecoration[numDecorations];
if (g_vm->getGameId() == GID_DINO) {
warning("TODO: setDecorations() for Dino");
return;
}
// For each "decorative panel" within the frame of the window
for (i = 0; i < numDecorations; i++, dec++) {

View File

@ -25,6 +25,7 @@
*/
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/blitters.h"
#include "saga2/objects.h"
#include "saga2/contain.h"
@ -1527,6 +1528,11 @@ void unloadImageRes(void **images, int16 numRes) {
// defined for setup off all button based user controls
void SetupUserControls() {
if (g_vm->getGameId() == GID_DINO) {
warning("TODO: SetupUserControls() for Dino");
return;
}
// index variables
uint16 n;
uint8 index = 0;
@ -2019,7 +2025,7 @@ void updateBrotherArmor(uint16 brotherID) {
void updateAllUserControls() {
if (displayEnabled()) {
if (g_vm->_userControlsSetup) {
if (g_vm->_userControlsSetup && g_vm->getGameId() == GID_FTA2) {
uint16 centerBrotherID = getCenterActorPlayerID(),
brotherID;

View File

@ -25,6 +25,7 @@
*/
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "graphics/palette.h"
@ -42,6 +43,9 @@ void initLoadMode() {
}
void updateLoadMode() {
if (g_vm->getGameId() == GID_DINO)
return; // TODO: Load EXE resources for Dino
if (inLoadMode) {
byte normalPalette[768];

View File

@ -332,9 +332,10 @@ void displayUpdate() {
elapsed += (gameTime - lastGameTime);
lastGameTime = gameTime;
debugC(1, kDebugEventLoop, "EventLoop: Interface indicator updates");
updateIndicators();
if (g_vm->getGameId() == GID_FTA2) {
debugC(1, kDebugEventLoop, "EventLoop: Interface indicator updates");
updateIndicators();
}
g_system->updateScreen();
g_system->delayMillis(10);
@ -597,6 +598,9 @@ bool openResources() {
break;
case GAME_SOUNDFILE:
res = openResource(soundResFile, desc->fileName);
// Dinotopia contains both sound and voices in the same file
if (g_vm->getGameId() == GID_DINO)
res = openResource(voiceResFile, desc->fileName);
break;
case GAME_IMAGEFILE:
res = openResource(resFile, desc->fileName);

View File

@ -25,6 +25,7 @@
*/
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/objects.h"
#include "saga2/tile.h"
#include "saga2/motion.h"
@ -2963,6 +2964,11 @@ void initObjects() {
delete stream;
if (g_vm->getGameId() == GID_DINO) {
warning("TODO: initObjects() for Dino");
return;
}
for (i = 0; i < resourceObjectCount; i++) {
GameObject *obj = &objectList[i];
@ -3298,9 +3304,11 @@ void ActiveRegion::update() {
// Iterate through the active regions, updating each
void updateActiveRegions() {
int16 i;
// TODO: updateActiveRegions() for Dino
if (g_vm->getGameId() == GID_DINO)
return;
for (i = 0; i < kPlayerActors; i++)
for (int16 i = 0; i < kPlayerActors; i++)
g_vm->_activeRegionList[i].update();
}
@ -3315,6 +3323,11 @@ ActiveRegion *getActiveRegion(PlayerActorID id) {
// Initialize the state of the active regions
void initActiveRegions() {
if (g_vm->getGameId() == GID_DINO) {
warning("TODO: initActiveRegions() for Dino");
return;
}
static PlayerActorID playerIDArray[kPlayerActors] =
{ FTA_JULIAN, FTA_PHILIP, FTA_KEVIN };
@ -4531,6 +4544,10 @@ bool backgroundSimulationPaused;
// This function does background processing on a few actors, objects
void doBackgroundSimulation() {
// TODO: doBackgroundSimulation() for Dino
if (g_vm->getGameId() == GID_DINO)
return;
if (backgroundSimulationPaused) return;
// Debug code to verify the validity of the limbo counts

View File

@ -25,6 +25,7 @@
*/
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/intrface.h"
#include "saga2/contain.h"
#include "saga2/task.h"
@ -897,6 +898,11 @@ struct PlayerActorArchive {
// Initialize the player list
void initPlayerActors() {
if (g_vm->getGameId() == GID_DINO) {
warning("TODO: initPlayerActors() for Dino");
return;
}
g_vm->_playerList.push_back(new PlayerActor(ActorBaseID + 0)); // Julian
g_vm->_playerList.push_back(new PlayerActor(ActorBaseID + 1)); // Philip
g_vm->_playerList.push_back(new PlayerActor(ActorBaseID + 2)); // Kevin
@ -1043,6 +1049,11 @@ struct CenterActorArchive {
// Initialize the center actor ID and view object ID
void initCenterActor() {
if (g_vm->getGameId() == GID_DINO) {
warning("TODO: initCenterActor() for Dino");
return;
}
centerActor = FTA_JULIAN;
viewCenterObject = g_vm->_playerList[centerActor]->getActorID();

View File

@ -27,6 +27,7 @@
#include "graphics/surface.h"
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/blitters.h"
#include "saga2/objects.h"
#include "saga2/tile.h"
@ -214,16 +215,16 @@ void PlayModeSetup() {
// placement configurations
Point16 massWeightIndicator = Point16(531, 265);
// activate the indiv mode character mass and weight indicator
MassWeightIndicator = new CMassWeightIndicator(indivControls, massWeightIndicator);
// activate the plyaer health indicator
HealthIndicator = new CHealthIndicator(cmdHealthStar);
if (g_vm->getGameId() == GID_FTA2) {
// activate the indiv mode character mass and weight indicator
MassWeightIndicator = new CMassWeightIndicator(indivControls, massWeightIndicator);
// activate the player health indicator
HealthIndicator = new CHealthIndicator(cmdHealthStar);
}
SetupUserControls();
// Set up mouse cursor
g_vm->_mouseInfo = new GrabInfo;
g_vm->_mouseInfo->setIntent(GrabInfo::WalkTo);

View File

@ -104,6 +104,8 @@ Saga2Engine::Saga2Engine(OSystem *syst, const SAGA2GameDescription *desc)
SearchMan.addSubDirectoryMatching(gameDataDir, "res");
SearchMan.addSubDirectoryMatching(gameDataDir, "dos/drivers"); // For Miles Sound files
SearchMan.addSubDirectoryMatching(gameDataDir, "drivers");
SearchMan.addSubDirectoryMatching(gameDataDir, "video"); // FTA2 movies
SearchMan.addSubDirectoryMatching(gameDataDir, "smack"); // Dino movies
_loadedWeapons = 0;
@ -174,6 +176,7 @@ Common::Error Saga2Engine::run() {
if (getGameId() == GID_FTA2)
loadExeResources();
// TODO: Load EXE resources for Dino
main_saga2();

View File

@ -25,6 +25,7 @@
*/
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/fta.h"
#include "saga2/blitters.h"
#include "saga2/sprite.h"
@ -829,31 +830,33 @@ void initSprites() {
delete stream;
assert(objectSprites);
// intagible object sprites
stream = loadResourceToStream(spriteRes, mentalSpriteID, "mental sprites");
mentalSprites = new SpriteSet(stream);
delete stream;
assert(mentalSprites);
if (g_vm->getGameId() == GID_FTA2) {
// intagible object sprites
stream = loadResourceToStream(spriteRes, mentalSpriteID, "mental sprites");
mentalSprites = new SpriteSet(stream);
delete stream;
assert(mentalSprites);
for (i = 0; i < maxWeaponSpriteSets; i++) {
hResID weaponSpriteID;
for (i = 0; i < maxWeaponSpriteSets; i++) {
hResID weaponSpriteID;
weaponSpriteID = weaponSpriteBaseID + MKTAG(0, 0, 0, i);
weaponSpriteID = weaponSpriteBaseID + MKTAG(0, 0, 0, i);
if (spriteRes->size(weaponSpriteID) == 0) {
weaponSprites[i] = nullptr;
continue;
if (spriteRes->size(weaponSpriteID) == 0) {
weaponSprites[i] = nullptr;
continue;
}
stream = loadResourceToStream(spriteRes, weaponSpriteID, "weapon sprite set");
weaponSprites[i] = new SpriteSet(stream);
delete stream;
}
stream = loadResourceToStream(spriteRes, weaponSpriteID, "weapon sprite set");
weaponSprites[i] = new SpriteSet(stream);
stream = loadResourceToStream(spriteRes, missileSpriteID, "missle sprites");
missileSprites = new SpriteSet(stream);
delete stream;
}
stream = loadResourceToStream(spriteRes, missileSpriteID, "missle sprites");
missileSprites = new SpriteSet(stream);
delete stream;
initQuickMem(0x10000);
// Initialize actor appearance table

View File

@ -28,6 +28,7 @@
#include "graphics/surface.h"
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/blitters.h"
#include "saga2/hresmgr.h"
#include "saga2/objects.h"
@ -4298,6 +4299,10 @@ bool underSameRoof(GameObject *obj1, GameObject *obj2) {
extern void testSprites();
void updateMainDisplay() {
// TODO: updateMainDisplay() for Dino
if (g_vm->getGameId() == GID_DINO)
return;
static TilePoint lastViewLoc = TilePoint(0, 0, 0);
int32 deltaTime = gameTime - lastUpdateTime;

View File

@ -27,6 +27,7 @@
#include "common/events.h"
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/tilemode.h"
#include "saga2/tile.h"
#include "saga2/setup.h"
@ -700,12 +701,52 @@ static int postDisplayFrame = 3;
// We need to test if UI is locked, so as to not pause combat
extern int lockUINest;
void CheckCombat() {
static int flipper = 0;
// Get the actor we're controlling.
Actor *a = getCenterActor();
audioEnvironmentSetAggression(isCenterActorAggressive());
// Check combat mood once every 8 frames or so.
// Otherwise, check for combat start/stop
// (Kludge to balance CPU usage).
if ((++flipper & 0xF) == 0)
CheckCombatMood();
else if (timeSinceLastAggressiveAct() < 60 && areThereActiveEnemies()) {
if (!inCombat) {
inCombat = true;
startCombat();
}
} else {
if (inCombat) {
inCombat = false;
endCombat();
}
}
if (inCombat) {
if (!a->isMoving() && a->isInterruptable() && lockUINest == 0) {
if (!combatPaused) {
combatPaused = true;
pauseCombat();
}
} else {
if (combatPaused) {
combatPaused = false;
resumeCombat();
}
}
}
}
void TileModeHandleTask() {
bool taskChek = false;
// Run any SAGA scripts which are waiting to run.
dispatchScripts();
// update day and night
//mm("daytime transition update loop");
dayNightUpdate();
@ -713,52 +754,17 @@ void TileModeHandleTask() {
// If it's time to do a new frame.
if (frameAlarm.check()
&& tileLockFlag == 0) {
static int flipper = 0;
// Get the actor we're controlling.
Actor *a = getCenterActor();
if (g_vm->getGameId() == GID_FTA2)
CheckCombat();
audioEnvironmentSetAggression(isCenterActorAggressive());
// Check combat mood once every 8 frames or so.
// Otherwise, check for combat start/stop
// (Kludge to balance CPU usage).
if ((++flipper & 0xF) == 0)
CheckCombatMood();
else if (timeSinceLastAggressiveAct() < 60
&& areThereActiveEnemies()) {
if (!inCombat) {
inCombat = true;
startCombat();
}
} else {
if (inCombat) {
inCombat = false;
endCombat();
}
}
if (inCombat) {
if (!a->isMoving() && a->isInterruptable() && lockUINest == 0) {
if (!combatPaused) {
combatPaused = true;
pauseCombat();
}
} else {
if (combatPaused) {
combatPaused = false;
resumeCombat();
}
}
}
updateCalender();
updateCalendar();
// update the text status line
StatusLine->experationCheck();
doBackgroundSimulation();
if (g_vm->getGameId() == GID_FTA2)
doBackgroundSimulation();
// do an alarm check for container views
if (containerObjTextAlarm.check()) {
@ -772,8 +778,10 @@ void TileModeHandleTask() {
}
}
if (g_vm->_toolBase->isMousePanel(tileMapControl)) {
// Get the actor we're controlling.
Actor *a = getCenterActor();
// If mouse is near edge of screen, then run.
runFlag = lastMousePos.x < runThreshhold
|| lastMousePos.x >= kTileRectWidth - runThreshhold

View File

@ -25,6 +25,7 @@
*/
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/towerwin.h"
#include "saga2/towerfta.h"
#include "saga2/fta.h"
@ -213,9 +214,12 @@ INITIALIZER(initResourceHandles) {
listRes = objResFile->newContext(MKTAG('L', 'I', 'S', 'T'), "list resources");
if (!listRes->_valid)
return false;
resImports = (ResImportTable *)LoadResource(listRes, MKTAG('I', 'M', 'P', 'O'), "res imports");
if (!resImports)
return false;
if (g_vm->getGameId() == GID_FTA2) {
// Only FTA2 has resource imports
resImports = (ResImportTable *)LoadResource(listRes, MKTAG('I', 'M', 'P', 'O'), "res imports");
if (!resImports)
return false;
}
return true;
}
@ -383,7 +387,8 @@ TERMINATOR(termActorSprites) {
// ------------------------------------------------------------------------
INITIALIZER(initWeaponData) {
initWeapons();
if (g_vm->getGameId() == GID_FTA2)
initWeapons();
return true;
}
@ -395,7 +400,8 @@ TERMINATOR(termWeaponData) {
// ------------------------------------------------------------------------
INITIALIZER(initSpellData) {
initMagic();
if (g_vm->getGameId() == GID_FTA2)
initMagic();
return true;
}
@ -407,7 +413,8 @@ TERMINATOR(termSpellData) {
// ------------------------------------------------------------------------
INITIALIZER(initObjectSoundFX) {
initObjectSoundFXTable();
if (g_vm->getGameId() == GID_FTA2)
initObjectSoundFXTable();
return true;
}
@ -418,7 +425,8 @@ TERMINATOR(termObjectSoundFX) {
// ------------------------------------------------------------------------
INITIALIZER(initObjectPrototypes) {
initPrototypes();
if (g_vm->getGameId() == GID_FTA2)
initPrototypes();
return true;
}

View File

@ -27,6 +27,7 @@
#include "common/config-manager.h"
#include "saga2/saga2.h"
#include "saga2/detection.h"
#include "saga2/fta.h"
#include "saga2/player.h"
#include "saga2/display.h"
@ -40,6 +41,8 @@ namespace Saga2 {
#define INTRO_VID1 "TRIMARK" VIDEO_EXTENSION
#define INTRO_VID2 "INTRO" VIDEO_EXTENSION
#define INTRO_VID_DINO "TESTVID" VIDEO_EXTENSION
#define WIN_VID_1 "END_1" VIDEO_EXTENSION
#define WIN_VID_2 "END_2" VIDEO_EXTENSION
#define WIN_VID_3 "END_3A" VIDEO_EXTENSION
@ -223,9 +226,13 @@ static void playAVideo(const char *fileName, int x, int y) { //, int16 from, int
// intro video(s)
static void doIntro() {
playAVideo(INTRO_VID1, 0, 0);
abortFlag = false;
playAVideo(INTRO_VID2, 0, 0);
if (g_vm->getGameId() == GID_FTA2) {
playAVideo(INTRO_VID1, 0, 0);
abortFlag = false;
playAVideo(INTRO_VID2, 0, 0);
} else {
playAVideo(INTRO_VID_DINO, 0, 0);
}
}
// ------------------------------------------------------------------------

View File

@ -41,16 +41,13 @@ static bool nameCheck(char name[], const char ext[], int len) {
}
void Saga2Engine::startVideo(const char *fileName, int x, int y) {
char file[260];
strcpy(file, "video/");
Common::strlcat(file, fileName, 260);
nameCheck(file, VIDEO_EXT, 260);
nameCheck((char *)fileName, VIDEO_EXT, 260);
if (!_smkDecoder)
_smkDecoder = new Video::SmackerDecoder();
if (!_smkDecoder->loadFile(file)) {
warning("startVideo: Cannot open file %s", file);
if (!_smkDecoder->loadFile(fileName)) {
warning("startVideo: Cannot open file %s", fileName);
return;
}