aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS14
-rw-r--r--audio/decoders/quicktime.cpp7
-rw-r--r--backends/keymapper/action.h6
-rw-r--r--backends/midi/coreaudio.cpp38
-rw-r--r--common/quicktime.cpp19
-rw-r--r--common/quicktime.h2
-rwxr-xr-xdevtools/credits.pl14
-rwxr-xr-xdevtools/tasmrecover/tasm-recover24
-rw-r--r--engines/agi/objects.cpp2
-rw-r--r--engines/dreamweb/dreambase.h7
-rw-r--r--engines/dreamweb/dreamgen.cpp1213
-rw-r--r--engines/dreamweb/dreamgen.h94
-rw-r--r--engines/dreamweb/pathfind.cpp20
-rw-r--r--engines/dreamweb/people.cpp15
-rw-r--r--engines/dreamweb/sprite.cpp2
-rw-r--r--engines/dreamweb/stubs.cpp350
-rw-r--r--engines/dreamweb/stubs.h20
-rw-r--r--engines/dreamweb/use.cpp270
-rw-r--r--engines/kyra/lol.cpp54
-rw-r--r--engines/mohawk/graphics.cpp15
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp8
-rw-r--r--engines/mohawk/myst_stacks/stoneship.cpp4
-rw-r--r--engines/mohawk/video.cpp9
-rw-r--r--engines/mohawk/video.h1
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp8
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.cpp169
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.h24
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes2.cpp297
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes2.h61
-rw-r--r--engines/tsage/ringworld2/ringworld2_speakers.cpp9
-rw-r--r--engines/tsage/ringworld2/ringworld2_speakers.h2
-rw-r--r--gui/credits.h7
-rw-r--r--video/qt_decoder.cpp808
-rw-r--r--video/qt_decoder.h114
34 files changed, 2103 insertions, 1604 deletions
diff --git a/AUTHORS b/AUTHORS
index e152e3a21b..b28cd55fb4 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -32,7 +32,7 @@ ScummVM Team
Max Horn - (retired)
Travis Howell
Pawel Kolodziejski - Codecs, iMUSE, Smush, etc.
- Gregory Montoir
+ Gregory Montoir - (retired)
Eugene Sandulenko - FT INSANE, MM NES, MM C64, game detection,
Herc/CGA
Ludvig Strigeus - (retired)
@@ -40,7 +40,7 @@ ScummVM Team
HE:
Jonathan Gray - (retired)
Travis Howell
- Gregory Montoir
+ Gregory Montoir - (retired)
Eugene Sandulenko
AGI:
@@ -67,7 +67,7 @@ ScummVM Team
Cine:
Vincent Hamm - (retired)
Pawel Kolodziejski
- Gregory Montoir
+ Gregory Montoir - (retired)
Kari Salminen
Eugene Sandulenko
@@ -111,7 +111,7 @@ ScummVM Team
Torbjorn Andersson - VQA Player
Oystein Eftevaag
Florian Kagerer
- Gregory Montoir
+ Gregory Montoir - (retired)
Johannes Schickel
Lastexpress:
@@ -139,7 +139,7 @@ ScummVM Team
Queen:
David Eriksson - (retired)
- Gregory Montoir
+ Gregory Montoir - (retired)
Joost Peters
SAGA:
@@ -198,14 +198,14 @@ ScummVM Team
Sylvain Dupont
Touche:
- Gregory Montoir
+ Gregory Montoir - (retired)
TsAGE:
Arnaud Boutonne
Paul Gilbert
Tucker:
- Gregory Montoir
+ Gregory Montoir - (retired)
Backend Teams
-------------
diff --git a/audio/decoders/quicktime.cpp b/audio/decoders/quicktime.cpp
index 8cf0305e88..e737bf8e10 100644
--- a/audio/decoders/quicktime.cpp
+++ b/audio/decoders/quicktime.cpp
@@ -87,6 +87,9 @@ void QuickTimeAudioDecoder::init() {
// Initialize the codec (if necessary)
entry->initCodec();
+
+ if (_tracks[_audioTrackIndex]->editCount != 1)
+ warning("Multiple edit list entries in an audio track. Things may go awry");
}
}
}
@@ -414,7 +417,9 @@ public:
}
Timestamp getLength() const {
- return Timestamp(0, _tracks[_audioTrackIndex]->duration, _tracks[_audioTrackIndex]->timeScale);
+ // TODO: Switch to the other one when audio edits are supported
+ //return Timestamp(0, _tracks[_audioTrackIndex]->duration, _timeScale);
+ return Timestamp(0, _tracks[_audioTrackIndex]->mediaDuration, _tracks[_audioTrackIndex]->timeScale);
}
};
diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h
index b15b3aaaad..e5bf6d51dd 100644
--- a/backends/keymapper/action.h
+++ b/backends/keymapper/action.h
@@ -40,6 +40,12 @@ class Keymap;
#define ACTION_ID_SIZE (4)
+struct KeyActionEntry {
+ const KeyState ks;
+ const char *id;
+ const char *description;
+};
+
struct Action {
/** unique id used for saving/loading to config */
char id[ACTION_ID_SIZE];
diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp
index 305b462836..4b707eace6 100644
--- a/backends/midi/coreaudio.cpp
+++ b/backends/midi/coreaudio.cpp
@@ -26,15 +26,24 @@
#ifdef MACOSX
-// HACK to disable deprecated warnings under Mac OS X 10.5.
-// Apple depracted the AUGraphNewNode & AUGraphGetNodeInfo APIs
-// in favor of the new AUGraphAddNode & AUGraphNodeInfo APIs.
-// While it would be trivial to switch to those, this would break
-// binary compatibility with all pre-10.5 systems, so we don't want
-// to do that just now. Maybe when 10.6 comes... :)
+
+// HACK to disable deprecated warnings under Mac OS X 10.5. Apple deprecated the
+// AUGraphNewNode & AUGraphGetNodeInfo APIs in favor of the new AUGraphAddNode &
+// AUGraphNodeInfo APIs. While it is easy to switch to those, it breaks
+// compatibility with all pre-10.5 systems.
+// If you want to retain compatibility with old systems, enable the following
+// switch. But Apple will eventually remove these APIs, at which point the
+// switch needs to be disabled.
+//
+// Also note that only the new API is available on the iPhone!
+#define USE_DEPRECATED_COREAUDIO_API
+
+
+#ifdef USE_DEPRECATED_COREAUDIO_API
#include <AvailabilityMacros.h>
#undef DEPRECATED_ATTRIBUTE
#define DEPRECATED_ATTRIBUTE
+#endif
#include "common/config-manager.h"
@@ -105,7 +114,11 @@ int MidiDriver_CORE::open() {
RequireNoErr(NewAUGraph(&_auGraph));
AUNode outputNode, synthNode;
+#ifdef USE_DEPRECATED_COREAUDIO_API
ComponentDescription desc;
+#else
+ AudioComponentDescription desc;
+#endif
// The default output device
desc.componentType = kAudioUnitType_Output;
@@ -113,13 +126,21 @@ int MidiDriver_CORE::open() {
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
+#ifdef USE_DEPRECATED_COREAUDIO_API
RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &outputNode));
+#else
+ RequireNoErr(AUGraphAddNode(_auGraph, &desc, &outputNode));
+#endif
// The built-in default (softsynth) music device
desc.componentType = kAudioUnitType_MusicDevice;
desc.componentSubType = kAudioUnitSubType_DLSSynth;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+#ifdef USE_DEPRECATED_COREAUDIO_API
RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &synthNode));
+#else
+ RequireNoErr(AUGraphAddNode(_auGraph, &desc, &synthNode));
+#endif
// Connect the softsynth to the default output
RequireNoErr(AUGraphConnectNodeInput(_auGraph, synthNode, 0, outputNode, 0));
@@ -129,8 +150,11 @@ int MidiDriver_CORE::open() {
RequireNoErr(AUGraphInitialize(_auGraph));
// Get the music device from the graph.
+#ifdef USE_DEPRECATED_COREAUDIO_API
RequireNoErr(AUGraphGetNodeInfo(_auGraph, synthNode, NULL, NULL, NULL, &_synth));
-
+#else
+ RequireNoErr(AUGraphNodeInfo(_auGraph, synthNode, NULL, &_synth));
+#endif
// Load custom soundfont, if specified
if (ConfMan.hasKey("soundfont")) {
diff --git a/common/quicktime.cpp b/common/quicktime.cpp
index 9ea8c229ea..e16d3f2652 100644
--- a/common/quicktime.cpp
+++ b/common/quicktime.cpp
@@ -386,8 +386,7 @@ int QuickTimeParser::readTKHD(Atom atom) {
/* track->id = */_fd->readUint32BE(); // track id (NOT 0 !)
_fd->readUint32BE(); // reserved
- //track->startTime = 0; // check
- (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // highlevel (considering edits) duration in movie timebase
+ track->duration = (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // highlevel (considering edits) duration in movie timebase
_fd->readUint32BE(); // reserved
_fd->readUint32BE(); // reserved
@@ -410,8 +409,8 @@ int QuickTimeParser::readTKHD(Atom atom) {
track->scaleFactorY.debugPrint(1, "readTKHD(): scaleFactorY =");
// these are fixed-point, 16:16
- // uint32 tkWidth = _fd->readUint32BE() >> 16; // track width
- // uint32 tkHeight = _fd->readUint32BE() >> 16; // track height
+ //_fd->readUint32BE() >> 16; // track width
+ //_fd->readUint32BE() >> 16; // track height
return 0;
}
@@ -428,17 +427,18 @@ int QuickTimeParser::readELST(Atom atom) {
debug(2, "Track %d edit list count: %d", _tracks.size() - 1, track->editCount);
+ uint32 offset = 0;
+
for (uint32 i = 0; i < track->editCount; i++){
track->editList[i].trackDuration = _fd->readUint32BE();
track->editList[i].mediaTime = _fd->readSint32BE();
track->editList[i].mediaRate = Rational(_fd->readUint32BE(), 0x10000);
- debugN(3, "\tDuration = %d, Media Time = %d, ", track->editList[i].trackDuration, track->editList[i].mediaTime);
+ track->editList[i].timeOffset = offset;
+ debugN(3, "\tDuration = %d (Offset = %d), Media Time = %d, ", track->editList[i].trackDuration, offset, track->editList[i].mediaTime);
track->editList[i].mediaRate.debugPrint(3, "Media Rate =");
+ offset += track->editList[i].trackDuration;
}
- if (track->editCount != 1)
- warning("Multiple edit list entries. Things may go awry");
-
return 0;
}
@@ -500,7 +500,7 @@ int QuickTimeParser::readMDHD(Atom atom) {
}
track->timeScale = _fd->readUint32BE();
- track->duration = (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // duration
+ track->mediaDuration = (version == 1) ? (_fd->readUint32BE(), _fd->readUint32BE()) : _fd->readUint32BE(); // duration
_fd->readUint16BE(); // language
_fd->readUint16BE(); // quality
@@ -793,6 +793,7 @@ QuickTimeParser::Track::Track() {
duration = 0;
startTime = 0;
objectTypeMP4 = 0;
+ mediaDuration = 0;
}
QuickTimeParser::Track::~Track() {
diff --git a/common/quicktime.h b/common/quicktime.h
index e4c821e209..d7e2691c2b 100644
--- a/common/quicktime.h
+++ b/common/quicktime.h
@@ -109,6 +109,7 @@ protected:
struct EditListEntry {
uint32 trackDuration;
+ uint32 timeOffset;
int32 mediaTime;
Rational mediaRate;
};
@@ -163,6 +164,7 @@ protected:
uint32 frameCount;
uint32 duration;
+ uint32 mediaDuration;
uint32 startTime;
Rational scaleFactorX;
Rational scaleFactorY;
diff --git a/devtools/credits.pl b/devtools/credits.pl
index 2833236e75..86ba7412fa 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -484,7 +484,7 @@ begin_credits("Credits");
add_person("Max Horn", "Fingolfin", "(retired)");
add_person("Travis Howell", "Kirben", "");
add_person("Pawe&#322; Ko&#322;odziejski", "aquadran", "Codecs, iMUSE, Smush, etc.");
- add_person("Gregory Montoir", "cyx", "");
+ add_person("Gregory Montoir", "cyx", "(retired)");
add_person("Eugene Sandulenko", "sev", "FT INSANE, MM NES, MM C64, game detection, Herc/CGA");
add_person("Ludvig Strigeus", "ludde", "(retired)");
end_section();
@@ -492,7 +492,7 @@ begin_credits("Credits");
begin_section("HE");
add_person("Jonathan Gray", "khalek", "(retired)");
add_person("Travis Howell", "Kirben", "");
- add_person("Gregory Montoir", "cyx", "");
+ add_person("Gregory Montoir", "cyx", "(retired)");
add_person("Eugene Sandulenko", "sev", "");
end_section();
@@ -523,7 +523,7 @@ begin_credits("Credits");
begin_section("Cine");
add_person("Vincent Hamm", "yaz0r", "(retired)");
add_person("Pawe&#322; Ko&#322;odziejski", "aquadran", "");
- add_person("Gregory Montoir", "cyx", "");
+ add_person("Gregory Montoir", "cyx", "(retired)");
add_person("Kari Salminen", "Buddha^", "");
add_person("Eugene Sandulenko", "sev", "");
end_section();
@@ -576,7 +576,7 @@ begin_credits("Credits");
add_person("Torbj&ouml;rn Andersson", "eriktorbjorn", "VQA Player");
add_person("Oystein Eftevaag", "vinterstum", "");
add_person("Florian Kagerer", "athrxx", "");
- add_person("Gregory Montoir", "cyx", "");
+ add_person("Gregory Montoir", "cyx", "(retired)");
add_person("Johannes Schickel", "LordHoto", "");
end_section();
@@ -610,7 +610,7 @@ begin_credits("Credits");
begin_section("Queen");
add_person("David Eriksson", "twogood", "(retired)");
- add_person("Gregory Montoir", "cyx", "");
+ add_person("Gregory Montoir", "cyx", "(retired)");
add_person("Joost Peters", "joostp", "");
end_section();
@@ -679,7 +679,7 @@ begin_credits("Credits");
end_section();
begin_section("Touch&eacute;");
- add_person("Gregory Montoir", "cyx", "");
+ add_person("Gregory Montoir", "cyx", "(retired)");
end_section();
begin_section("TsAGE");
@@ -688,7 +688,7 @@ begin_credits("Credits");
end_section();
begin_section("Tucker");
- add_person("Gregory Montoir", "cyx", "");
+ add_person("Gregory Montoir", "cyx", "(retired)");
end_section();
end_section();
diff --git a/devtools/tasmrecover/tasm-recover b/devtools/tasmrecover/tasm-recover
index 8ddfed4aa7..c1f2872a8b 100755
--- a/devtools/tasmrecover/tasm-recover
+++ b/devtools/tasmrecover/tasm-recover
@@ -148,6 +148,9 @@ p = parser(skip_binary_data = [
'ch1blocksplayed',
'soundemmpage',
'speechemmpage',
+ 'lineroutine',
+ 'increment1',
+ 'increment2',
# vgagrafx.asm
'cityname',
'extragraphics1',
@@ -222,6 +225,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'animpointer',
'atmospheres',
'attendant',
+ 'autoappear',
'autolook',
'autosetwalk',
'backobject',
@@ -356,6 +360,8 @@ generator = cpp(context, "DreamGen", blacklist = [
'endpaltostart',
'entercode',
'entersymbol',
+ 'entryanims',
+ 'entrytexts',
'eraseoldobs',
'error',
'errormessage1',
@@ -430,6 +436,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'getroomspaths',
'gettime',
'gettingshot',
+ 'getundercentre',
'getundermenu',
'getundertimed',
'getunderzoom',
@@ -601,12 +608,15 @@ generator = cpp(context, "DreamGen", blacklist = [
'printslow',
'printsprites',
'printundermon',
+ 'processtrigger',
'putbackobstuff',
+ 'putundercentre',
'putundermenu',
'putundertimed',
'putunderzoom',
'quickquit',
'quickquit2',
+ 'quitkey',
'quitsymbol',
'random',
'randomaccess',
@@ -633,6 +643,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'reelsonscreen',
'reexfromopen',
'removeemm',
+ 'removefreeobject',
'removesetobject',
'resetkeyboard',
'restoreall',
@@ -642,6 +653,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'rollendcredits',
'rollendcredits2',
'roomname',
+ 'runtap',
'runintroseq',
'saveems',
'savefileread',
@@ -656,6 +668,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'security',
'seecommandtail',
'selectlocation',
+ 'selectslot',
'selectslot2',
'set16colpalette',
'setallchanges',
@@ -671,6 +684,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'setupemm',
'setuppit',
'setuptimedtemp',
+ 'setuptimeduse',
'setwalk',
'showallex',
'showallfree',
@@ -754,6 +768,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'transferinv',
'transfertext',
'trapdoor',
+ 'triggermessage',
'trysoundalloc',
'turnanypathoff',
'turnanypathon',
@@ -763,6 +778,9 @@ generator = cpp(context, "DreamGen", blacklist = [
'twodigitnum',
'undertextline',
'updatepeople',
+ 'updatesymboltop',
+ 'updatesymbolbot',
+ 'useaxe',
'usebalcony',
'usebuttona',
'usecardreader1',
@@ -773,6 +791,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'usechurchgate',
'usechurchhole',
'useclearbox',
+ 'usecontrol',
'usecooker',
'usecoveredbox',
'usediary',
@@ -785,6 +804,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'useelvdoor',
'usefullcart',
'usehole',
+ 'usekey',
'useladder',
'useladderb',
'uselighter',
@@ -792,12 +812,15 @@ generator = cpp(context, "DreamGen", blacklist = [
'usemenu',
'usemon',
'useobject',
+ 'useopenbox',
+ 'usepipe',
'useplate',
'useplinth',
'usepoolreader',
'userailing',
'useroutine',
'useshield',
+ 'useslab',
'usetempcharset',
'usetext',
'usetimedtext',
@@ -805,6 +828,7 @@ generator = cpp(context, "DreamGen", blacklist = [
'usewall',
'usewinch',
'usewindow',
+ 'usewire',
'viewfolder',
'vsync',
'volumeadjust',
diff --git a/engines/agi/objects.cpp b/engines/agi/objects.cpp
index 94eef92579..447cff2a3f 100644
--- a/engines/agi/objects.cpp
+++ b/engines/agi/objects.cpp
@@ -52,7 +52,7 @@ int AgiEngine::decodeObjects(uint8 *mem, uint32 flen) {
// alloc memory for object list
// byte 3 = number of animated objects. this is ignored.. ??
- if (READ_LE_UINT16(mem) / padsize >= 256) {
+ if (READ_LE_UINT16(mem) / padsize > 256) {
// die with no error! AGDS game needs not to die to work!! :(
return errOK;
}
diff --git a/engines/dreamweb/dreambase.h b/engines/dreamweb/dreambase.h
index 3d5c9ce88b..c7e9546069 100644
--- a/engines/dreamweb/dreambase.h
+++ b/engines/dreamweb/dreambase.h
@@ -115,6 +115,7 @@ public:
const Frame *getReelFrameAX(uint16 frame);
void soundOnReels(uint16 reelPointer);
void rollEndCredits();
+ void priestText(ReelRoutine &routine);
// from stubs.cpp
void crosshair();
@@ -154,6 +155,7 @@ public:
// from use.cpp
void placeFreeObject(uint8 index);
void removeFreeObject(uint8 index);
+ void setupTimedUse(uint16 offset, uint16 countToTimed, uint16 timeCount, byte x, byte y);
// from vgafades.cpp
uint8 *mainPalette();
@@ -182,6 +184,10 @@ public:
inline uint8 *workspace() { return _workspace; }
void clearWork();
+ uint8 getLocation(uint8 index);
+ void setLocation(uint8 index);
+ void getUnderCentre();
+ void putUnderCentre();
uint8 *mapStore();
void panelToMap();
void mapToPanel();
@@ -209,6 +215,7 @@ public:
void createPanel();
void createPanel2();
void showPanel();
+ void entryTexts();
};
diff --git a/engines/dreamweb/dreamgen.cpp b/engines/dreamweb/dreamgen.cpp
index 7276445b7f..63942575bf 100644
--- a/engines/dreamweb/dreamgen.cpp
+++ b/engines/dreamweb/dreamgen.cpp
@@ -2821,28 +2821,6 @@ _tmp2:
workToScreenM();
}
-void DreamGenContext::getUnderCentre() {
- STACK_CHECK;
- di = 58;
- bx = 72;
- ds = data.word(kMapstore);
- si = 0;
- cl = 254;
- ch = 110;
- multiGet();
-}
-
-void DreamGenContext::putUnderCentre() {
- STACK_CHECK;
- di = 58;
- bx = 72;
- ds = data.word(kMapstore);
- si = 0;
- cl = 254;
- ch = 110;
- multiPut();
-}
-
void DreamGenContext::locationPic() {
STACK_CHECK;
getDestInfo();
@@ -2898,14 +2876,14 @@ void DreamGenContext::getDestInfo() {
push(ax);
dx = data;
es = dx;
- si = 1249;
+ si = 1244;
_add(si, ax);
cl = es.byte(si);
ax = pop();
push(cx);
dx = data;
es = dx;
- si = 1265;
+ si = 1260;
_add(si, ax);
ax = pop();
}
@@ -2957,7 +2935,7 @@ clearedlocations:
bx = ax;
dx = data;
es = dx;
- _add(bx, 1249);
+ _add(bx, 1244);
es.byte(bx) = 0;
}
@@ -2993,7 +2971,7 @@ void DreamGenContext::execCommand() {
es = cs;
bx = offset_comlist;
ds = cs;
- si = 1283;
+ si = 1278;
al = ds.byte(si);
_cmp(al, 0);
if (!flags.z())
@@ -3086,7 +3064,7 @@ dirroot:
si = offset_rootdir;
_inc(si);
es = cs;
- di = 1125;
+ di = 1120;
_inc(di);
cx = 12;
_movsb(cx, true);
@@ -3188,7 +3166,7 @@ notyetassigned:
push(bx);
_add(bx, 2);
ds = cs;
- si = 1283;
+ si = 1278;
checkpass:
_lodsw();
ah = es.byte(bx);
@@ -3259,7 +3237,7 @@ void DreamGenContext::read() {
return;
okcom:
es = cs;
- di = 1125;
+ di = 1120;
ax = data.word(kTextfile1);
data.word(kMonsource) = ax;
ds = ax;
@@ -3389,7 +3367,7 @@ keyok2:
ds = cs;
si = offset_operand1+1;
es = cs;
- di = 1125+1;
+ di = 1120+1;
cx = 12;
_movsb(cx, true);
monitorLogo();
@@ -3516,7 +3494,7 @@ void DreamGenContext::parser() {
al = '=';
_stosb();
ds = cs;
- si = 1283;
+ si = 1278;
notspace1:
_lodsw();
_cmp(al, 32);
@@ -3544,117 +3522,6 @@ finishpars:
di = offset_operand1;
}
-void DreamGenContext::processTrigger() {
- STACK_CHECK;
- _cmp(data.byte(kLasttrigger), '1');
- if (!flags.z())
- goto notfirsttrigger;
- al = 8;
- setLocation();
- al = 45;
- triggerMessage();
- return;
-notfirsttrigger:
- _cmp(data.byte(kLasttrigger), '2');
- if (!flags.z())
- goto notsecondtrigger;
- al = 9;
- setLocation();
- al = 55;
- triggerMessage();
- return;
-notsecondtrigger:
- _cmp(data.byte(kLasttrigger), '3');
- if (!flags.z())
- return /* (notthirdtrigger) */;
- al = 2;
- setLocation();
- al = 59;
- triggerMessage();
-}
-
-void DreamGenContext::triggerMessage() {
- STACK_CHECK;
- push(ax);
- di = 174;
- bx = 153;
- cl = 200;
- ch = 63;
- ds = data.word(kMapstore);
- si = 0;
- multiGet();
- ax = pop();
- findPuzText();
- di = 174;
- bx = 156;
- dl = 141;
- ah = 16;
- printDirect();
- cx = 140;
- hangOn();
- workToScreen();
- cx = 340;
- hangOn();
- di = 174;
- bx = 153;
- cl = 200;
- ch = 63;
- ds = data.word(kMapstore);
- si = 0;
- multiPut();
- workToScreen();
- data.byte(kLasttrigger) = 0;
-}
-
-void DreamGenContext::runTap() {
- STACK_CHECK;
- _cmp(data.byte(kWithobject), 255);
- if (!flags.z())
- goto tapwith;
- withWhat();
- return;
-tapwith:
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'C';
- ch = 'U';
- dl = 'P';
- dh = 'E';
- compare();
- if (flags.z())
- goto fillcupfromtap;
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'C';
- ch = 'U';
- dl = 'P';
- dh = 'F';
- compare();
- if (flags.z())
- goto cupfromtapfull;
- cx = 300;
- al = 56;
- showPuzText();
- putBackObStuff();
- return;
-fillcupfromtap:
- al = data.byte(kWithobject);
- getExAd();
- es.byte(bx+15) = 'F'-'A';
- al = 8;
- playChannel1();
- cx = 300;
- al = 57;
- showPuzText();
- putBackObStuff();
- return;
-cupfromtapfull:
- cx = 300;
- al = 58;
- showPuzText();
- putBackObStuff();
-}
-
void DreamGenContext::notHeldError() {
STACK_CHECK;
createPanel();
@@ -3674,155 +3541,6 @@ void DreamGenContext::notHeldError() {
putBackObStuff();
}
-void DreamGenContext::usePipe() {
- STACK_CHECK;
- _cmp(data.byte(kWithobject), 255);
- if (!flags.z())
- goto pipewith;
- withWhat();
- return;
-pipewith:
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'C';
- ch = 'U';
- dl = 'P';
- dh = 'E';
- compare();
- if (flags.z())
- goto fillcup;
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'C';
- ch = 'U';
- dl = 'P';
- dh = 'F';
- compare();
- if (flags.z())
- goto alreadyfull;
- cx = 300;
- al = 14;
- showPuzText();
- putBackObStuff();
- return;
-fillcup:
- cx = 300;
- al = 36;
- showPuzText();
- putBackObStuff();
- al = data.byte(kWithobject);
- getExAd();
- es.byte(bx+15) = 'F'-'A';
- return;
-alreadyfull:
- cx = 300;
- al = 35;
- showPuzText();
- putBackObStuff();
-}
-
-void DreamGenContext::useSLab() {
- STACK_CHECK;
- _cmp(data.byte(kWithobject), 255);
- if (!flags.z())
- goto slabwith;
- withWhat();
- return;
-slabwith:
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'J';
- ch = 'E';
- dl = 'W';
- dh = 'L';
- compare();
- if (flags.z())
- goto nextslab;
- cx = 300;
- al = 14;
- showPuzText();
- putBackObStuff();
- return;
-nextslab:
- al = data.byte(kWithobject);
- getExAd();
- es.byte(bx+2) = 0;
- al = data.byte(kCommand);
- push(ax);
- removeSetObject();
- ax = pop();
- _inc(al);
- push(ax);
- placeSetObject();
- ax = pop();
- _cmp(al, 54);
- if (!flags.z())
- goto notlastslab;
- al = 0;
- turnPathOn();
- data.word(kWatchingtime) = 22;
- data.word(kReeltowatch) = 35;
- data.word(kEndwatchreel) = 48;
- data.byte(kWatchspeed) = 1;
- data.byte(kSpeedcount) = 1;
-notlastslab:
- _inc(data.byte(kProgresspoints));
- showFirstUse();
- data.byte(kGetback) = 1;
-}
-
-void DreamGenContext::useOpenBox() {
- STACK_CHECK;
- _cmp(data.byte(kWithobject), 255);
- if (!flags.z())
- goto openboxwith;
- withWhat();
- return;
-openboxwith:
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'C';
- ch = 'U';
- dl = 'P';
- dh = 'F';
- compare();
- if (flags.z())
- goto destoryopenbox;
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'C';
- ch = 'U';
- dl = 'P';
- dh = 'E';
- compare();
- if (flags.z())
- goto openboxwrong;
- showFirstUse();
- return;
-destoryopenbox:
- _inc(data.byte(kProgresspoints));
- cx = 300;
- al = 37;
- showPuzText();
- al = data.byte(kWithobject);
- getExAd();
- es.byte(bx+15) = 'E'-'A';
- data.word(kWatchingtime) = 140;
- data.word(kReeltowatch) = 105;
- data.word(kEndwatchreel) = 181;
- data.byte(kWatchspeed) = 1;
- data.byte(kSpeedcount) = 1;
- al = 4;
- turnPathOn();
- data.byte(kGetback) = 1;
- return;
-openboxwrong:
- cx = 300;
- al = 38;
- showPuzText();
- putBackObStuff();
-}
-
void DreamGenContext::useAltar() {
STACK_CHECK;
al = 'C';
@@ -4039,151 +3757,6 @@ numberpoke3:
cs.byte(bx) = al;
}
-void DreamGenContext::useControl() {
- STACK_CHECK;
- _cmp(data.byte(kWithobject), 255);
- if (!flags.z())
- goto gotcontrolwith;
- withWhat();
- return;
-gotcontrolwith:
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'K';
- ch = 'E';
- dl = 'Y';
- dh = 'A';
- compare();
- if (flags.z())
- goto rightkey;
- _cmp(data.byte(kReallocation), 21);
- if (!flags.z())
- goto balls;
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'K';
- ch = 'N';
- dl = 'F';
- dh = 'E';
- compare();
- if (flags.z())
- goto jimmycontrols;
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'A';
- ch = 'X';
- dl = 'E';
- dh = 'D';
- compare();
- if (flags.z())
- goto axeoncontrols;
-balls:
- showFirstUse();
- putBackObStuff();
- return;
-rightkey:
- al = 16;
- playChannel1();
- _cmp(data.byte(kLocation), 21);
- if (flags.z())
- goto goingdown;
- cx = 300;
- al = 0;
- showPuzText();
- data.byte(kNewlocation) = 21;
- data.byte(kCounttoclose) = 8;
- data.byte(kCounttoopen) = 0;
- data.word(kWatchingtime) = 80;
- data.byte(kGetback) = 1;
- return;
-goingdown:
- cx = 300;
- al = 3;
- showPuzText();
- data.byte(kNewlocation) = 30;
- data.byte(kCounttoclose) = 8;
- data.byte(kCounttoopen) = 0;
- data.word(kWatchingtime) = 80;
- data.byte(kGetback) = 1;
- return;
-jimmycontrols:
- al = 50;
- placeSetObject();
- al = 51;
- placeSetObject();
- al = 26;
- placeSetObject();
- al = 30;
- placeSetObject();
- al = 16;
- removeSetObject();
- al = 17;
- removeSetObject();
- al = 14;
- playChannel1();
- cx = 300;
- al = 10;
- showPuzText();
- _inc(data.byte(kProgresspoints));
- data.byte(kGetback) = 1;
- return;
-axeoncontrols:
- cx = 300;
- al = 16;
- showPuzText();
- _inc(data.byte(kProgresspoints));
- putBackObStuff();
-}
-
-void DreamGenContext::useWire() {
- STACK_CHECK;
- _cmp(data.byte(kWithobject), 255);
- if (!flags.z())
- goto gotwirewith;
- withWhat();
- return;
-gotwirewith:
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'K';
- ch = 'N';
- dl = 'F';
- dh = 'E';
- compare();
- if (flags.z())
- goto wireknife;
- al = data.byte(kWithobject);
- ah = data.byte(kWithtype);
- cl = 'A';
- ch = 'X';
- dl = 'E';
- dh = 'D';
- compare();
- if (flags.z())
- goto wireaxe;
- cx = 300;
- al = 14;
- showPuzText();
- putBackObStuff();
- return;
-wireaxe:
- cx = 300;
- al = 16;
- showPuzText();
- putBackObStuff();
- return;
-wireknife:
- al = 51;
- removeSetObject();
- al = 52;
- placeSetObject();
- cx = 300;
- al = 11;
- showPuzText();
- _inc(data.byte(kProgresspoints));
- data.byte(kGetback) = 1;
-}
-
void DreamGenContext::useHandle() {
STACK_CHECK;
al = 'C';
@@ -4208,58 +3781,6 @@ havecutwire:
data.byte(kGetback) = 1;
}
-void DreamGenContext::useKey() {
- STACK_CHECK;
- _cmp(data.byte(kLocation), 5);
- if (flags.z())
- goto usekey1;
- _cmp(data.byte(kLocation), 30);
- if (flags.z())
- goto usekey1;
- _cmp(data.byte(kLocation), 21);
- if (flags.z())
- goto usekey2;
- cx = 200;
- al = 1;
- showPuzText();
- putBackObStuff();
- return;
-usekey1:
- _cmp(data.byte(kMapx), 22);
- if (!flags.z())
- goto wrongroom1;
- _cmp(data.byte(kMapy), 10);
- if (!flags.z())
- goto wrongroom1;
- cx = 300;
- al = 0;
- showPuzText();
- data.byte(kCounttoclose) = 100;
- data.byte(kGetback) = 1;
- return;
-usekey2:
- _cmp(data.byte(kMapx), 11);
- if (!flags.z())
- goto wrongroom1;
- _cmp(data.byte(kMapy), 10);
- if (!flags.z())
- goto wrongroom1;
- cx = 300;
- al = 3;
- showPuzText();
- data.byte(kNewlocation) = 30;
- al = 2;
- fadeScreenDown();
- showFirstUse();
- putBackObStuff();
- return;
-wrongroom1:
- cx = 200;
- al = 2;
- showPuzText();
- putBackObStuff();
-}
-
void DreamGenContext::useStereo() {
STACK_CHECK;
_cmp(data.byte(kLocation), 0);
@@ -4322,37 +3843,6 @@ stereoon:
putBackObStuff();
}
-void DreamGenContext::useAxe() {
- STACK_CHECK;
- _cmp(data.byte(kReallocation), 22);
- if (!flags.z())
- goto notinpool;
- _cmp(data.byte(kMapy), 10);
- if (flags.z())
- goto axeondoor;
- showSecondUse();
- _inc(data.byte(kProgresspoints));
- data.byte(kLastweapon) = 2;
- data.byte(kGetback) = 1;
- removeObFromInv();
- return;
-notinpool:
- showFirstUse();
- return;
-/*continuing to unbounded code: axeondoor from useelvdoor:19-30*/
-axeondoor:
- al = 15;
- cx = 300;
- showPuzText();
- _inc(data.byte(kProgresspoints));
- data.word(kWatchingtime) = 46*2;
- data.word(kReeltowatch) = 31;
- data.word(kEndwatchreel) = 77;
- data.byte(kWatchspeed) = 1;
- data.byte(kSpeedcount) = 1;
- data.byte(kGetback) = 1;
-}
-
void DreamGenContext::withWhat() {
STACK_CHECK;
createPanel();
@@ -4570,108 +4060,6 @@ void DreamGenContext::findPuzText() {
si = ax;
}
-void DreamGenContext::removeFreeObject() {
- STACK_CHECK;
- push(es);
- push(bx);
- getFreeAd();
- es.byte(bx+2) = 255;
- bx = pop();
- es = pop();
-}
-
-void DreamGenContext::autoAppear() {
- STACK_CHECK;
- _cmp(data.byte(kLocation), 32);
- if (!flags.z())
- goto notinalley;
- al = 5;
- resetLocation();
- al = 10;
- setLocation();
- data.byte(kDestpos) = 10;
- return;
-notinalley:
- _cmp(data.byte(kReallocation), 24);
- if (!flags.z())
- goto notinedens;
- _cmp(data.byte(kGeneraldead), 1);
- if (!flags.z())
- goto edenspart2;
- _inc(data.byte(kGeneraldead));
- al = 44;
- placeSetObject();
- al = 18;
- placeSetObject();
- al = 93;
- placeSetObject();
- al = 92;
- removeSetObject();
- al = 55;
- removeSetObject();
- al = 75;
- removeSetObject();
- al = 84;
- removeSetObject();
- al = 85;
- removeSetObject();
- return;
-edenspart2:
- _cmp(data.byte(kSartaindead), 1);
- if (!flags.z())
- return /* (notedens2) */;
- al = 44;
- removeSetObject();
- al = 93;
- removeSetObject();
- al = 55;
- placeSetObject();
- _inc(data.byte(kSartaindead));
- return;
-notinedens:
- _cmp(data.byte(kReallocation), 25);
- if (!flags.z())
- goto notonsartroof;
- data.byte(kNewsitem) = 3;
- al = 6;
- resetLocation();
- al = 11;
- setLocation();
- data.byte(kDestpos) = 11;
- return;
-notonsartroof:
- _cmp(data.byte(kReallocation), 2);
- if (!flags.z())
- return /* (notinlouiss) */;
- _cmp(data.byte(kRockstardead), 0);
- if (flags.z())
- return /* (notinlouiss) */;
- al = 23;
- placeSetObject();
-}
-
-void DreamGenContext::setupTimedUse() {
- STACK_CHECK;
- _cmp(data.word(kTimecount), 0);
- if (!flags.z())
- return /* (cantsetup) */;
- data.byte(kTimedy) = bh;
- data.byte(kTimedx) = bl;
- data.word(kCounttotimed) = cx;
- _add(dx, cx);
- data.word(kTimecount) = dx;
- bl = al;
- bh = 0;
- _add(bx, bx);
- es = data.word(kPuzzletext);
- cx = (66*2);
- ax = es.word(bx);
- _add(ax, cx);
- bx = ax;
- data.word(kTimedseg) = es;
- data.word(kTimedoffset) = bx;
-}
-
void DreamGenContext::useGun() {
STACK_CHECK;
_cmp(data.byte(kObjecttype), 4);
@@ -4849,115 +4237,6 @@ nottvsoldier:
putBackObStuff();
}
-void DreamGenContext::quitKey() {
- STACK_CHECK;
- _cmp(data.byte(kCommandtype), 222);
- if (flags.z())
- goto alreadyqk;
- data.byte(kCommandtype) = 222;
- al = 4;
- commandOnly();
-alreadyqk:
- ax = data.word(kMousebutton);
- _cmp(ax, data.word(kOldbutton));
- if (flags.z())
- return /* (notqk) */;
- _and(ax, 1);
- if (!flags.z())
- goto doqk;
- return;
-doqk:
- data.byte(kGetback) = 1;
-}
-
-void DreamGenContext::updateSymbolTop() {
- STACK_CHECK;
- _cmp(data.byte(kSymboltopdir), 0);
- if (flags.z())
- return /* (topfinished) */;
- _cmp(data.byte(kSymboltopdir), -1);
- if (flags.z())
- goto backwards;
- _inc(data.byte(kSymboltopx));
- _cmp(data.byte(kSymboltopx), 49);
- if (!flags.z())
- goto notwrapfor;
- data.byte(kSymboltopx) = 0;
- _dec(data.byte(kSymboltopnum));
- _cmp(data.byte(kSymboltopnum), -1);
- if (!flags.z())
- return /* (topfinished) */;
- data.byte(kSymboltopnum) = 5;
- return;
-notwrapfor:
- _cmp(data.byte(kSymboltopx), 24);
- if (!flags.z())
- return /* (topfinished) */;
- data.byte(kSymboltopdir) = 0;
- return;
-backwards:
- _dec(data.byte(kSymboltopx));
- _cmp(data.byte(kSymboltopx), -1);
- if (!flags.z())
- goto notwrapback;
- data.byte(kSymboltopx) = 48;
- _inc(data.byte(kSymboltopnum));
- _cmp(data.byte(kSymboltopnum), 6);
- if (!flags.z())
- return /* (topfinished) */;
- data.byte(kSymboltopnum) = 0;
- return;
-notwrapback:
- _cmp(data.byte(kSymboltopx), 24);
- if (!flags.z())
- return /* (topfinished) */;
- data.byte(kSymboltopdir) = 0;
-}
-
-void DreamGenContext::updateSymbolBot() {
- STACK_CHECK;
- _cmp(data.byte(kSymbolbotdir), 0);
- if (flags.z())
- return /* (botfinished) */;
- _cmp(data.byte(kSymbolbotdir), -1);
- if (flags.z())
- goto backwardsbot;
- _inc(data.byte(kSymbolbotx));
- _cmp(data.byte(kSymbolbotx), 49);
- if (!flags.z())
- goto notwrapforb;
- data.byte(kSymbolbotx) = 0;
- _dec(data.byte(kSymbolbotnum));
- _cmp(data.byte(kSymbolbotnum), -1);
- if (!flags.z())
- return /* (botfinished) */;
- data.byte(kSymbolbotnum) = 5;
- return;
-notwrapforb:
- _cmp(data.byte(kSymbolbotx), 24);
- if (!flags.z())
- return /* (botfinished) */;
- data.byte(kSymbolbotdir) = 0;
- return;
-backwardsbot:
- _dec(data.byte(kSymbolbotx));
- _cmp(data.byte(kSymbolbotx), -1);
- if (!flags.z())
- goto notwrapbackb;
- data.byte(kSymbolbotx) = 48;
- _inc(data.byte(kSymbolbotnum));
- _cmp(data.byte(kSymbolbotnum), 6);
- if (!flags.z())
- return /* (botfinished) */;
- data.byte(kSymbolbotnum) = 0;
- return;
-notwrapbackb:
- _cmp(data.byte(kSymbolbotx), 24);
- if (!flags.z())
- return /* (botfinished) */;
- data.byte(kSymbolbotdir) = 0;
-}
-
void DreamGenContext::showDiaryKeys() {
STACK_CHECK;
_cmp(data.byte(kPresscount), 0);
@@ -5106,58 +4385,6 @@ void DreamGenContext::findText1() {
si = ax;
}
-void DreamGenContext::selectSlot() {
- STACK_CHECK;
- _cmp(data.byte(kCommandtype), 244);
- if (flags.z())
- goto alreadysel;
- data.byte(kCommandtype) = 244;
- al = 45;
- commandOnly();
-alreadysel:
- ax = data.word(kMousebutton);
- _cmp(ax, 1);
- if (!flags.z())
- return /* (noselslot) */;
- _cmp(ax, data.word(kOldbutton));
- if (flags.z())
- return /* (noselslot) */;
- _cmp(data.byte(kLoadingorsave), 3);
- if (!flags.z())
- goto notnocurs;
- _dec(data.byte(kLoadingorsave));
-notnocurs:
- oldToNames();
- ax = data.word(kMousey);
- _sub(ax, (52)+4);
- cl = -1;
-getslotnum:
- _inc(cl);
- _sub(ax, 11);
- if (!flags.c())
- goto getslotnum;
- data.byte(kCurrentslot) = cl;
- delPointer();
- showOpBox();
- showSlots();
- showNames();
- _cmp(data.byte(kLoadingorsave), 1);
- if (flags.z())
- goto isloadmode;
- showSaveOps();
- readMouse();
- showPointer();
- workToScreen();
- delPointer();
- return;
-isloadmode:
- showLoadOps();
- readMouse();
- showPointer();
- workToScreen();
- delPointer();
-}
-
void DreamGenContext::showSlots() {
STACK_CHECK;
di = (60)+7;
@@ -5191,220 +4418,10 @@ nomatchslot:
goto slotloop;
}
-void DreamGenContext::entryTexts() {
- STACK_CHECK;
- _cmp(data.byte(kLocation), 21);
- if (!flags.z())
- goto notloc15;
- al = 28;
- cx = 60;
- dx = 11;
- bl = 68;
- bh = 64;
- setupTimedUse();
- return;
-notloc15:
- _cmp(data.byte(kLocation), 30);
- if (!flags.z())
- goto notloc43;
- al = 27;
- cx = 60;
- dx = 11;
- bl = 68;
- bh = 64;
- setupTimedUse();
- return;
-notloc43:
- _cmp(data.byte(kLocation), 23);
- if (!flags.z())
- goto notloc23;
- al = 29;
- cx = 60;
- dx = 11;
- bl = 68;
- bh = 64;
- setupTimedUse();
- return;
-notloc23:
- _cmp(data.byte(kLocation), 31);
- if (!flags.z())
- goto notloc44;
- al = 30;
- cx = 60;
- dx = 11;
- bl = 68;
- bh = 64;
- setupTimedUse();
- return;
-notloc44:
- _cmp(data.byte(kLocation), 20);
- if (!flags.z())
- goto notsarters2;
- al = 31;
- cx = 60;
- dx = 11;
- bl = 68;
- bh = 64;
- setupTimedUse();
- return;
-notsarters2:
- _cmp(data.byte(kLocation), 24);
- if (!flags.z())
- goto notedenlob;
- al = 32;
- cx = 60;
- dx = 3;
- bl = 68;
- bh = 64;
- setupTimedUse();
- return;
-notedenlob:
- _cmp(data.byte(kLocation), 34);
- if (!flags.z())
- return /* (noteden2) */;
- al = 33;
- cx = 60;
- dx = 3;
- bl = 68;
- bh = 64;
- setupTimedUse();
-}
-
-void DreamGenContext::entryAnims() {
- STACK_CHECK;
- data.word(kReeltowatch) = -1;
- data.byte(kWatchmode) = -1;
- _cmp(data.byte(kLocation), 33);
- if (!flags.z())
- goto notinthebeach;
- switchRyanOff();
- data.word(kWatchingtime) = 76*2;
- data.word(kReeltowatch) = 0;
- data.word(kEndwatchreel) = 76;
- data.byte(kWatchspeed) = 1;
- data.byte(kSpeedcount) = 1;
- return;
-notinthebeach:
- _cmp(data.byte(kLocation), 44);
- if (!flags.z())
- goto notsparkys;
- al = 8;
- resetLocation();
- data.word(kWatchingtime) = 50*2;
- data.word(kReeltowatch) = 247;
- data.word(kEndwatchreel) = 297;
- data.byte(kWatchspeed) = 1;
- data.byte(kSpeedcount) = 1;
- switchRyanOff();
- return;
-notsparkys:
- _cmp(data.byte(kLocation), 22);
- if (!flags.z())
- goto notinthelift;
- data.word(kWatchingtime) = 31*2;
- data.word(kReeltowatch) = 0;
- data.word(kEndwatchreel) = 30;
- data.byte(kWatchspeed) = 1;
- data.byte(kSpeedcount) = 1;
- switchRyanOff();
- return;
-notinthelift:
- _cmp(data.byte(kLocation), 26);
- if (!flags.z())
- goto notunderchurch;
- data.byte(kSymboltopnum) = 2;
- data.byte(kSymbolbotnum) = 1;
- return;
-notunderchurch:
- _cmp(data.byte(kLocation), 45);
- if (!flags.z())
- goto notenterdream;
- data.byte(kKeeperflag) = 0;
- data.word(kWatchingtime) = 296;
- data.word(kReeltowatch) = 45;
- data.word(kEndwatchreel) = 198;
- data.byte(kWatchspeed) = 1;
- data.byte(kSpeedcount) = 1;
- switchRyanOff();
- return;
-notenterdream:
- _cmp(data.byte(kReallocation), 46);
- if (!flags.z())
- goto notcrystal;
- _cmp(data.byte(kSartaindead), 1);
- if (!flags.z())
- goto notcrystal;
- al = 0;
- removeFreeObject();
- return;
-notcrystal:
- _cmp(data.byte(kLocation), 9);
- if (!flags.z())
- goto nottopchurch;
- al = 2;
- checkIfPathIsOn();
- if (flags.z())
- goto nottopchurch;
- _cmp(data.byte(kAidedead), 0);
- if (flags.z())
- goto nottopchurch;
- al = 3;
- checkIfPathIsOn();
- if (!flags.z())
- goto makedoorsopen;
- al = 2;
- turnPathOn();
-makedoorsopen:
- al = 4;
- removeSetObject();
- al = 5;
- placeSetObject();
- return;
-nottopchurch:
- _cmp(data.byte(kLocation), 47);
- if (!flags.z())
- goto notdreamcentre;
- al = 4;
- placeSetObject();
- al = 5;
- placeSetObject();
- return;
-notdreamcentre:
- _cmp(data.byte(kLocation), 38);
- if (!flags.z())
- goto notcarpark;
- data.word(kWatchingtime) = 57*2;
- data.word(kReeltowatch) = 4;
- data.word(kEndwatchreel) = 57;
- data.byte(kWatchspeed) = 1;
- data.byte(kSpeedcount) = 1;
- switchRyanOff();
- return;
-notcarpark:
- _cmp(data.byte(kLocation), 32);
- if (!flags.z())
- goto notalley;
- data.word(kWatchingtime) = 66*2;
- data.word(kReeltowatch) = 0;
- data.word(kEndwatchreel) = 66;
- data.byte(kWatchspeed) = 1;
- data.byte(kSpeedcount) = 1;
- switchRyanOff();
- return;
-notalley:
- _cmp(data.byte(kLocation), 24);
- if (!flags.z())
- return /* (notedensagain) */;
- al = 2;
- ah = data.byte(kRoomnum);
- _dec(ah);
- turnAnyPathOn();
-}
-
void DreamGenContext::clearBuffers() {
STACK_CHECK;
es = data.word(kBuffers);
- cx = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+916-459+68-0)/2;
+ cx = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+911-454+68-0)/2;
ax = 0;
di = 0;
_stosw(cx, true);
@@ -5416,11 +4433,11 @@ void DreamGenContext::clearBuffers() {
es = data.word(kBuffers);
di = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64));
ds = cs;
- si = 459;
- cx = (916-459);
+ si = 454;
+ cx = (911-454);
_movsb(cx, true);
es = data.word(kBuffers);
- di = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+916-459);
+ di = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+911-454);
ds = cs;
si = 0;
cx = (68-0);
@@ -5438,11 +4455,11 @@ void DreamGenContext::clearChanges() {
ds = data.word(kBuffers);
si = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64));
es = cs;
- di = 459;
- cx = (916-459);
+ di = 454;
+ cx = (911-454);
_movsb(cx, true);
ds = data.word(kBuffers);
- si = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+916-459);
+ si = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+911-454);
es = cs;
di = 0;
cx = (68-0);
@@ -5456,7 +4473,7 @@ void DreamGenContext::clearChanges() {
di = 0;
_stosw(cx, true);
es = cs;
- di = 1249;
+ di = 1244;
al = 1;
_stosb(2);
al = 0;
@@ -5703,111 +4720,111 @@ void DreamGenContext::__start() {
//0x0190: .... .... .... ....
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//0x01a0: .... .... .... ....
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
//0x01b0: .... .... .... ....
- 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x2c, 0x00, 0x14, 0x00,
- //0x01c0: .... .... .... ,...
- 0x02, 0x00, 0x01, 0x01, 0x37, 0x00, 0x00, 0x00, 0x32, 0x14, 0x00, 0x18, 0x16, 0x00, 0x4a, 0x00,
- //0x01d0: .... 7... 2... ..J.
- 0x01, 0x00, 0x00, 0x18, 0x21, 0x0a, 0x4b, 0x00, 0x01, 0x00, 0x01, 0x01, 0x2c, 0x00, 0x1b, 0x00,
- //0x01e0: .... !.K. .... ,...
- 0x02, 0x00, 0x02, 0x01, 0x2c, 0x00, 0x60, 0x00, 0x03, 0x00, 0x04, 0x01, 0x2c, 0x00, 0x76, 0x00,
- //0x01f0: .... ,.`. .... ,.v.
- 0x02, 0x00, 0x05, 0x01, 0x2c, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x16, 0x14, 0x35, 0x00,
- //0x0200: .... ,... .... ..5.
- 0x03, 0x00, 0x00, 0x05, 0x16, 0x14, 0x28, 0x00, 0x01, 0x00, 0x02, 0x05, 0x16, 0x14, 0x32, 0x00,
- //0x0210: .... ..(. .... ..2.
- 0x01, 0x00, 0x03, 0x02, 0x0b, 0x0a, 0xc0, 0x00, 0x01, 0x00, 0x00, 0x02, 0x0b, 0x0a, 0xb6, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x2c, 0x00, 0x14, 0x00, 0x02, 0x00, 0x01, 0x01, 0x37,
+ //0x01c0: .... ..., .... ...7
+ 0x00, 0x00, 0x00, 0x32, 0x14, 0x00, 0x18, 0x16, 0x00, 0x4a, 0x00, 0x01, 0x00, 0x00, 0x18, 0x21,
+ //0x01d0: ...2 .... .J.. ...!
+ 0x0a, 0x4b, 0x00, 0x01, 0x00, 0x01, 0x01, 0x2c, 0x00, 0x1b, 0x00, 0x02, 0x00, 0x02, 0x01, 0x2c,
+ //0x01e0: .K.. ..., .... ...,
+ 0x00, 0x60, 0x00, 0x03, 0x00, 0x04, 0x01, 0x2c, 0x00, 0x76, 0x00, 0x02, 0x00, 0x05, 0x01, 0x2c,
+ //0x01f0: .`.. ..., .v.. ...,
+ 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x16, 0x14, 0x35, 0x00, 0x03, 0x00, 0x00, 0x05, 0x16,
+ //0x0200: .... .... .5.. ....
+ 0x14, 0x28, 0x00, 0x01, 0x00, 0x02, 0x05, 0x16, 0x14, 0x32, 0x00, 0x01, 0x00, 0x03, 0x02, 0x0b,
+ //0x0210: .(.. .... .2.. ....
+ 0x0a, 0xc0, 0x00, 0x01, 0x00, 0x00, 0x02, 0x0b, 0x0a, 0xb6, 0x00, 0x02, 0x00, 0x01, 0x08, 0x0b,
//0x0220: .... .... .... ....
- 0x02, 0x00, 0x01, 0x08, 0x0b, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x17, 0x00, 0x32, 0x00, 0x00,
- //0x0230: .... .... .... .2..
- 0x03, 0x00, 0x00, 0x1c, 0x0b, 0x14, 0xfa, 0x00, 0x04, 0x00, 0x00, 0x17, 0x00, 0x32, 0x2b, 0x00,
- //0x0240: .... .... .... .2+.
- 0x02, 0x00, 0x08, 0x17, 0x0b, 0x28, 0x82, 0x00, 0x02, 0x00, 0x01, 0x17, 0x16, 0x28, 0x7a, 0x00,
- //0x0250: .... .(.. .... .(z.
- 0x02, 0x00, 0x02, 0x17, 0x16, 0x28, 0x69, 0x00, 0x02, 0x00, 0x03, 0x17, 0x16, 0x28, 0x51, 0x00,
- //0x0260: .... .(i. .... .(Q.
- 0x02, 0x00, 0x04, 0x17, 0x0b, 0x28, 0x87, 0x00, 0x02, 0x00, 0x05, 0x17, 0x16, 0x28, 0x91, 0x00,
- //0x0270: .... .(.. .... .(..
- 0x02, 0x00, 0x06, 0x04, 0x16, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x2d, 0x16, 0x1e, 0xc8, 0x00,
- //0x0280: .... .... ...- ....
- 0x00, 0x00, 0x14, 0x2d, 0x16, 0x1e, 0x27, 0x00, 0x02, 0x00, 0x00, 0x2d, 0x16, 0x1e, 0x19, 0x00,
- //0x0290: ...- ..'. ...- ....
- 0x02, 0x00, 0x00, 0x08, 0x16, 0x28, 0x20, 0x00, 0x02, 0x00, 0x00, 0x07, 0x0b, 0x14, 0x40, 0x00,
- //0x02a0: .... .( . .... ..@.
- 0x02, 0x00, 0x00, 0x16, 0x16, 0x14, 0x52, 0x00, 0x02, 0x00, 0x00, 0x1b, 0x0b, 0x1e, 0x00, 0x00,
- //0x02b0: .... ..R. .... ....
- 0x02, 0x00, 0x00, 0x14, 0x00, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0e, 0x21, 0x28, 0x15, 0x00,
- //0x02c0: .... .... .... !(..
- 0x01, 0x00, 0x00, 0x1d, 0x0b, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x16, 0x00, 0x02, 0x00,
+ 0x0a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x17, 0x00, 0x32, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1c, 0x0b,
+ //0x0230: .... .... 2... ....
+ 0x14, 0xfa, 0x00, 0x04, 0x00, 0x00, 0x17, 0x00, 0x32, 0x2b, 0x00, 0x02, 0x00, 0x08, 0x17, 0x0b,
+ //0x0240: .... .... 2+.. ....
+ 0x28, 0x82, 0x00, 0x02, 0x00, 0x01, 0x17, 0x16, 0x28, 0x7a, 0x00, 0x02, 0x00, 0x02, 0x17, 0x16,
+ //0x0250: (... .... (z.. ....
+ 0x28, 0x69, 0x00, 0x02, 0x00, 0x03, 0x17, 0x16, 0x28, 0x51, 0x00, 0x02, 0x00, 0x04, 0x17, 0x0b,
+ //0x0260: (i.. .... (Q.. ....
+ 0x28, 0x87, 0x00, 0x02, 0x00, 0x05, 0x17, 0x16, 0x28, 0x91, 0x00, 0x02, 0x00, 0x06, 0x04, 0x16,
+ //0x0270: (... .... (... ....
+ 0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x2d, 0x16, 0x1e, 0xc8, 0x00, 0x00, 0x00, 0x14, 0x2d, 0x16,
+ //0x0280: .... ..-. .... ..-.
+ 0x1e, 0x27, 0x00, 0x02, 0x00, 0x00, 0x2d, 0x16, 0x1e, 0x19, 0x00, 0x02, 0x00, 0x00, 0x08, 0x16,
+ //0x0290: .'.. ..-. .... ....
+ 0x28, 0x20, 0x00, 0x02, 0x00, 0x00, 0x07, 0x0b, 0x14, 0x40, 0x00, 0x02, 0x00, 0x00, 0x16, 0x16,
+ //0x02a0: ( .. .... .@.. ....
+ 0x14, 0x52, 0x00, 0x02, 0x00, 0x00, 0x1b, 0x0b, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x14, 0x00,
+ //0x02b0: .R.. .... .... ....
+ 0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0e, 0x21, 0x28, 0x15, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x0b,
+ //0x02c0: .... ...! (... ....
+ 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x16, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
//0x02d0: .... .... .... ....
- 0x02, 0x00, 0x00, 0x19, 0x00, 0x32, 0x04, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16, 0x1e, 0x79, 0x00,
- //0x02e0: .... .2.. ...2 ..y.
- 0x02, 0x00, 0x00, 0x32, 0x16, 0x1e, 0x00, 0x00, 0x14, 0x00, 0x00, 0x34, 0x16, 0x1e, 0xc0, 0x00,
- //0x02f0: ...2 .... ...4 ....
- 0x02, 0x00, 0x00, 0x34, 0x16, 0x1e, 0xe9, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16, 0x28, 0x68, 0x00,
- //0x0300: ...4 .... ...2 .(h.
- 0x37, 0x00, 0x00, 0x35, 0x21, 0x00, 0x63, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16, 0x28, 0x00, 0x00,
- //0x0310: 7..5 !.c. ...2 .(..
- 0x03, 0x00, 0x00, 0x32, 0x16, 0x1e, 0xa2, 0x00, 0x02, 0x00, 0x00, 0x34, 0x16, 0x1e, 0x39, 0x00,
- //0x0320: ...2 .... ...4 ..9.
- 0x02, 0x00, 0x00, 0x34, 0x16, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x48, 0x00,
- //0x0330: ...4 .... ...6 ..H.
- 0x03, 0x00, 0x00, 0x37, 0x2c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00,
- //0x0340: ...7 ,... .... ....
- 0x1c, 0x00, 0x00, 0x0e, 0x16, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x0e, 0x16, 0x00, 0x2c, 0x01,
- //0x0350: .... .... .... ..,.
- 0x01, 0x00, 0x00, 0x0a, 0x16, 0x1e, 0xae, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x16, 0x14, 0x00, 0x00,
+ 0x32, 0x04, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16, 0x1e, 0x79, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16,
+ //0x02e0: 2... ..2. .y.. ..2.
+ 0x1e, 0x00, 0x00, 0x14, 0x00, 0x00, 0x34, 0x16, 0x1e, 0xc0, 0x00, 0x02, 0x00, 0x00, 0x34, 0x16,
+ //0x02f0: .... ..4. .... ..4.
+ 0x1e, 0xe9, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16, 0x28, 0x68, 0x00, 0x37, 0x00, 0x00, 0x35, 0x21,
+ //0x0300: .... ..2. (h.7 ..5!
+ 0x00, 0x63, 0x00, 0x02, 0x00, 0x00, 0x32, 0x16, 0x28, 0x00, 0x00, 0x03, 0x00, 0x00, 0x32, 0x16,
+ //0x0310: .c.. ..2. (... ..2.
+ 0x1e, 0xa2, 0x00, 0x02, 0x00, 0x00, 0x34, 0x16, 0x1e, 0x39, 0x00, 0x02, 0x00, 0x00, 0x34, 0x16,
+ //0x0320: .... ..4. .9.. ..4.
+ 0x1e, 0x00, 0x00, 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x48, 0x00, 0x03, 0x00, 0x00, 0x37, 0x2c,
+ //0x0330: .... ..6. .H.. ..7,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x0e, 0x16,
+ //0x0340: .... .... .... ....
+ 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x0e, 0x16, 0x00, 0x2c, 0x01, 0x01, 0x00, 0x00, 0x0a, 0x16,
+ //0x0350: .... .... .,.. ....
+ 0x1e, 0xae, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x16, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x0b,
//0x0360: .... .... .... ....
- 0x01, 0x00, 0x00, 0x0b, 0x0b, 0x14, 0x00, 0x00, 0x32, 0x14, 0x00, 0x0b, 0x0b, 0x1e, 0x00, 0x00,
- //0x0370: .... .... 2... ....
- 0x32, 0x14, 0x00, 0x0b, 0x16, 0x14, 0x00, 0x00, 0x32, 0x14, 0x00, 0x0e, 0x21, 0x28, 0x00, 0x00,
- //0x0380: 2... .... 2... !(..
- 0x32, 0x14, 0x00, 0xff, 0x44, 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x56, 0x39, 0x39,
- //0x0390: 2... DREA MWEB .V99
- 0x00, 0x00, 0x01, 0x45, 0x58, 0x49, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 0x45, 0x4c,
- //0x03a0: ...E XIT HEL
- 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x49, 0x53, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20,
- //0x03b0: P L IST
- 0x20, 0x52, 0x45, 0x41, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x4f, 0x47, 0x4f, 0x4e,
- //0x03c0: REA D L OGON
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x4b, 0x45, 0x59, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01,
- //0x03d0: KEY S .
- 0x00, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x55, 0x42,
- //0x03e0: .PUB LIC PUB
- 0x4c, 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x42, 0x4c, 0x41, 0x43, 0x4b,
- //0x03f0: LIC ...B LACK
- 0x44, 0x52, 0x41, 0x47, 0x4f, 0x4e, 0x20, 0x52, 0x59, 0x41, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20,
- //0x0400: DRAG ON R YAN
- 0x20, 0x20, 0x00, 0x00, 0x00, 0x48, 0x45, 0x4e, 0x44, 0x52, 0x49, 0x58, 0x20, 0x20, 0x20, 0x20,
- //0x0410: .. .HEN DRIX
- 0x20, 0x4c, 0x4f, 0x55, 0x49, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x53,
- //0x0420: LOU IS ...S
- 0x45, 0x50, 0x54, 0x49, 0x4d, 0x55, 0x53, 0x20, 0x20, 0x20, 0x20, 0x42, 0x45, 0x43, 0x4b, 0x45,
- //0x0430: EPTI MUS B ECKE
- 0x54, 0x54, 0x20, 0x20, 0x20, 0x20, 0x00, 0xff, 0xff, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- //0x0440: TT .. .
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x22, 0x52, 0x4f, 0x4f, 0x54, 0x20, 0x20, 0x20, 0x20,
- //0x0450: ." ROOT
- 0x20, 0x20, 0x20, 0x20, 0x00, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- //0x0460: ."
- 0x20, 0x20, 0x00, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x0d, 0x0a, 0x0d, 0x0a, 0x24,
- //0x0470: .0 000. 00.. ...$
- 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x20, 0x4e, 0x41, 0x4d, 0x45, 0x20, 0x4f, 0x4e, 0x45, 0x20,
- //0x0480: OBJE CT N AME ONE
+ 0x14, 0x00, 0x00, 0x32, 0x14, 0x00, 0x0b, 0x0b, 0x1e, 0x00, 0x00, 0x32, 0x14, 0x00, 0x0b, 0x16,
+ //0x0370: ...2 .... ...2 ....
+ 0x14, 0x00, 0x00, 0x32, 0x14, 0x00, 0x0e, 0x21, 0x28, 0x00, 0x00, 0x32, 0x14, 0x00, 0xff, 0x44,
+ //0x0380: ...2 ...! (..2 ...D
+ 0x52, 0x45, 0x41, 0x4d, 0x57, 0x45, 0x42, 0x2e, 0x56, 0x39, 0x39, 0x00, 0x00, 0x01, 0x45, 0x58,
+ //0x0390: REAM WEB. V99. ..EX
+ 0x49, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 0x45, 0x4c, 0x50, 0x20, 0x20, 0x20, 0x20,
+ //0x03a0: IT HELP
+ 0x20, 0x20, 0x4c, 0x49, 0x53, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x45, 0x41, 0x44,
+ //0x03b0: LI ST READ
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x4f, 0x47, 0x4f, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x03c0: LO GON
+ 0x4b, 0x45, 0x59, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x50, 0x55, 0x42, 0x4c,
+ //0x03d0: KEYS .. PUBL
+ 0x49, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x20,
+ //0x03e0: IC PUBL IC
+ 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x42, 0x4c, 0x41, 0x43, 0x4b, 0x44, 0x52, 0x41, 0x47, 0x4f,
+ //0x03f0: . ..BL ACKD RAGO
+ 0x4e, 0x20, 0x52, 0x59, 0x41, 0x4e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00,
+ //0x0400: N RY AN ...
+ 0x48, 0x45, 0x4e, 0x44, 0x52, 0x49, 0x58, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x4f, 0x55, 0x49,
+ //0x0410: HEND RIX LOUI
+ 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x53, 0x45, 0x50, 0x54, 0x49, 0x4d,
+ //0x0420: S . ..SE PTIM
+ 0x55, 0x53, 0x20, 0x20, 0x20, 0x20, 0x42, 0x45, 0x43, 0x4b, 0x45, 0x54, 0x54, 0x20, 0x20, 0x20,
+ //0x0430: US BE CKET T
+ 0x20, 0x00, 0xff, 0xff, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x0440: ...
+ 0x20, 0x00, 0x22, 0x52, 0x4f, 0x4f, 0x54, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00,
+ //0x0450: ."R OOT .
+ 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x30, 0x30,
+ //0x0460: " .00
+ 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x0d, 0x0a, 0x0d, 0x0a, 0x24, 0x4f, 0x42, 0x4a, 0x45, 0x43,
+ //0x0470: 00.0 0... ..$O BJEC
+ 0x54, 0x20, 0x4e, 0x41, 0x4d, 0x45, 0x20, 0x4f, 0x4e, 0x45, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ //0x0480: T NA ME O NE
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
//0x0490:
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x10, 0x12, 0x12, 0x11, 0x10, 0x10, 0x10,
- //0x04a0: .... ....
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- //0x04b0: .... .... .... ....
- 0x02, 0x44, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- //0x04c0: .D:. .... .... ....
+ 0x20, 0x20, 0x20, 0x00, 0x10, 0x12, 0x12, 0x11, 0x10, 0x10, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01,
+ //0x04a0: . .... .... ....
+ 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x44, 0x3a, 0x00, 0x00,
+ //0x04b0: .... .... .... D:..
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ //0x04c0: .... .... .... ....
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01,
//0x04d0: .... .... .... ....
- 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x02,
//0x04e0: .... .... .... ....
- 0x00, 0x05, 0x00, 0x03, 0x02, 0x04, 0x01, 0x0a, 0x09, 0x08, 0x06, 0x0b, 0x04, 0x07, 0x07, 0x00,
+ 0x04, 0x01, 0x0a, 0x09, 0x08, 0x06, 0x0b, 0x04, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//0x04f0: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//0x0500: .... .... .... ....
@@ -5823,9 +4840,9 @@ void DreamGenContext::__start() {
//0x0550: .... .... .... ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//0x0560: .... .... .... ....
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
//0x0570: .... .... .... ....
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, };
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, };
ds.assign(src, src + sizeof(src));
dreamweb();
}
diff --git a/engines/dreamweb/dreamgen.h b/engines/dreamweb/dreamgen.h
index 3da8d8ecb8..b7fb2495c5 100644
--- a/engines/dreamweb/dreamgen.h
+++ b/engines/dreamweb/dreamgen.h
@@ -32,14 +32,14 @@
namespace DreamGen {
-static const uint16 offset_rootdir = 0x0457;
-static const uint16 offset_money2poke = 0x0478;
-static const uint16 offset_keys = 0x03df;
-static const uint16 offset_money1poke = 0x0473;
-static const uint16 offset_comlist = 0x03a3;
-static const uint16 offset_openchangesize = 0x03a1;
-static const uint16 offset_commandline = 0x0480;
-static const uint16 offset_operand1 = 0x0449;
+static const uint16 offset_money1poke = 0x046e;
+static const uint16 offset_operand1 = 0x0444;
+static const uint16 offset_comlist = 0x039e;
+static const uint16 offset_commandline = 0x047b;
+static const uint16 offset_rootdir = 0x0452;
+static const uint16 offset_money2poke = 0x0473;
+static const uint16 offset_openchangesize = 0x039c;
+static const uint16 offset_keys = 0x03da;
static const uint16 kStartvars = 0;
static const uint16 kProgresspoints = 1;
static const uint16 kWatchon = 2;
@@ -359,32 +359,29 @@ static const uint16 kLinestartx = 431;
static const uint16 kLinestarty = 433;
static const uint16 kLineendx = 435;
static const uint16 kLineendy = 437;
-static const uint16 kIncrement1 = 439;
-static const uint16 kIncrement2 = 441;
-static const uint16 kLineroutine = 443;
-static const uint16 kLinepointer = 444;
-static const uint16 kLinedirection = 445;
-static const uint16 kLinelength = 446;
-static const uint16 kLiftsoundcount = 447;
-static const uint16 kCh0blockstocopy = 448;
-static const uint16 kCh0playing = 450;
-static const uint16 kCh0repeat = 451;
-static const uint16 kCh1playing = 452;
-static const uint16 kCh1blockstocopy = 453;
-static const uint16 kSoundbufferwrite = 455;
-static const uint16 kCurrentsample = 457;
-static const uint16 kRoomssample = 458;
-static const uint16 kReelroutines = 459;
-static const uint16 kBasicsample = 916;
-static const uint16 kCurrentfile = 1125;
-static const uint16 kRoomscango = 1249;
-static const uint16 kRoompics = 1265;
-static const uint16 kOplist = 1280;
-static const uint16 kInputline = 1283;
-static const uint16 kPresslist = 1411;
-static const uint16 kQuitrequested = 1417;
-static const uint16 kSubtitles = 1418;
-static const uint16 kForeignrelease = 1419;
+static const uint16 kLinepointer = 439;
+static const uint16 kLinedirection = 440;
+static const uint16 kLinelength = 441;
+static const uint16 kLiftsoundcount = 442;
+static const uint16 kCh0blockstocopy = 443;
+static const uint16 kCh0playing = 445;
+static const uint16 kCh0repeat = 446;
+static const uint16 kCh1playing = 447;
+static const uint16 kCh1blockstocopy = 448;
+static const uint16 kSoundbufferwrite = 450;
+static const uint16 kCurrentsample = 452;
+static const uint16 kRoomssample = 453;
+static const uint16 kReelroutines = 454;
+static const uint16 kBasicsample = 911;
+static const uint16 kCurrentfile = 1120;
+static const uint16 kRoomscango = 1244;
+static const uint16 kRoompics = 1260;
+static const uint16 kOplist = 1275;
+static const uint16 kInputline = 1278;
+static const uint16 kPresslist = 1406;
+static const uint16 kQuitrequested = 1412;
+static const uint16 kSubtitles = 1413;
+static const uint16 kForeignrelease = 1414;
static const uint16 kBlocktextdat = (0);
static const uint16 kPersonframes = (0);
static const uint16 kDebuglevel1 = (0);
@@ -423,8 +420,8 @@ static const uint16 kListofchanges = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768
static const uint16 kUndertimedtext = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4));
static const uint16 kRainlist = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30));
static const uint16 kInitialreelrouts = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64));
-static const uint16 kInitialvars = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+916-459);
-static const uint16 kLengthofbuffer = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+916-459+68-0);
+static const uint16 kInitialvars = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+911-454);
+static const uint16 kLengthofbuffer = (0+(228*13)+32+60+(32*32)+(11*10*3)+768+768+768+(32*32)+(128*5)+(80*5)+(100*5)+(12*5)+(46*40)+(5*80)+(250*4)+(256*30)+(6*64)+911-454+68-0);
static const uint16 kReellist = (0+(36*144));
static const uint16 kIntext = (0+(38*2));
static const uint16 kLengthofmap = (0+(66*60));
@@ -475,7 +472,7 @@ static const uint16 kKeypady = (72);
static const uint16 kZoomx = (8);
static const uint16 kInventx = (80);
static const uint16 kMenux = (80+40);
-static const uint16 kLenofreelrouts = (916-459);
+static const uint16 kLenofreelrouts = (911-454);
static const uint16 kHeaderlen = (96);
@@ -486,15 +483,10 @@ public:
void __start();
#include "stubs.h" // Allow hand-reversed functions to have a signature different than void f()
- void useWire();
void identifyOb();
void runEndSeq();
- void useOpenBox();
void clearBuffers();
void getObTextStart();
- void dumpDiaryKeys();
- void entryTexts();
- void putUnderCentre();
void checkObjectSize();
void findText1();
void isRyanHolding();
@@ -512,23 +504,19 @@ public:
void dirCom();
void endGameSeq();
void findFirstPath();
- void useSLab();
void useAltar();
void startTalk();
void getAnyAd();
- void usePipe();
void reminders();
- void runTap();
+ void dumpDiaryKeys();
void checkForExit();
void lookInInterface();
void inToInv();
void adjustLeft();
void deleteExText();
- void entryAnims();
void getFreeAd();
void removeObFromInv();
void heavy();
- void useKey();
void dirFile();
void pickupConts();
void nextColon();
@@ -536,7 +524,6 @@ public:
void getKeyAndLogo();
void selectOb();
void receptionist();
- void selectSlot();
void fadeUpMon();
void showDiaryPage();
void reExFromInv();
@@ -547,7 +534,6 @@ public:
void purgeALocation();
void notHeldError();
void getSetAd();
- void getUnderCentre();
void showKeys();
void printmessage2();
void findOpenPos();
@@ -557,12 +543,10 @@ public:
void rollEm();
void poolGuard();
void lookAtPlace();
- void useAxe();
void findAllOpen();
void fillOpen();
void findSetObject();
void deleteExObject();
- void removeFreeObject();
void lookAtCard();
void helicopter();
void getEitherAd();
@@ -575,13 +559,11 @@ public:
void useOpened();
void signOn();
void locationPic();
- void triggerMessage();
void swapWithOpen();
void dreamweb();
void checkInside();
void findPathOfPoint();
void getDestInfo();
- void setupTimedUse();
void makeCaps();
void read();
void additionalText();
@@ -589,7 +571,6 @@ public:
void searchForString();
void selectOpenOb();
void useGun();
- void autoAppear();
void useHandle();
void incRyanPage();
void findExObject();
@@ -598,18 +579,13 @@ public:
void getExAd();
void initialMonCols();
void execCommand();
- void updateSymbolBot();
void findPuzText();
void swapWithInv();
- void useControl();
void adjustRight();
void transferToEx();
- void updateSymbolTop();
void getPersonText();
void parser();
void emergencyPurge();
- void quitKey();
- void processTrigger();
void transferConToEx();
void adjustDown();
void withWhat();
diff --git a/engines/dreamweb/pathfind.cpp b/engines/dreamweb/pathfind.cpp
index f6591d4666..212d61e6e2 100644
--- a/engines/dreamweb/pathfind.cpp
+++ b/engines/dreamweb/pathfind.cpp
@@ -230,33 +230,35 @@ void DreamBase::bresenhams() {
}
uint16 delta1, delta2;
+ byte lineRoutine;
+
if (deltaY > deltaX) {
- data.byte(kLineroutine) = 1;
+ lineRoutine = 1;
delta1 = deltaY;
delta2 = deltaX;
} else {
- data.byte(kLineroutine) = 0;
+ lineRoutine = 0;
delta1 = deltaX;
delta2 = deltaY;
}
- data.word(kIncrement1) = delta2 * 2;
+ uint16 increment1 = delta2 * 2;
+ uint16 increment2 = delta2 * 2 - delta1 * 2;
int16 remainder = delta2 * 2 - delta1;
- data.word(kIncrement2) = delta2 * 2 - delta1 * 2;
++delta1;
int8 x = (int8)startX;
int8 y = (int8)startY;
data.byte(kLinelength) = delta1;
- if (data.byte(kLineroutine) != 1) {
+ if (lineRoutine != 1) {
for (; delta1; --delta1) {
lineData->x = x;
lineData->y = y;
++lineData;
++x;
if (remainder < 0) {
- remainder += data.word(kIncrement1);
+ remainder += increment1;
} else {
- remainder += data.word(kIncrement2);
+ remainder += increment2;
y += increment;
}
}
@@ -267,9 +269,9 @@ void DreamBase::bresenhams() {
++lineData;
y += increment;
if (remainder < 0) {
- remainder += data.word(kIncrement1);
+ remainder += increment1;
} else {
- remainder += data.word(kIncrement2);
+ remainder += increment2;
++x;
}
}
diff --git a/engines/dreamweb/people.cpp b/engines/dreamweb/people.cpp
index 889a430a22..84f6543a19 100644
--- a/engines/dreamweb/people.cpp
+++ b/engines/dreamweb/people.cpp
@@ -321,7 +321,7 @@ void DreamGenContext::madmansTelly(ReelRoutine &routine) {
void DreamGenContext::smokeBloke(ReelRoutine &routine) {
if (data.byte(kRockstardead) == 0) {
if (routine.b7 & 128)
- setLocation(5);
+ DreamBase::setLocation(5);
}
if (checkSpeed(routine)) {
if (routine.reelPointer() == 100) {
@@ -629,25 +629,16 @@ void DreamGenContext::priest(ReelRoutine &routine) {
if (checkSpeed(routine)) {
routine.incReelPointer();
- push(es);
- push(bx);
priestText(routine);
- bx = pop();
- es = pop();
}
}
-void DreamGenContext::priestText(ReelRoutine &routine) {
+void DreamBase::priestText(ReelRoutine &routine) {
uint16 reel = routine.reelPointer();
if (reel < 2 || reel >= 7 || (reel & 1))
return; // nopriesttext
- al = ((reel & 0xFF) >> 1) + 50;
- bl = 72;
- bh = 80;
- cx = 54;
- dx = 1;
- setupTimedUse();
+ setupTimedUse((reel >> 1) + 50, 54, 1, 72, 80);
}
void DreamGenContext::monkAndRyan(ReelRoutine &routine) {
diff --git a/engines/dreamweb/sprite.cpp b/engines/dreamweb/sprite.cpp
index e93a77f3ff..aca935cde9 100644
--- a/engines/dreamweb/sprite.cpp
+++ b/engines/dreamweb/sprite.cpp
@@ -763,7 +763,7 @@ void DreamBase::rollEndCredits() {
playChannel0(16, 255);
data.byte(kVolume) = 7;
data.byte(kVolumeto) = 0;
- data.byte(kVolumedirection) = 0xFF;
+ data.byte(kVolumedirection) = (byte)-1;
multiGet(mapStore(), 75, 20, 160, 160);
diff --git a/engines/dreamweb/stubs.cpp b/engines/dreamweb/stubs.cpp
index 71a6834b73..a7d65845e1 100644
--- a/engines/dreamweb/stubs.cpp
+++ b/engines/dreamweb/stubs.cpp
@@ -576,7 +576,7 @@ void DreamGenContext::dreamweb() {
data.byte(kLastflag) = 32;
startup1();
data.byte(kVolumeto) = 0;
- data.byte(kVolumedirection) = (uint8)-1;
+ data.byte(kVolumedirection) = (byte)-1;
data.byte(kCommandtype) = 255;
}
@@ -862,6 +862,41 @@ void DreamGenContext::putUnderTimed() {
multiPut(ds.ptr(si, 0), data.byte(kTimedx), y, 240, kUndertimedysize);
}
+void DreamBase::getUnderCentre() {
+ multiGet(mapStore(), 58, 72, 254, 110);
+}
+
+void DreamBase::putUnderCentre() {
+ multiPut(mapStore(), 58, 72, 254, 110);
+}
+
+void DreamGenContext::triggerMessage(uint16 index) {
+ multiGet(mapStore(), 174, 153, 200, 63);
+ uint16 offset = kTextstart + getSegment(data.word(kPuzzletext)).word(index * 2);
+ const uint8 *string = getSegment(data.word(kPuzzletext)).ptr(offset, 0);
+ uint16 y = 156;
+ printDirect(&string, 174, &y, 141, true);
+ hangOn(140);
+ workToScreenCPP();
+ hangOn(340);
+ multiPut(mapStore(), 174, 153, 200, 63);
+ workToScreenCPP();
+ data.byte(kLasttrigger) = 0;
+}
+
+void DreamGenContext::processTrigger() {
+ if (data.byte(kLasttrigger) == '1') {
+ DreamBase::setLocation(8);
+ triggerMessage(45);
+ } else if (data.byte(kLasttrigger) == '2') {
+ DreamBase::setLocation(9);
+ triggerMessage(55);
+ } else if (data.byte(kLasttrigger) == '3') {
+ DreamBase::setLocation(2);
+ triggerMessage(59);
+ }
+}
+
void DreamGenContext::useTimedText() {
if (data.word(kTimecount) == 0)
return;
@@ -2466,20 +2501,20 @@ void DreamGenContext::examIcon() {
showFrame(engine->icons2(), 254, 5, 3, 0);
}
-uint8 DreamGenContext::getLocation(uint8 index) {
+uint8 DreamBase::getLocation(uint8 index) {
return data.byte(kRoomscango + index);
}
void DreamGenContext::getLocation() {
- al = getLocation(al);
+ al = DreamBase::getLocation(al);
}
-void DreamGenContext::setLocation(uint8 index) {
+void DreamBase::setLocation(uint8 index) {
data.byte(kRoomscango + index) = 1;
}
void DreamGenContext::setLocation() {
- setLocation(al);
+ DreamBase::setLocation(al);
}
const uint8 *DreamBase::getTextInFile1(uint16 index) {
@@ -2542,8 +2577,8 @@ void DreamGenContext::lastFolder() {
void DreamGenContext::folderHints() {
if (data.byte(kFolderpage) == 5) {
- if ((data.byte(kAidedead) != 1) && (getLocation(13) != 1)) {
- setLocation(13);
+ if ((data.byte(kAidedead) != 1) && (DreamBase::getLocation(13) != 1)) {
+ DreamBase::setLocation(13);
showFolder();
const uint8 *string = getTextInFile1(30);
printDirect(string, 0, 86, 141, true);
@@ -2551,8 +2586,8 @@ void DreamGenContext::folderHints() {
hangOnP(200);
}
} else if (data.byte(kFolderpage) == 9) {
- if (getLocation(7) != 1) {
- setLocation(7);
+ if (DreamBase::getLocation(7) != 1) {
+ DreamBase::setLocation(7);
showFolder();
const uint8 *string = getTextInFile1(31);
printDirect(string, 0, 86, 141, true);
@@ -3031,7 +3066,7 @@ void DreamGenContext::intro() {
clearPalette();
loadIntroRoom();
data.byte(kVolume) = 7;
- data.byte(kVolumedirection) = (uint8)-1;
+ data.byte(kVolumedirection) = (byte)-1;
data.byte(kVolumeto) = 4;
playChannel0(12, 255);
fadeScreenUps();
@@ -3247,7 +3282,7 @@ void DreamGenContext::gettingShot() {
loadIntroRoom();
fadeScreenUps();
data.byte(kVolumeto) = 0;
- data.byte(kVolumedirection) = 0xFF;
+ data.byte(kVolumedirection) = (byte)-1;
runEndSeq();
clearBeforeLoad();
}
@@ -3314,8 +3349,8 @@ void DreamGenContext::obsThatDoThings() {
if (!compare(data.byte(kCommand), data.byte(kObjecttype), id))
return; // notlouiscard
- if (getLocation(4) != 1) {
- setLocation(4);
+ if (DreamBase::getLocation(4) != 1) {
+ DreamBase::setLocation(4);
lookAtCard();
}
}
@@ -3896,7 +3931,7 @@ void DreamGenContext::talk() {
workToScreenM();
if (data.byte(kSpeechloaded) == 1) {
cancelCh1();
- data.byte(kVolumedirection) = 0xFF;
+ data.byte(kVolumedirection) = (byte)-1;
data.byte(kVolumeto) = 0;
}
}
@@ -4219,7 +4254,7 @@ void DreamGenContext::monkSpeaking() {
showFrame(tempGraphics(), 160, 72, 0, 128); // show monk
workToScreen();
data.byte(kVolume) = 7;
- data.byte(kVolumedirection) = 0xFF;
+ data.byte(kVolumedirection) = (byte)-1;
data.byte(kVolumeto) = 5;
playChannel0(12, 255);
fadeScreenUps();
@@ -4262,4 +4297,289 @@ void DreamGenContext::useButtonA() {
}
}
+void DreamGenContext::autoAppear() {
+ if (data.byte(kLocation) == 32) {
+ // In alley
+ al = 5;
+ resetLocation();
+ DreamBase::setLocation(10);
+ data.byte(kDestpos) = 10;
+ return;
+ }
+
+ if (data.byte(kReallocation) == 24) {
+ // In Eden's apartment
+ if (data.byte(kGeneraldead) == 1) {
+ data.byte(kGeneraldead)++;
+ placeSetObject(44);
+ placeSetObject(18);
+ placeSetObject(93);
+ removeSetObject(92);
+ removeSetObject(55);
+ removeSetObject(75);
+ removeSetObject(84);
+ removeSetObject(85);
+ } else if (data.byte(kSartaindead) == 1) {
+ // Eden's part 2
+ removeSetObject(44);
+ removeSetObject(93);
+ placeSetObject(55);
+ data.byte(kSartaindead)++;
+ }
+ } else {
+ // Not in Eden's
+ if (data.byte(kReallocation) == 25) {
+ // Sart roof
+ data.byte(kNewsitem) = 3;
+ al = 6;
+ resetLocation();
+ DreamBase::setLocation(11);
+ data.byte(kDestpos) = 11;
+ } else {
+ if (data.byte(kReallocation) == 2 && data.byte(kRockstardead) != 0)
+ placeSetObject(23);
+ }
+ }
+}
+
+void DreamGenContext::quitKey() {
+ if (data.byte(kCommandtype) != 222) {
+ data.byte(kCommandtype) = 222;
+ commandOnly(4);
+ }
+
+ if (data.word(kMousebutton) != data.word(kOldbutton) && (data.word(kMousebutton) & 1))
+ data.byte(kGetback) = 1;
+}
+
+void DreamGenContext::setupTimedUse() {
+ DreamBase::setupTimedUse(al, cx, dx, bl, bh);
+}
+
+void DreamBase::setupTimedUse(uint16 textIndex, uint16 countToTimed, uint16 timeCount, byte x, byte y) {
+ if (data.word(kTimecount) != 0)
+ return; // can't setup
+
+ data.byte(kTimedy) = y;
+ data.byte(kTimedx) = x;
+ data.word(kCounttotimed) = countToTimed;
+ data.word(kTimecount) = timeCount + countToTimed;
+ data.word(kTimedseg) = data.word(kPuzzletext);
+ data.word(kTimedoffset) = kTextstart + getSegment(data.word(kPuzzletext)).word(textIndex * 2);
+ const uint8 *string = getSegment(data.word(kPuzzletext)).ptr(data.word(kTimedoffset), 0);
+ debug(1, "setupTimedUse: %d => '%s'", textIndex, string);
+}
+
+void DreamBase::entryTexts() {
+ switch (data.byte(kLocation)) {
+ case 21:
+ setupTimedUse(28, 60, 11, 68, 64);
+ break;
+ case 30:
+ setupTimedUse(27, 60, 11, 68, 64);
+ break;
+ case 23:
+ setupTimedUse(29, 60, 11, 68, 64);
+ break;
+ case 31:
+ setupTimedUse(30, 60, 11, 68, 64);
+ break;
+ case 20: // Sarter's 2
+ setupTimedUse(31, 60, 11, 68, 64);
+ break;
+ case 24: // Eden's lobby
+ setupTimedUse(32, 60, 3, 68, 64);
+ break;
+ case 34: // Eden 2
+ setupTimedUse(33, 60, 3, 68, 64);
+ break;
+ default:
+ break;
+ }
+}
+
+void DreamGenContext::entryAnims() {
+ data.word(kReeltowatch) = 0xFFFF;
+ data.byte(kWatchmode) = (byte)-1;
+
+ switch (data.byte(kLocation)) {
+ case 33: // beach
+ switchRyanOff();
+ data.word(kWatchingtime) = 76 * 2;
+ data.word(kReeltowatch) = 0;
+ data.word(kEndwatchreel) = 76;
+ data.byte(kWatchspeed) = 1;
+ data.byte(kSpeedcount) = 1;
+ break;
+ case 44: // Sparky's
+ al = 8;
+ resetLocation();
+ data.word(kWatchingtime) = 50*2;
+ data.word(kReeltowatch) = 247;
+ data.word(kEndwatchreel) = 297;
+ data.byte(kWatchspeed) = 1;
+ data.byte(kSpeedcount) = 1;
+ switchRyanOff();
+ break;
+ case 22: // lift
+ data.word(kWatchingtime) = 31 * 2;
+ data.word(kReeltowatch) = 0;
+ data.word(kEndwatchreel) = 30;
+ data.byte(kWatchspeed) = 1;
+ data.byte(kSpeedcount) = 1;
+ switchRyanOff();
+ break;
+ case 26: // under church
+ data.byte(kSymboltopnum) = 2;
+ data.byte(kSymbolbotnum) = 1;
+ break;
+ case 45: // entered Dreamweb
+ data.byte(kKeeperflag) = 0;
+ data.word(kWatchingtime) = 296;
+ data.word(kReeltowatch) = 45;
+ data.word(kEndwatchreel) = 198;
+ data.byte(kWatchspeed) = 1;
+ data.byte(kSpeedcount) = 1;
+ switchRyanOff();
+ break;
+ default:
+ if (data.byte(kReallocation) == 46 && data.byte(kSartaindead) == 1) { // Crystal
+ removeFreeObject(0);
+ } else if (data.byte(kLocation) == 9 && !checkIfPathIsOn(2) && data.byte(kAidedead) != 0) {
+ // Top of church
+ if (checkIfPathIsOn(3))
+ turnPathOn(2);
+
+ // Make doors open
+ removeSetObject(4);
+ placeSetObject(5);
+ } else if (data.byte(kLocation) == 47) { // Dream centre
+ placeSetObject(4);
+ placeSetObject(5);
+ } else if (data.byte(kLocation) == 38) { // Car park
+ data.word(kWatchingtime) = 57 * 2;
+ data.word(kReeltowatch) = 4;
+ data.word(kEndwatchreel) = 57;
+ data.byte(kWatchspeed) = 1;
+ data.byte(kSpeedcount) = 1;
+ switchRyanOff();
+ } else if (data.byte(kLocation) == 32) { // Alley
+ data.word(kWatchingtime) = 66 * 2;
+ data.word(kReeltowatch) = 0;
+ data.word(kEndwatchreel) = 66;
+ data.byte(kWatchspeed) = 1;
+ data.byte(kSpeedcount) = 1;
+ switchRyanOff();
+ } else if (data.byte(kLocation) == 24) { // Eden's again
+ turnAnyPathOn(2, data.byte(kRoomnum) - 1);
+ }
+ }
+}
+
+void DreamGenContext::selectSlot() {
+ if (data.byte(kCommandtype) != 244) {
+ data.byte(kCommandtype) = 244;
+ commandOnly(45);
+ }
+
+ if (data.word(kMousebutton) != 1 || data.word(kMousebutton) == data.word(kOldbutton))
+ return; // noselslot
+ if (data.byte(kLoadingorsave) == 3)
+ data.byte(kLoadingorsave)--;
+
+ oldToNames();
+ int y = data.word(kMousey) - (kOpsy + 4);
+ if (y < 11)
+ data.byte(kCurrentslot) = 0;
+ else
+ data.byte(kCurrentslot) = y / 11;
+
+ delPointer();
+ showOpBox();
+ showSlots();
+ showNames();
+ if (data.byte(kLoadingorsave) == 1)
+ showLoadOps();
+ else
+ showSaveOps();
+ readMouse();
+ showPointer();
+ workToScreen();
+ delPointer();
+}
+
+void DreamGenContext::updateSymbolTop() {
+ if (!data.byte(kSymboltopdir))
+ return; // topfinished
+
+ if (data.byte(kSymboltopdir) == (byte)-1) {
+ // Backward
+ data.byte(kSymboltopx)--;
+ if (data.byte(kSymboltopx) != (byte)-1) {
+ // Not wrapping
+ if (data.byte(kSymboltopx) != 24)
+ return; // topfinished
+ data.byte(kSymboltopdir) = 0;
+ } else {
+ data.byte(kSymboltopx) = 48;
+ data.byte(kSymboltopnum)++;
+ if (data.byte(kSymboltopnum) != 6)
+ return; // topfinished
+ data.byte(kSymboltopnum) = 0;
+ }
+ } else {
+ // Forward
+ data.byte(kSymboltopx)++;
+ if (data.byte(kSymboltopx) != 49) {
+ // Not wrapping
+ if (data.byte(kSymboltopx) != 24)
+ return; // topfinished
+ data.byte(kSymboltopdir) = 0;
+ } else {
+ data.byte(kSymboltopx) = 0;
+ data.byte(kSymboltopnum)--;
+ if (data.byte(kSymboltopnum) != (byte)-1)
+ return; // topfinished
+ data.byte(kSymboltopnum) = 5;
+ }
+ }
+}
+
+void DreamGenContext::updateSymbolBot() {
+ if (!data.byte(kSymbolbotdir))
+ return; // botfinished
+
+ if (data.byte(kSymbolbotdir) == (byte)-1) {
+ // Backward
+ data.byte(kSymbolbotx)--;
+ if (data.byte(kSymbolbotx) != (byte)-1) {
+ // Not wrapping
+ if (data.byte(kSymbolbotx) != 24)
+ return; // botfinished
+ data.byte(kSymbolbotdir) = 0;
+ } else {
+ data.byte(kSymbolbotx) = 48;
+ data.byte(kSymbolbotnum)++;
+ if (data.byte(kSymbolbotnum) != 6)
+ return; // botfinished
+ data.byte(kSymbolbotnum) = 0;
+ }
+ } else {
+ // Forward
+ data.byte(kSymbolbotx)++;
+ if (data.byte(kSymbolbotx) != 49) {
+ // Not wrapping
+ if (data.byte(kSymbolbotx) != 24)
+ return; // botfinished
+ data.byte(kSymbolbotdir) = 0;
+ } else {
+ data.byte(kSymbolbotx) = 0;
+ data.byte(kSymbolbotnum)--;
+ if (data.byte(kSymbolbotnum) != (byte)-1)
+ return; // botfinished
+ data.byte(kSymbolbotnum) = 5;
+ }
+ }
+}
+
} // End of namespace DreamGen
diff --git a/engines/dreamweb/stubs.h b/engines/dreamweb/stubs.h
index 4efcc3c07e..6a8445b991 100644
--- a/engines/dreamweb/stubs.h
+++ b/engines/dreamweb/stubs.h
@@ -331,6 +331,11 @@
void useWindow();
void useHatch();
void useLighter();
+ void useSLab();
+ void usePipe();
+ void useOpenBox();
+ void useAxe();
+ void useKey();
void wheelSound();
void callHotelLift();
void useShield();
@@ -348,6 +353,8 @@
void useCardReader3();
void usePoolReader();
void useCooker();
+ void useWire();
+ void useControl();
bool defaultUseHandler(const char *id);
void openTVDoor();
void wearWatch();
@@ -361,9 +368,7 @@
void lastFolder();
void folderHints();
void folderExit();
- uint8 getLocation(uint8 index);
void getLocation();
- void setLocation(uint8 index);
void setLocation();
void loadTempText();
void loadTempText(const char *fileName);
@@ -407,7 +412,6 @@
void louisChair(ReelRoutine &routine);
void bossMan(ReelRoutine &routine);
void priest(ReelRoutine &routine);
- void priestText(ReelRoutine &routine);
void monkAndRyan(ReelRoutine &routine);
void copper(ReelRoutine &routine);
void introMonks1(ReelRoutine &routine);
@@ -472,6 +476,7 @@
void afterIntroRoom();
void gettingShot();
void redrawMainScrn();
+ void selectSlot();
void selectSlot2();
void blank();
void allPointer();
@@ -487,6 +492,7 @@
void useCart();
void useTrainer();
void useHole();
+ void runTap();
void chewy();
void sLabDoorA();
void sLabDoorB();
@@ -565,5 +571,13 @@
void monkSpeaking();
void rollEndCredits2();
void useButtonA();
+ void autoAppear();
+ void quitKey();
+ void setupTimedUse();
+ void entryAnims();
+ void triggerMessage(uint16 index);
+ void processTrigger();
+ void updateSymbolTop();
+ void updateSymbolBot();
#endif
diff --git a/engines/dreamweb/use.cpp b/engines/dreamweb/use.cpp
index 76ecdc732d..c591eca826 100644
--- a/engines/dreamweb/use.cpp
+++ b/engines/dreamweb/use.cpp
@@ -1110,6 +1110,33 @@ void DreamGenContext::useLighter() {
}
}
+void DreamGenContext::useWire() {
+ if (data.byte(kWithobject) == 255) {
+ withWhat();
+ return;
+ }
+
+ char knife[4] = { 'K', 'N', 'F', 'E' }; // TODO: convert to string with trailing zero
+ if (compare(data.byte(kWithobject), data.byte(kWithtype), knife)) {
+ removeSetObject(51);
+ placeSetObject(52);
+ showPuzText(11, 300);
+ data.byte(kProgresspoints)++;
+ data.byte(kGetback) = 1;
+ return;
+ }
+
+ char axe[4] = { 'A', 'X', 'E', 'D' }; // TODO: convert to string with trailing zero
+ if (compare(data.byte(kWithobject), data.byte(kWithtype), axe)) {
+ showPuzText(16, 300);
+ putBackObStuff();
+ return;
+ }
+
+ showPuzText(14, 300);
+ putBackObStuff();
+}
+
void DreamGenContext::openTomb() {
data.byte(kProgresspoints)++;
showFirstUse();
@@ -1197,4 +1224,247 @@ void DreamGenContext::useDiary() {
workToScreenM();
}
+void DreamGenContext::useControl() {
+ if (data.byte(kWithobject) == 255) {
+ withWhat();
+ return;
+ }
+
+ char key[4] = { 'K', 'E', 'Y', 'A' }; // TODO: convert to string with trailing zero
+ if (compare(data.byte(kWithobject), data.byte(kWithtype), key)) { // Right key
+ playChannel1(16);
+ if (data.byte(kLocation) == 21) { // Going down
+ showPuzText(3, 300);
+ data.byte(kNewlocation) = 30;
+ } else {
+ showPuzText(0, 300);
+ data.byte(kNewlocation) = 21;
+ }
+
+ data.byte(kCounttoclose) = 8;
+ data.byte(kCounttoopen) = 0;
+ data.word(kWatchingtime) = 80;
+ data.byte(kGetback) = 1;
+ return;
+ }
+
+ if (data.byte(kReallocation) == 21) {
+ char knife[4] = { 'K', 'N', 'F', 'E' }; // TODO: convert to string with trailing zero
+ char axe[4] = { 'A', 'X', 'E', 'D' }; // TODO: convert to string with trailing zero
+
+ if (compare(data.byte(kWithobject), data.byte(kWithtype), knife)) {
+ // Jimmy controls
+ placeSetObject(50);
+ placeSetObject(51);
+ placeSetObject(26);
+ placeSetObject(30);
+ removeSetObject(16);
+ removeSetObject(17);
+ playChannel1(14);
+ showPuzText(10, 300);
+ data.byte(kProgresspoints)++;
+ data.byte(kGetback) = 1;
+ } else if (compare(data.byte(kWithobject), data.byte(kWithtype), axe)) {
+ // Axe on controls
+ showPuzText(16, 300);
+ data.byte(kProgresspoints)++;
+ putBackObStuff();
+ } else {
+ // Balls
+ showFirstUse();
+ putBackObStuff();
+ }
+ } else {
+ // Balls
+ showFirstUse();
+ putBackObStuff();
+ }
+}
+
+void DreamGenContext::useSLab() {
+ if (data.byte(kWithobject) == 255) {
+ withWhat();
+ return;
+ }
+
+ char id[4] = { 'J', 'E', 'W', 'L' }; // TODO: convert to string with trailing zero
+ if (!compare(data.byte(kWithobject), data.byte(kWithtype), id)) {
+ showPuzText(14, 300);
+ putBackObStuff();
+ return;
+ }
+
+ DynObject *exObject = getExAd(data.byte(kWithobject));
+ exObject->mapad[0] = 0;
+
+ removeSetObject(data.byte(kCommand));
+ placeSetObject(data.byte(kCommand) + 1);
+ if (data.byte(kCommand) + 1 == 54) {
+ // Last slab
+ turnPathOn(0);
+ data.word(kWatchingtime) = 22;
+ data.word(kReeltowatch) = 35;
+ data.word(kEndwatchreel) = 48;
+ data.byte(kWatchspeed) = 1;
+ data.byte(kSpeedcount) = 1;
+ }
+
+ data.byte(kProgresspoints)++;
+ showFirstUse();
+ data.byte(kGetback) = 1;
+}
+
+void DreamGenContext::usePipe() {
+ if (data.byte(kWithobject) == 255) {
+ withWhat();
+ return;
+ }
+
+ char cupEmpty[4] = { 'C', 'U', 'P', 'E' }; // TODO: convert to string with trailing zero
+ char cupFull[4] = { 'C', 'U', 'P', 'F' }; // TODO: convert to string with trailing zero
+
+ if (compare(data.byte(kWithobject), data.byte(kWithtype), cupEmpty)) {
+ // Fill cup
+ showPuzText(36, 300);
+ putBackObStuff();
+ DynObject *exObject = getExAd(data.byte(kWithobject));
+ exObject->id[3] = 'F'-'A'; // CUPE (empty cup) -> CUPF (full cup)
+ return;
+ } else if (compare(data.byte(kWithobject), data.byte(kWithtype), cupFull)) {
+ // Already full
+ showPuzText(35, 300);
+ putBackObStuff();
+ } else {
+ showPuzText(14, 300);
+ showPuzText();
+ putBackObStuff();
+ }
+}
+
+void DreamGenContext::useOpenBox() {
+ if (data.byte(kWithobject) == 255) {
+ withWhat();
+ return;
+ }
+
+ char cupEmpty[4] = { 'C', 'U', 'P', 'E' }; // TODO: convert to string with trailing zero
+ char cupFull[4] = { 'C', 'U', 'P', 'F' }; // TODO: convert to string with trailing zero
+
+ if (compare(data.byte(kWithobject), data.byte(kWithtype), cupFull)) {
+ // Destroy open box
+ data.byte(kProgresspoints)++;
+ showPuzText(37, 300);
+ DynObject *exObject = getExAd(data.byte(kWithobject));
+ exObject->id[3] = 'E'-'A'; // CUPF (full cup) -> CUPE (empty cup)
+ data.word(kWatchingtime) = 140;
+ data.word(kReeltowatch) = 105;
+ data.word(kEndwatchreel) = 181;
+ data.byte(kWatchspeed) = 1;
+ data.byte(kSpeedcount) = 1;
+ turnPathOn(4);
+ data.byte(kGetback) = 1;
+ return;
+ }
+
+ if (compare(data.byte(kWithobject), data.byte(kWithtype), cupEmpty)) {
+ // Open box wrong
+ showPuzText(38, 300);
+ putBackObStuff();
+ return;
+ }
+
+ showFirstUse();
+}
+
+void DreamGenContext::runTap() {
+ if (data.byte(kWithobject) == 255) {
+ withWhat();
+ return;
+ }
+
+ char cupEmpty[4] = { 'C', 'U', 'P', 'E' }; // TODO: convert to string with trailing zero
+ char cupFull[4] = { 'C', 'U', 'P', 'F' }; // TODO: convert to string with trailing zero
+
+ if (compare(data.byte(kWithobject), data.byte(kWithtype), cupEmpty)) {
+ // Fill cup from tap
+ DynObject *exObject = getExAd(data.byte(kWithobject));
+ exObject->id[3] = 'F'-'A'; // CUPE (empty cup) -> CUPF (full cup)
+ playChannel1(8);
+ showPuzText(57, 300);
+ putBackObStuff();
+ return;
+ }
+
+ if (compare(data.byte(kWithobject), data.byte(kWithtype), cupFull)) {
+ // Cup from tap full
+ showPuzText(58, 300);
+ putBackObStuff();
+ return;
+ }
+
+ showPuzText(56, 300);
+ putBackObStuff();
+}
+
+void DreamGenContext::useAxe() {
+ if (data.byte(kReallocation) != 22) {
+ // Not in pool
+ showFirstUse();
+ return;
+ }
+
+ if (data.byte(kMapy) == 10) {
+ // Axe on door
+ showPuzText(15, 300);
+ data.byte(kProgresspoints)++;
+ data.word(kWatchingtime) = 46*2;
+ data.word(kReeltowatch) = 31;
+ data.word(kEndwatchreel) = 77;
+ data.byte(kWatchspeed) = 1;
+ data.byte(kSpeedcount) = 1;
+ data.byte(kGetback) = 1;
+ return;
+ }
+
+ showSecondUse();
+ data.byte(kProgresspoints)++;
+ data.byte(kLastweapon) = 2;
+ data.byte(kGetback) = 1;
+ removeObFromInv();
+}
+
+void DreamGenContext::useKey() {
+ switch(data.byte(kLocation)) {
+ case 5:
+ case 30:
+ if (data.byte(kMapx) == 22 && data.byte(kMapy) == 10) {
+ showPuzText(0, 300);
+ data.byte(kCounttoclose) = 100;
+ data.byte(kGetback) = 1;
+ } else {
+ // Wrong room
+ showPuzText(2, 200);
+ putBackObStuff();
+ }
+ break;
+ case 21:
+ if (data.byte(kMapx) == 11 && data.byte(kMapy) == 10) {
+ showPuzText(3, 300);
+ data.byte(kNewlocation) = 30;
+ al = 2;
+ fadeScreenDown();
+ showFirstUse();
+ putBackObStuff();
+ } else {
+ // Wrong room
+ showPuzText(2, 200);
+ putBackObStuff();
+ }
+ default:
+ showPuzText(1, 200);
+ putBackObStuff();
+ break;
+ }
+}
+
} // End of namespace DreamGen
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 538e88aa90..120900537b 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -568,41 +568,27 @@ void LoLEngine::initKeymap() {
Common::Action *act;
Common::Keymap *engineKeyMap = new Common::Keymap(kKeymapName);
- act = new Common::Action(engineKeyMap, "AT1", _("Attack 1"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_F1, Common::ASCII_F1 , 0));
-
- act = new Common::Action(engineKeyMap, "AT2", _("Attack 2"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_F2, Common::ASCII_F2 , 0));
-
- act = new Common::Action(engineKeyMap, "AT3", _("Attack 3"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_F3, Common::ASCII_F3 , 0));
-
- act = new Common::Action(engineKeyMap, "MVF", _("Move Forward"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_UP));
-
- act = new Common::Action(engineKeyMap, "MVB", _("Move Back"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_DOWN));
-
- act = new Common::Action(engineKeyMap, "SLL", _("Slide Left"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_LEFT));
-
- act = new Common::Action(engineKeyMap, "SLR", _("Slide Right"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_RIGHT));
-
- act = new Common::Action(engineKeyMap, "TL", _("Turn Left"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_HOME));
-
- act = new Common::Action(engineKeyMap, "TR", _("Turn Right"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_PAGEUP));
-
- act = new Common::Action(engineKeyMap, "RST", _("Rest"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_r));
-
- act = new Common::Action(engineKeyMap, "OPT", _("Options"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_o));
+ const Common::KeyActionEntry keyActionEntries[] = {
+ {Common::KeyState(Common::KEYCODE_F1, Common::ASCII_F1, 0), "AT1", _("Attack 1")},
+ {Common::KeyState(Common::KEYCODE_F2, Common::ASCII_F2, 0), "AT2", _("Attack 2")},
+ {Common::KeyState(Common::KEYCODE_F3, Common::ASCII_F2, 0), "AT3", _("Attack 3")},
+ {Common::KeyState(Common::KEYCODE_UP), "MVF", _("Move Forward")},
+ {Common::KeyState(Common::KEYCODE_DOWN), "MVB", _("Move Back")},
+ {Common::KeyState(Common::KEYCODE_LEFT), "SLL", _("Slide Left")},
+ {Common::KeyState(Common::KEYCODE_RIGHT), "SLR", _("Slide Right")},
+ {Common::KeyState(Common::KEYCODE_HOME), "TL", _("Turn Left")},
+ {Common::KeyState(Common::KEYCODE_PAGEUP), "TR", _("Turn Right")},
+ {Common::KeyState(Common::KEYCODE_r), "RST", _("Rest")},
+ {Common::KeyState(Common::KEYCODE_o), "OPT", _("Options")},
+ {Common::KeyState(Common::KEYCODE_SLASH), "SPL", _("Choose Spell")},
+ {Common::KeyState(), 0, 0}
+ };
- act = new Common::Action(engineKeyMap, "SPL", _("Choose Spell"), Common::kGenericActionType, Common::kActionKeyType);
- act->addKeyEvent(Common::KeyState(Common::KEYCODE_SLASH));
+ const Common::KeyActionEntry *entry;
+ for (entry = keyActionEntries; entry->id; ++entry) {
+ act = new Common::Action(engineKeyMap, entry->id, Common::String(entry->description), Common::kGenericActionType, Common::kActionKeyType);
+ act->addKeyEvent(Common::KeyState(entry->ks));
+ }
mapper->addGameKeymap(engineKeyMap);
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index c4326d175f..dcb0c7940d 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -308,16 +308,19 @@ MystGraphics::~MystGraphics() {
delete _backBuffer;
}
-static const char* picFileNames[] = {
+static const char *s_picFileNames[] = {
"CHpics",
"",
+ "",
"DUpics",
"INpics",
+ "",
"MEpics",
"MYpics",
"SEpics",
- "STpics",
- ""
+ "",
+ "",
+ "STpics"
};
void MystGraphics::loadExternalPictureFile(uint16 stack) {
@@ -328,11 +331,11 @@ void MystGraphics::loadExternalPictureFile(uint16 stack) {
_pictureFile.picFile.close();
delete[] _pictureFile.entries;
- if (!scumm_stricmp(picFileNames[stack], ""))
+ if (!scumm_stricmp(s_picFileNames[stack], ""))
return;
- if (!_pictureFile.picFile.open(picFileNames[stack]))
- error ("Could not open external picture file \'%s\'", picFileNames[stack]);
+ if (!_pictureFile.picFile.open(s_picFileNames[stack]))
+ error ("Could not open external picture file \'%s\'", s_picFileNames[stack]);
_pictureFile.pictureCount = _pictureFile.picFile.readUint32BE();
_pictureFile.entries = new PictureFile::PictureEntry[_pictureFile.pictureCount];
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index b6c0a3212f..b3222e0322 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -2978,15 +2978,17 @@ void Myst::clockReset() {
}
void Myst::clockResetWeight() {
- // Set video bounds, weight going up
+ _clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
+
if (!(_vm->getFeatures() & GF_ME)) {
- _clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
+ // Set video bounds, weight going up
_vm->_video->setVideoBounds(_clockWeightVideo,
Audio::Timestamp(0, 2214 * 2 - _clockWeightPosition, 600),
Audio::Timestamp(0, 2214 * 2, 600));
} else {
- //FIXME: Needs QT backwards playing
+ //FIXME: Needs QT backwards playing, for now just display the weight up
warning("Weight going back up not implemented");
+ _vm->_video->drawVideoFrame(_clockWeightVideo, Audio::Timestamp(0, 0, 600));
}
// Reset position
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index 4c715b56e4..6d54d0c586 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -623,7 +623,7 @@ void Stoneship::o_hologramSelectionMove(uint16 op, uint16 var, uint16 argc, uint
uint16 selectionPos = position * 1500 / 243;
VideoHandle handleMovie = _hologramSelection->playMovie();
- _vm->_video->setVideoBounds(handleMovie, Audio::Timestamp(0, selectionPos, 600), Audio::Timestamp(0, selectionPos, 600));
+ _vm->_video->drawVideoFrame(handleMovie, Audio::Timestamp(0, selectionPos, 600));
_hologramDisplayPos = position * 1450 / 243 + 350;
@@ -631,7 +631,7 @@ void Stoneship::o_hologramSelectionMove(uint16 op, uint16 var, uint16 argc, uint
if (_hologramTurnedOn) {
_hologramDisplay->setBlocking(false);
VideoHandle displayMovie = _hologramDisplay->playMovie();
- _vm->_video->setVideoBounds(displayMovie, Audio::Timestamp(0, _hologramDisplayPos, 600), Audio::Timestamp(0, _hologramDisplayPos, 600));
+ _vm->_video->drawVideoFrame(displayMovie, Audio::Timestamp(0, _hologramDisplayPos, 600));
}
}
}
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index cd8fc8ef80..7958906897 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -529,6 +529,15 @@ void VideoManager::setVideoBounds(VideoHandle handle, Audio::Timestamp start, Au
_videoStreams[handle]->seekToTime(start);
}
+void VideoManager::drawVideoFrame(VideoHandle handle, Audio::Timestamp time) {
+ assert(handle != NULL_VID_HANDLE);
+ _videoStreams[handle].end = Audio::Timestamp(0xffffffff, 1);
+ _videoStreams[handle]->seekToTime(time);
+ updateMovies();
+ delete _videoStreams[handle].video;
+ _videoStreams[handle].clear();
+}
+
void VideoManager::seekToTime(VideoHandle handle, Audio::Timestamp time) {
assert(handle != NULL_VID_HANDLE);
_videoStreams[handle]->seekToTime(time);
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index efa81edfbd..34c287497f 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -104,6 +104,7 @@ public:
uint32 getDuration(VideoHandle videoHandle);
bool endOfVideo(VideoHandle handle);
void setVideoBounds(VideoHandle handle, Audio::Timestamp start, Audio::Timestamp end);
+ void drawVideoFrame(VideoHandle handle, Audio::Timestamp time);
void seekToTime(VideoHandle handle, Audio::Timestamp time);
void setVideoLooping(VideoHandle handle, bool loop);
void waitUntilMovieEnds(VideoHandle videoHandle);
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index dca3dcead5..f86bab3a87 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -42,8 +42,8 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
case 100: return new Scene100();
// Computer console
case 125: return new Scene125();
- //
- case 150:
+ // Empty Bedroom
+ case 150: return new Scene150();
case 160:
case 175:
case 180:
@@ -128,7 +128,11 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Maze: Large Cave
return new Scene2500();
case 2525:
+ // Maze: Furnace room
+ return new Scene2525();
case 2530:
+ // Maze: Well
+ return new Scene2530();
case 2535:
case 2600:
case 2700:
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
index 214853ce86..661a52d601 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
@@ -94,11 +94,11 @@ bool Scene100::Door::startAction(CursorType action, Event &event) {
if (_state) {
SceneItem::display2(100, 26);
_state = 0;
- scene->_object10.setFrame(1);
+ scene->_doorDisplay.setFrame(1);
} else {
SceneItem::display2(100, 27);
_state = 1;
- scene->_object10.setFrame(2);
+ scene->_doorDisplay.setFrame(2);
}
return true;
default:
@@ -176,7 +176,7 @@ bool Scene100::StasisNegator::startAction(CursorType action, Event &event) {
}
}
-bool Scene100::Object10::startAction(CursorType action, Event &event) {
+bool Scene100::DoorDisplay::startAction(CursorType action, Event &event) {
Scene100 *scene = (Scene100 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
@@ -242,34 +242,35 @@ void Scene100::postInit(SceneObjectList *OwnerList) {
_door.setPosition(Common::Point(160, 84));
_door.setDetails(100, 3, 4, 5, 1, NULL);
- _object10.postInit();
- _object10.setup(100, 2, 1);
- _object10.setDetails(100, -1, -1, -1, 1, NULL);
+ _doorDisplay.postInit();
+ _doorDisplay.setup(100, 2, 1);
+ _doorDisplay.setPosition(Common::Point(202, 53));
+ _doorDisplay.setDetails(100, -1, -1, -1, 1, NULL);
_table.postInit();
_table.setup(100, 2, 3);
_table.setPosition(Common::Point(175, 157));
_table.setDetails(100, 17, 18, 20, 1, NULL);
- _object1.postInit();
- _object1.setup(100, 3, 1);
- _object1.setPosition(Common::Point(89, 79));
- _object1.fixPriority(250);
- _object1.animate(ANIM_MODE_2, NULL);
- _object1._numFrames = 3;
-
- _object2.postInit();
- _object2.setup(100, 3, 1);
- _object2.setPosition(Common::Point(89, 147));
- _object2.fixPriority(250);
- _object2.animate(ANIM_MODE_7, 0, NULL);
- _object2._numFrames = 3;
-
- _object6.postInit();
- _object6.setVisage(101);
- _object6.setPosition(Common::Point(231, 126));
- _object6.fixPriority(10);
- _object6.setDetails(100, 37, -1, 39, 1, NULL);
+ _bedLights1.postInit();
+ _bedLights1.setup(100, 3, 1);
+ _bedLights1.setPosition(Common::Point(89, 79));
+ _bedLights1.fixPriority(250);
+ _bedLights1.animate(ANIM_MODE_2, NULL);
+ _bedLights1._numFrames = 3;
+
+ _bedLights2.postInit();
+ _bedLights2.setup(100, 3, 1);
+ _bedLights2.setPosition(Common::Point(89, 147));
+ _bedLights2.fixPriority(250);
+ _bedLights2.animate(ANIM_MODE_7, 0, NULL);
+ _bedLights2._numFrames = 3;
+
+ _wardrobe.postInit();
+ _wardrobe.setVisage(101);
+ _wardrobe.setPosition(Common::Point(231, 126));
+ _wardrobe.fixPriority(10);
+ _wardrobe.setDetails(100, 37, -1, 39, 1, NULL);
if (R2_INVENTORY.getObjectScene(R2_STEPPING_DISKS) == 100) {
_steppingDisks.postInit();
@@ -296,7 +297,7 @@ void Scene100::postInit(SceneObjectList *OwnerList) {
_object5.postInit();
_object4.postInit();
_sceneMode = 104;
- setAction(&_sequenceManager1, this, 104, &R2_GLOBALS._player, &_object6, &_object4, &_object5, NULL);
+ setAction(&_sequenceManager1, this, 104, &R2_GLOBALS._player, &_wardrobe, &_object4, &_object5, NULL);
break;
case 125:
_sceneMode = 100;
@@ -356,10 +357,10 @@ void Scene100::signal() {
case 110:
if (_door._state) {
_door._state = 0;
- _object10.setFrame(1);
+ _doorDisplay.setFrame(1);
} else {
_door._state = 1;
- _object10.setFrame(2);
+ _doorDisplay.setFrame(2);
}
R2_GLOBALS._player.enableControl();
break;
@@ -1199,6 +1200,98 @@ Common::String Scene125::parseMessage(const Common::String &msg) {
}
/*--------------------------------------------------------------------------
+ * Scene 150 - Empty Bedroom
+ *
+ *--------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------*/
+
+void Scene150::postInit(SceneObjectList *OwnerList) {
+ SceneExt::postInit();
+ loadScene(100);
+
+ _door.postInit();
+ _door._state = 0;
+ _door.setVisage(100);
+ _door.setPosition(Common::Point(160, 84));
+ _door.setDetails(100, 3, -1, -1, 1, NULL);
+
+ _doorDisplay.postInit();
+ _doorDisplay.setup(100, 2, 1);
+ _doorDisplay.setPosition(Common::Point(202, 53));
+ _doorDisplay.setDetails(100, -1, -1, -1, 1, NULL);
+
+ _emptyRoomTable.postInit();
+ _emptyRoomTable.setVisage(100);
+ _emptyRoomTable.setStrip(4);
+ _emptyRoomTable.setFrame(1);
+ _emptyRoomTable.setPosition(Common::Point(175, 157));
+ _emptyRoomTable.setDetails(150, 3, 4, 5, 1, NULL);
+
+ _wardrobe.postInit();
+ _wardrobe.setVisage(101);
+ _wardrobe.setPosition(Common::Point(231, 126));
+ _wardrobe.fixPriority(10);
+ _wardrobe.setDetails(100, 37, -1, 39, 1, NULL);
+
+ _terminal.setDetails(11, 100, 14, 15, 16);
+ _desk.setDetails(12, 100, 11, -1, 13);
+ _bed.setDetails(13, 100, 8, 9, 10);
+ _duct.setDetails(14, 100, 34, -1, 36);
+
+ R2_GLOBALS._player.postInit();
+ R2_GLOBALS._player.setVisage(10);
+ R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+ R2_GLOBALS._player.disableControl();
+
+ _background.setDetails(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 150, 0, 1, -1, 1, NULL);
+ _sceneMode = 100;
+
+ switch (R2_GLOBALS._sceneManager._previousScene) {
+ case 100:
+ setAction(&_sequenceManager1, this, 106, &R2_GLOBALS._player, NULL);
+ break;
+ case 200:
+ setAction(&_sequenceManager1, this, 100, &R2_GLOBALS._player, &_door, NULL);
+ break;
+ default:
+ R2_GLOBALS._player.setStrip(3);
+ R2_GLOBALS._player.setPosition(Common::Point(180, 100));
+ R2_GLOBALS._player.enableControl();
+ break;
+ }
+}
+
+void Scene150::remove() {
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ SceneExt::remove();
+}
+
+void Scene150::signal() {
+ switch (_sceneMode) {
+ case 101:
+ R2_GLOBALS._sceneManager.changeScene(200);
+ break;
+ case 105:
+ R2_GLOBALS._sceneManager.changeScene(125);
+ break;
+ case 110:
+ if (_door._state) {
+ _door._state = 0;
+ _doorDisplay.setFrame(1);
+ } else {
+ _door._state = 1;
+ _doorDisplay.setFrame(2);
+ }
+ R2_GLOBALS._player.enableControl();
+ break;
+ default:
+ R2_GLOBALS._player.enableControl();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
* Scene 200 - Ship Corridor
*
*--------------------------------------------------------------------------*/
@@ -1707,6 +1800,25 @@ bool Scene300::Quinn::startAction(CursorType action, Event &event) {
}
}
+bool Scene300::Doorway::startAction(CursorType action, Event &event) {
+ Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
+
+ if (action == CURSOR_USE) {
+ if ((R2_GLOBALS._player._characterIndex == R2_QUINN) &&
+ (!R2_GLOBALS.getFlag(44) || R2_GLOBALS._player._characterScene[R2_MIRANDA] == 500)) {
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 301;
+ scene->setAction(&scene->_sequenceManager1, scene, 301, &R2_GLOBALS._player, this, NULL);
+ } else {
+ SceneItem::display2(300, 45);
+ }
+
+ return true;
+ } else {
+ return SceneActor::startAction(action, event);
+ }
+}
+
/*--------------------------------------------------------------------------*/
Scene300::Scene300(): SceneExt() {
@@ -1769,7 +1881,6 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
_object4.postInit();
_object4.setup(300, 5, 1);
_object4.setPosition(Common::Point(236, 48));
-
_object4.animate(ANIM_MODE_2, NULL);
_protocolDisplay.postInit();
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.h b/engines/tsage/ringworld2/ringworld2_scenes0.h
index 834b91c01c..5b3123b37f 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.h
@@ -67,7 +67,7 @@ class Scene100: public SceneExt {
public:
bool startAction(CursorType action, Event &event);
};
- class Object10: public SceneActorExt {
+ class DoorDisplay: public SceneActorExt {
public:
bool startAction(CursorType action, Event &event);
};
@@ -85,12 +85,12 @@ class Scene100: public SceneExt {
public:
NamedHotspot _background, _duct, _bed, _desk;
Terminal _terminal;
- SceneActor _object1, _object2, _object3, _object4, _object5;
- SceneActor _object6;
+ SceneActor _bedLights1, _bedLights2, _object3, _object4, _object5;
+ SceneActor _wardrobe;
Door _door;
Table _table;
StasisNegator _stasisNegator;
- Object10 _object10;
+ DoorDisplay _doorDisplay;
SteppingDisks _steppingDisks;
SequenceManager _sequenceManager1, _sequenceManager2;
@@ -157,6 +157,15 @@ public:
Common::String parseMessage(const Common::String &msg);
};
+class Scene150: public Scene100 {
+public:
+ SceneActor _emptyRoomTable;
+public:
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ virtual void signal();
+};
+
class Scene200: public SceneExt {
/* Objects */
class NorthDoor: public SceneActor {
@@ -240,6 +249,10 @@ class Scene300: public SceneExt {
public:
virtual bool startAction(CursorType action, Event &event);
};
+ class Doorway: public SceneActor {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
public:
SequenceManager _sequenceManager1, _sequenceManager2, _sequenceManager3, _sequenceManager4;
ASoundExt _sound1;
@@ -258,7 +271,8 @@ public:
MirandaWorkstation _mirandaWorkstation1, _mirandaWorkstation2;
SceneActor _object1, _object2, _object3, _object4, _protocolDisplay;
SceneActor _object6, _object7, _object8, _object9;
- SceneActor _teal, _soldier, _object12, _doorway;
+ SceneActor _teal, _soldier, _object12;
+ Doorway _doorway;
Miranda _miranda;
Seeker _seeker;
Quinn _quinn;
diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.cpp b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
index 18fd6e6bde..cbb6dbc42e 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes2.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
@@ -2503,5 +2503,302 @@ void Scene2500::signal() {
}
}
+/*--------------------------------------------------------------------------
+ * Scene 2525 - Furnace room
+ *
+ *--------------------------------------------------------------------------*/
+bool Scene2525::Item5::startAction(CursorType action, Event &event) {
+ Scene2525 *scene = (Scene2525 *)R2_GLOBALS._sceneManager._scene;
+
+ if ((action == R2_20) && (!R2_GLOBALS.getFlag(74))) {
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 2526;
+ scene->setAction(&scene->_sequenceManager, scene, 2526, &R2_GLOBALS._player, NULL);
+ return true;
+ }
+
+ return SceneItem::startAction(action, event);
+}
+
+bool Scene2525::Actor3::startAction(CursorType action, Event &event) {
+ Scene2525 *scene = (Scene2525 *)R2_GLOBALS._sceneManager._scene;
+
+ if (action != CURSOR_USE)
+ return SceneActor::startAction(action, event);
+
+ if (R2_GLOBALS._player._characterIndex == 2) {
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 2525;
+ scene->setAction(&scene->_sequenceManager, scene, 2525, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ } else {
+ SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ }
+ return true;
+}
+
+void Scene2525::Exit1::changeScene() {
+ Scene2525 *scene = (Scene2525 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._events.setCursor(CURSOR_ARROW);
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 11;
+
+ Common::Point pt(R2_GLOBALS._player._position.x, 200);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, scene);
+}
+
+void Scene2525::postInit(SceneObjectList *OwnerList) {
+ loadScene(2525);
+ SceneExt::postInit();
+ R2_GLOBALS._sound1.play(200);
+ R2_GLOBALS._sound2.play(207);
+
+ _exit1.setDetails(Rect(86, 155, 228, 168), EXITCURSOR_S, 2000);
+
+ if (R2_INVENTORY.getObjectScene(29) == 2525) {
+ _actor3.postInit();
+ _actor3.setup(2435, 1, 2);
+ _actor3.setPosition(Common::Point(78, 155));
+ _actor3.fixPriority(155);
+ _actor3.setDetails(2525, 27, -1, -1, 1, NULL);
+ }
+
+ _actor2.postInit();
+ _actor2.setup(2525, 1, 1);
+ _actor2.setPosition(Common::Point(183, 114));
+ _actor2.setDetails(2525, 15, -1, -1, 1, NULL);
+ _actor2.animate(ANIM_MODE_2, NULL);
+ _actor2._numFrames = 3;
+
+ R2_GLOBALS._player.postInit();
+ R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+ if (R2_GLOBALS._player._characterIndex == 1) {
+ R2_GLOBALS._player.setup(2008, 3, 1);
+ R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
+ } else {
+ R2_GLOBALS._player.setup(20, 3, 1);
+ R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
+ }
+
+ if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
+ _actor1.postInit();
+ if (R2_GLOBALS._player._characterIndex == 1) {
+ _actor1.setup(20, 5, 1);
+ _actor1.setDetails(9002, 0, 4, 3, 1, NULL);
+ } else {
+ _actor1.setup(2008, 5, 1);
+ _actor1.setDetails(9001, 0, 5, 3, 1, NULL);
+ }
+ _actor1.setPosition(Common::Point(209, 162));
+
+ R2_GLOBALS._walkRegions.enableRegion(4);
+ }
+
+ _item5.setDetails(Rect(125, 73, 140, 86), 2525, 6, -1, -1, 1, NULL);
+ _item3.setDetails(Rect(137, 11, 163, 72), 2525, 12, -1, -1, 1, NULL);
+ _item4.setDetails(Rect(204, 20, 234, 78), 2525, 12, -1, -1, 1, NULL);
+ _item2.setDetails(Rect(102, 62, 230, 134), 2525, 0, -1, -1, 1, NULL);
+ _item1.setDetails(Rect(0, 0, 320, 200), 2525, 24, -1, -1, 1, NULL);
+
+ R2_GLOBALS._player.disableControl();
+
+ if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2000) {
+ R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 2525;
+ R2_GLOBALS._player.setPosition(Common::Point(160, 200));
+ Common::Point pt(160, 150);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ } else {
+ R2_GLOBALS._player.setPosition(Common::Point(160, 150));
+ R2_GLOBALS._player.setStrip(3);
+ R2_GLOBALS._player.enableControl();
+ }
+}
+
+void Scene2525::remove() {
+ R2_GLOBALS._sound1.fadeOut2(NULL);
+ R2_GLOBALS._sound2.fadeOut2(NULL);
+ SceneExt::remove();
+}
+
+void Scene2525::signal() {
+ switch (_sceneMode) {
+ case 11:
+ g_globals->_sceneManager.changeScene(2000);
+ break;
+ case 2525:
+ _actor3.remove();
+ R2_INVENTORY.setObjectScene(29, 2);
+ R2_GLOBALS._player.enableControl();
+ break;
+ case 2526:
+ R2_GLOBALS.setFlag(74);
+ R2_GLOBALS._player.enableControl();
+ break;
+ default:
+ R2_GLOBALS._player.enableControl();
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------
+ * Scene 2530 - Maze: Well
+ *
+ *--------------------------------------------------------------------------*/
+bool Scene2530::Actor2::startAction(CursorType action, Event &event) {
+ Scene2530 *scene = (Scene2530 *)R2_GLOBALS._sceneManager._scene;
+
+ if (action != CURSOR_USE)
+ return SceneActor::startAction(action, event);
+
+ if (R2_GLOBALS._player._characterIndex == 2) {
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 2530;
+ scene->setAction(&scene->_sequenceManager, scene, 2530, &R2_GLOBALS._player, &scene->_actor2, NULL);
+ } else {
+ SceneItem::display(2530, 33, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ }
+
+ return true;
+}
+
+bool Scene2530::Actor3::startAction(CursorType action, Event &event) {
+ Scene2530 *scene = (Scene2530 *)R2_GLOBALS._sceneManager._scene;
+
+ if (action != CURSOR_USE)
+ return SceneActor::startAction(action, event);
+
+ if (R2_GLOBALS._player._characterIndex == 1) {
+ if (R2_GLOBALS.getFlag(73))
+ SceneItem::display(2530, 35, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ else {
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 2532;
+ scene->setAction(&scene->_sequenceManager, scene, 2532, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ }
+ } else {
+ if (R2_GLOBALS.getFlag(73)) {
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 2533;
+ scene->setAction(&scene->_sequenceManager, scene, 2533, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ } else {
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 2531;
+ scene->setAction(&scene->_sequenceManager, scene, 2531, &R2_GLOBALS._player, &scene->_actor3, NULL);
+ }
+ }
+
+ return true;
+}
+
+void Scene2530::Exit1::changeScene() {
+ Scene2530 *scene = (Scene2530 *)R2_GLOBALS._sceneManager._scene;
+
+ _enabled = false;
+ R2_GLOBALS._events.setCursor(CURSOR_ARROW);
+ R2_GLOBALS._player.disableControl();
+ scene->_sceneMode = 11;
+
+ Common::Point pt(108, 200);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, scene);
+}
+
+void Scene2530::postInit(SceneObjectList *OwnerList) {
+ loadScene(2530);
+ SceneExt::postInit();
+
+ _exit1.setDetails(Rect(68, 155, 147, 168), EXITCURSOR_S, 2000);
+ _exit1.setDest(Common::Point(108, 160));
+
+ if (R2_INVENTORY.getObjectScene(33) == 2530) {
+ _actor2.postInit();
+ _actor2.setup(2435, 1, 3);
+ _actor2.setPosition(Common::Point(299, 80));
+ _actor2.fixPriority(80);
+ _actor2.setDetails(2530, 28, -1, -1, 1, NULL);
+ }
+
+ _actor3.postInit();
+ if (R2_GLOBALS.getFlag(73)) {
+ _actor3.setup(2531, 4, 2);
+ _actor3.setPosition(Common::Point(154, 130));
+ } else {
+ _actor3.setup(2531, 4, 1);
+ _actor3.setPosition(Common::Point(173, 131));
+ }
+ _actor3.setDetails(2530, 22, -1, -1, 1, NULL);
+
+ R2_GLOBALS._player.postInit();
+ R2_GLOBALS._player.animate(ANIM_MODE_1, NULL);
+
+ if (R2_GLOBALS._player._characterIndex == 1) {
+ R2_GLOBALS._player.setVisage(2008);
+ R2_GLOBALS._player._moveDiff = Common::Point(3, 2);
+ } else {
+ R2_GLOBALS._player.setVisage(20);
+ R2_GLOBALS._player._moveDiff = Common::Point(5, 3);
+ }
+ R2_GLOBALS._player.setPosition(Common::Point(100, 200));
+
+ if (R2_GLOBALS._player._characterScene[1] == R2_GLOBALS._player._characterScene[2]) {
+ _actor1.postInit();
+ if (R2_GLOBALS._player._characterIndex == 1) {
+ _actor1.setup(20, 5, 1);
+ _actor1.setDetails(9002, 0, 4, 3, 1, NULL);
+ } else {
+ _actor1.setup(2008, 5, 1);
+ _actor1.setDetails(9001, 0, 5, 3, 1, NULL);
+ }
+ _actor1.setPosition(Common::Point(20, 130));
+ R2_GLOBALS._walkRegions.enableRegion(1);
+ }
+
+ _item2.setDetails(Rect(108, 90, 135, 205), 2530, 22, -1, -1, 1, NULL);
+ _item5.setDetails(Rect(115, 112, 206, 130), 2530, 25, -1, 27, 1, NULL);
+ _item3.setDetails(Rect(256, 64, 311, 85), 2530, 31, -1, 33, 1, NULL);
+ _item1.setDetails(Rect(0, 0, 320, 200), 2530, 0, 1, -1, 1, NULL);
+
+ R2_GLOBALS._player.disableControl();
+
+ if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 2000) {
+ R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 2530;
+ Common::Point pt(108, 150);
+ NpcMover *mover = new NpcMover();
+ R2_GLOBALS._player.addMover(mover, &pt, this);
+ } else {
+ R2_GLOBALS._player.setPosition(Common::Point(105, 145));
+ R2_GLOBALS._player.setStrip(3);
+ R2_GLOBALS._player.enableControl();
+ }
+}
+
+void Scene2530::signal() {
+ switch (_sceneMode) {
+ case 11:
+ g_globals->_sceneManager.changeScene(2000);
+ break;
+ case 2530:
+ R2_INVENTORY.setObjectScene(33, 2);
+ _actor2.remove();
+ break;
+ case 2531:
+ // No break on purpose
+ case 2532:
+ R2_GLOBALS.setFlag(73);
+ R2_GLOBALS._player.enableControl();
+ break;
+ case 2533:
+ R2_GLOBALS.clearFlag(73);
+ R2_GLOBALS._player.enableControl();
+ break;
+ default:
+ R2_GLOBALS._player.enableControl();
+ break;
+ }
+}
+
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.h b/engines/tsage/ringworld2/ringworld2_scenes2.h
index 82898a45dd..bef1fc9ea8 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes2.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes2.h
@@ -383,6 +383,67 @@ public:
virtual void signal();
};
+class Scene2525 : public SceneExt {
+ class Item5 : public NamedHotspot {
+ public:
+ virtual bool startAction(CursorType action, Event &event);
+ };
+
+ class Actor3 : public SceneActor {
+ public:
+ bool startAction(CursorType action, Event &event);
+ };
+
+ class Exit1 : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+public:
+ NamedHotspot _item1;
+ NamedHotspot _item2;
+ NamedHotspot _item3;
+ NamedHotspot _item4;
+ Item5 _item5;
+ SceneActor _actor1;
+ SceneActor _actor2;
+ Actor3 _actor3;
+ Exit1 _exit1;
+ SequenceManager _sequenceManager;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
+ virtual void signal();
+};
+
+class Scene2530 : public SceneExt {
+ class Actor2 : public SceneActor {
+ public:
+ bool startAction(CursorType action, Event &event);
+ };
+ class Actor3 : public SceneActor {
+ public:
+ bool startAction(CursorType action, Event &event);
+ };
+
+ class Exit1 : public SceneExit {
+ public:
+ virtual void changeScene();
+ };
+public:
+ NamedHotspot _item1;
+ NamedHotspot _item2;
+ NamedHotspot _item3;
+ NamedHotspot _item4;
+ NamedHotspot _item5;
+ SceneActor _actor1;
+ Actor2 _actor2;
+ Actor3 _actor3;
+ Exit1 _exit1;
+ SequenceManager _sequenceManager;
+
+ virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void signal();
+};
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_speakers.cpp b/engines/tsage/ringworld2/ringworld2_speakers.cpp
index 8c8bd7171a..cff7334090 100644
--- a/engines/tsage/ringworld2/ringworld2_speakers.cpp
+++ b/engines/tsage/ringworld2/ringworld2_speakers.cpp
@@ -128,7 +128,7 @@ void VisualSpeaker::setText(const Common::String &msg) {
//_sceneText.clone();
_sceneText.setPosition(_textPos);
- _sceneText.setPriority(0x100);
+ _sceneText.fixPriority(256);
// If subtitles are turned off, don't show the text
if (!(R2_GLOBALS._speechSubtitles & SPEECH_TEXT)) {
@@ -148,7 +148,7 @@ void VisualSpeaker::setText(const Common::String &msg) {
++numWords;
_numFrames = numWords * 30 + 120;
- setFrame(_numFrames);
+ setDelay(_numFrames);
} else {
_numFrames = 1;
}
@@ -185,6 +185,11 @@ void VisualSpeaker::setFrame(int numFrames) {
_frameNumber = R2_GLOBALS._events.getFrameNumber();
}
+void VisualSpeaker::setDelay(int delay) {
+ _delayAmount = delay;
+ _frameNumber = R2_GLOBALS._events.getFrameNumber();
+}
+
/*--------------------------------------------------------------------------*/
SpeakerMiranda300::SpeakerMiranda300(): VisualSpeaker() {
diff --git a/engines/tsage/ringworld2/ringworld2_speakers.h b/engines/tsage/ringworld2/ringworld2_speakers.h
index e6a805f31b..b8ad17886a 100644
--- a/engines/tsage/ringworld2/ringworld2_speakers.h
+++ b/engines/tsage/ringworld2/ringworld2_speakers.h
@@ -59,6 +59,8 @@ public:
virtual void setText(const Common::String &msg);
virtual void proc15() {}
virtual void proc16();
+
+ void setDelay(int delay);
};
class SpeakerMiranda300 : public VisualSpeaker {
diff --git a/gui/credits.h b/gui/credits.h
index 08be2e0534..dd839c2c3b 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -39,6 +39,7 @@ static const char *credits[] = {
"C0""Pawel Kolodziejski",
"C2""Codecs, iMUSE, Smush, etc.",
"C0""Gregory Montoir",
+"C2""(retired)",
"C0""Eugene Sandulenko",
"C2""FT INSANE, MM NES, MM C64, game detection, Herc/CGA",
"C0""Ludvig Strigeus",
@@ -49,6 +50,7 @@ static const char *credits[] = {
"C2""(retired)",
"C0""Travis Howell",
"C0""Gregory Montoir",
+"C2""(retired)",
"C0""Eugene Sandulenko",
"",
"C1""AGI",
@@ -81,6 +83,7 @@ static const char *credits[] = {
"C2""(retired)",
"C0""Pawel Kolodziejski",
"C0""Gregory Montoir",
+"C2""(retired)",
"C0""Kari Salminen",
"C0""Eugene Sandulenko",
"",
@@ -128,6 +131,7 @@ static const char *credits[] = {
"C0""Oystein Eftevaag",
"C0""Florian Kagerer",
"C0""Gregory Montoir",
+"C2""(retired)",
"C0""Johannes Schickel",
"",
"C1""Lastexpress",
@@ -157,6 +161,7 @@ static const char *credits[] = {
"C0""David Eriksson",
"C2""(retired)",
"C0""Gregory Montoir",
+"C2""(retired)",
"C0""Joost Peters",
"",
"C1""SAGA",
@@ -230,6 +235,7 @@ static const char *credits[] = {
"",
"C1""Touch\351",
"C0""Gregory Montoir",
+"C2""(retired)",
"",
"C1""TsAGE",
"C0""Arnaud Boutonn\351",
@@ -237,6 +243,7 @@ static const char *credits[] = {
"",
"C1""Tucker",
"C0""Gregory Montoir",
+"C2""(retired)",
"",
"",
"C1""Backend Teams",
diff --git a/video/qt_decoder.cpp b/video/qt_decoder.cpp
index 74bf533e62..4a57ac405d 100644
--- a/video/qt_decoder.cpp
+++ b/video/qt_decoder.cpp
@@ -56,155 +56,42 @@ namespace Video {
////////////////////////////////////////////
QuickTimeDecoder::QuickTimeDecoder() {
- _curFrame = -1;
- _startTime = _nextFrameStartTime = 0;
+ _setStartTime = false;
_audHandle = Audio::SoundHandle();
_scaledSurface = 0;
_dirtyPalette = false;
_palette = 0;
+ _width = _height = 0;
+ _needUpdate = false;
}
QuickTimeDecoder::~QuickTimeDecoder() {
close();
}
-uint16 QuickTimeDecoder::getWidth() const {
- if (_videoTrackIndex < 0)
- return 0;
-
- return (Common::Rational(_tracks[_videoTrackIndex]->width) / getScaleFactorX()).toInt();
-}
-
-uint16 QuickTimeDecoder::getHeight() const {
- if (_videoTrackIndex < 0)
- return 0;
-
- return (Common::Rational(_tracks[_videoTrackIndex]->height) / getScaleFactorY()).toInt();
-}
-
-uint32 QuickTimeDecoder::getFrameCount() const {
- if (_videoTrackIndex < 0)
- return 0;
-
- return _tracks[_videoTrackIndex]->frameCount;
-}
-
-Common::Rational QuickTimeDecoder::getScaleFactorX() const {
- if (_videoTrackIndex < 0)
- return 1;
-
- return (_scaleFactorX * _tracks[_videoTrackIndex]->scaleFactorX);
-}
-
-Common::Rational QuickTimeDecoder::getScaleFactorY() const {
- if (_videoTrackIndex < 0)
- return 1;
+int32 QuickTimeDecoder::getCurFrame() const {
+ // TODO: This is rather simplistic and doesn't take edits that
+ // repeat sections of the media into account. Doing that
+ // over-complicates things and shouldn't be necessary, but
+ // it would be nice to have in the future.
- return (_scaleFactorY * _tracks[_videoTrackIndex]->scaleFactorY);
-}
+ int32 frame = -1;
-uint32 QuickTimeDecoder::getFrameDuration() {
- if (_videoTrackIndex < 0)
- return 0;
+ for (uint32 i = 0; i < _handlers.size(); i++)
+ if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeVideo)
+ frame += ((VideoTrackHandler *)_handlers[i])->getCurFrame() + 1;
- uint32 curFrameIndex = 0;
- for (int32 i = 0; i < _tracks[_videoTrackIndex]->timeToSampleCount; i++) {
- curFrameIndex += _tracks[_videoTrackIndex]->timeToSample[i].count;
- if ((uint32)_curFrame < curFrameIndex) {
- // Ok, now we have what duration this frame has.
- return _tracks[_videoTrackIndex]->timeToSample[i].duration;
- }
- }
-
- // This should never occur
- error ("Cannot find duration for frame %d", _curFrame);
- return 0;
-}
-
-Graphics::PixelFormat QuickTimeDecoder::getPixelFormat() const {
- Codec *codec = findDefaultVideoCodec();
-
- if (!codec)
- return Graphics::PixelFormat::createFormatCLUT8();
-
- return codec->getPixelFormat();
-}
-
-uint32 QuickTimeDecoder::findKeyFrame(uint32 frame) const {
- for (int i = _tracks[_videoTrackIndex]->keyframeCount - 1; i >= 0; i--)
- if (_tracks[_videoTrackIndex]->keyframes[i] <= frame)
- return _tracks[_videoTrackIndex]->keyframes[i];
-
- // If none found, we'll assume the requested frame is a key frame
return frame;
}
-void QuickTimeDecoder::seekToFrame(uint32 frame) {
- assert(_videoTrackIndex >= 0);
- assert(frame < _tracks[_videoTrackIndex]->frameCount);
-
- // Stop all audio (for now)
- stopAudio();
-
- // Track down the keyframe
- _curFrame = findKeyFrame(frame) - 1;
- while (_curFrame < (int32)frame - 1)
- decodeNextFrame();
-
- // Map out the starting point
- _nextFrameStartTime = 0;
- uint32 curFrame = 0;
-
- for (int32 i = 0; i < _tracks[_videoTrackIndex]->timeToSampleCount && curFrame < frame; i++) {
- for (int32 j = 0; j < _tracks[_videoTrackIndex]->timeToSample[i].count && curFrame < frame; j++) {
- curFrame++;
- _nextFrameStartTime += _tracks[_videoTrackIndex]->timeToSample[i].duration;
- }
- }
-
- // Adjust the video starting point
- const Audio::Timestamp curVideoTime(0, _nextFrameStartTime, _tracks[_videoTrackIndex]->timeScale);
- _startTime = g_system->getMillis() - curVideoTime.msecs();
- resetPauseStartTime();
-
- // Adjust the audio starting point
- if (_audioTrackIndex >= 0) {
- _audioStartOffset = curVideoTime;
-
- // Seek to the new audio location
- setAudioStreamPos(_audioStartOffset);
-
- // Restart the audio
- startAudio();
-
- // Pause the audio again if we're still paused
- if (isPaused() && _audStream)
- g_system->getMixer()->pauseHandle(_audHandle, true);
- }
-}
-
-void QuickTimeDecoder::seekToTime(Audio::Timestamp time) {
- // Use makeQuickTimeStream() instead
- if (_videoTrackIndex < 0)
- error("Audio-only seeking not supported");
-
- // Try to find the last frame that should have been decoded
- uint32 frame = 0;
- Audio::Timestamp totalDuration(0, _tracks[_videoTrackIndex]->timeScale);
- bool done = false;
+uint32 QuickTimeDecoder::getFrameCount() const {
+ uint32 count = 0;
- for (int32 i = 0; i < _tracks[_videoTrackIndex]->timeToSampleCount && !done; i++) {
- for (int32 j = 0; j < _tracks[_videoTrackIndex]->timeToSample[i].count; j++) {
- totalDuration = totalDuration.addFrames(_tracks[_videoTrackIndex]->timeToSample[i].duration);
- if (totalDuration > time) {
- done = true;
- break;
- }
- frame++;
- }
- }
+ for (uint32 i = 0; i < _handlers.size(); i++)
+ if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeVideo)
+ count += ((VideoTrackHandler *)_handlers[i])->getFrameCount();
- seekToFrame(frame);
+ return count;
}
void QuickTimeDecoder::startAudio() {
@@ -224,98 +111,109 @@ void QuickTimeDecoder::pauseVideoIntern(bool pause) {
g_system->getMixer()->pauseHandle(_audHandle, pause);
}
-Codec *QuickTimeDecoder::findDefaultVideoCodec() const {
- if (_videoTrackIndex < 0 || _tracks[_videoTrackIndex]->sampleDescs.empty())
- return 0;
+QuickTimeDecoder::VideoTrackHandler *QuickTimeDecoder::findNextVideoTrack() const {
+ VideoTrackHandler *bestTrack = 0;
+ int32 num;
+ uint32 bestTime = 0xffffffff;
+
+ for (uint32 i = 0; i < _handlers.size(); i++) {
+ if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeVideo && !_handlers[i]->endOfTrack()) {
+ VideoTrackHandler *track = (VideoTrackHandler *)_handlers[i];
+ uint32 time = track->getNextFrameStartTime();
+
+ if (time < bestTime) {
+ bestTime = time;
+ bestTrack = track;
+ num = i;
+ }
+ }
+ }
- return ((VideoSampleDesc *)_tracks[_videoTrackIndex]->sampleDescs[0])->_videoCodec;
+ return bestTrack;
}
const Graphics::Surface *QuickTimeDecoder::decodeNextFrame() {
- if (_videoTrackIndex < 0 || _curFrame >= (int32)getFrameCount() - 1)
+ if (!_nextVideoTrack)
return 0;
- if (_startTime == 0)
- _startTime = g_system->getMillis();
-
- _curFrame++;
- _nextFrameStartTime += getFrameDuration();
-
- // Update the audio while we're at it
- updateAudioBuffer();
-
- // Get the next packet
- uint32 descId;
- Common::SeekableReadStream *frameData = getNextFramePacket(descId);
-
- if (!frameData || !descId || descId > _tracks[_videoTrackIndex]->sampleDescs.size())
- return 0;
+ const Graphics::Surface *frame = _nextVideoTrack->decodeNextFrame();
- // Find which video description entry we want
- VideoSampleDesc *entry = (VideoSampleDesc *)_tracks[_videoTrackIndex]->sampleDescs[descId - 1];
+ if (!_setStartTime) {
+ _startTime = g_system->getMillis();
+ _setStartTime = true;
+ }
- if (!entry->_videoCodec)
- return 0;
+ _nextVideoTrack = findNextVideoTrack();
+ _needUpdate = false;
- const Graphics::Surface *frame = entry->_videoCodec->decodeImage(frameData);
- delete frameData;
+ // Update audio buffers too
+ // (needs to be done after we find the next track)
+ for (uint32 i = 0; i < _handlers.size(); i++)
+ if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeAudio)
+ ((AudioTrackHandler *)_handlers[i])->updateBuffer();
- // Update the palette
- if (entry->_videoCodec->containsPalette()) {
- // The codec itself contains a palette
- if (entry->_videoCodec->hasDirtyPalette()) {
- _palette = entry->_videoCodec->getPalette();
- _dirtyPalette = true;
- }
- } else {
- // Check if the video description has been updated
- byte *palette = entry->_palette;
-
- if (palette != _palette) {
- _palette = palette;
- _dirtyPalette = true;
- }
+ if (_scaledSurface) {
+ scaleSurface(frame, _scaledSurface, _scaleFactorX, _scaleFactorY);
+ return _scaledSurface;
}
- return scaleSurface(frame);
+ return frame;
}
-const Graphics::Surface *QuickTimeDecoder::scaleSurface(const Graphics::Surface *frame) {
- if (getScaleFactorX() == 1 && getScaleFactorY() == 1)
- return frame;
+void QuickTimeDecoder::scaleSurface(const Graphics::Surface *src, Graphics::Surface *dst, Common::Rational scaleFactorX, Common::Rational scaleFactorY) {
+ assert(src && dst);
- assert(_scaledSurface);
-
- for (int32 j = 0; j < _scaledSurface->h; j++)
- for (int32 k = 0; k < _scaledSurface->w; k++)
- memcpy(_scaledSurface->getBasePtr(k, j), frame->getBasePtr((k * getScaleFactorX()).toInt() , (j * getScaleFactorY()).toInt()), frame->format.bytesPerPixel);
-
- return _scaledSurface;
+ for (int32 j = 0; j < dst->h; j++)
+ for (int32 k = 0; k < dst->w; k++)
+ memcpy(dst->getBasePtr(k, j), src->getBasePtr((k * scaleFactorX).toInt() , (j * scaleFactorY).toInt()), src->format.bytesPerPixel);
}
bool QuickTimeDecoder::endOfVideo() const {
- return (!_audStream || _audStream->endOfData()) && (!findDefaultVideoCodec() || SeekableVideoDecoder::endOfVideo());
+ if (!isVideoLoaded())
+ return true;
+
+ for (uint32 i = 0; i < _handlers.size(); i++)
+ if (!_handlers[i]->endOfTrack())
+ return false;
+
+ return true;
}
uint32 QuickTimeDecoder::getElapsedTime() const {
- if (_audStream)
- return g_system->getMixer()->getSoundElapsedTime(_audHandle) + _audioStartOffset.msecs();
+ // TODO: Convert to multi-track
+ if (_audStream) {
+ // Use the audio time if present and the audio track's time is less than the
+ // total length of the audio track. The audio track can end before the video
+ // track, so we need to fall back on the getMillis() time tracking in that
+ // case.
+ uint32 time = g_system->getMixer()->getSoundElapsedTime(_audHandle) + _audioStartOffset.msecs();
+ if (time < _tracks[_audioTrackIndex]->mediaDuration * 1000 / _tracks[_audioTrackIndex]->timeScale)
+ return time;
+ }
+ // Just use time elapsed since the beginning
return SeekableVideoDecoder::getElapsedTime();
}
uint32 QuickTimeDecoder::getTimeToNextFrame() const {
- if (endOfVideo() || _curFrame < 0)
+ if (_needUpdate)
return 0;
- // Convert from the QuickTime rate base to 1000
- uint32 nextFrameStartTime = _nextFrameStartTime * 1000 / _tracks[_videoTrackIndex]->timeScale;
- uint32 elapsedTime = getElapsedTime();
+ if (_nextVideoTrack) {
+ uint32 nextFrameStartTime = _nextVideoTrack->getNextFrameStartTime();
- if (nextFrameStartTime <= elapsedTime)
- return 0;
+ if (nextFrameStartTime == 0)
+ return 0;
+
+ // TODO: Add support for rate modification
+
+ uint32 elapsedTime = getElapsedTime();
+
+ if (elapsedTime < nextFrameStartTime)
+ return nextFrameStartTime - elapsedTime;
+ }
- return nextFrameStartTime - elapsedTime;
+ return 0;
}
bool QuickTimeDecoder::loadFile(const Common::String &filename) {
@@ -337,30 +235,49 @@ bool QuickTimeDecoder::loadStream(Common::SeekableReadStream *stream) {
void QuickTimeDecoder::init() {
Audio::QuickTimeAudioDecoder::init();
- _videoTrackIndex = -1;
_startTime = 0;
-
- // Find video streams
- for (uint32 i = 0; i < _tracks.size(); i++)
- if (_tracks[i]->codecType == CODEC_TYPE_VIDEO && _videoTrackIndex < 0)
- _videoTrackIndex = i;
+ _setStartTime = false;
// Start the audio codec if we've got one that we can handle
if (_audStream) {
startAudio();
_audioStartOffset = Audio::Timestamp(0);
+
+ // TODO: Support multiple audio tracks
+ // For now, just push back a handler for the first audio track
+ _handlers.push_back(new AudioTrackHandler(this, _tracks[_audioTrackIndex]));
}
- // Initialize video, if present
- if (_videoTrackIndex >= 0) {
- for (uint32 i = 0; i < _tracks[_videoTrackIndex]->sampleDescs.size(); i++)
- ((VideoSampleDesc *)_tracks[_videoTrackIndex]->sampleDescs[i])->initCodec();
+ // Initialize all the video tracks
+ for (uint32 i = 0; i < _tracks.size(); i++) {
+ if (_tracks[i]->codecType == CODEC_TYPE_VIDEO) {
+ for (uint32 j = 0; j < _tracks[i]->sampleDescs.size(); j++)
+ ((VideoSampleDesc *)_tracks[i]->sampleDescs[j])->initCodec();
- if (getScaleFactorX() != 1 || getScaleFactorY() != 1) {
+ _handlers.push_back(new VideoTrackHandler(this, _tracks[i]));
+ }
+ }
+
+ // Prepare the first video track
+ _nextVideoTrack = findNextVideoTrack();
+
+ if (_nextVideoTrack) {
+ // Initialize the scaled surface
+ if (_scaleFactorX != 1 || _scaleFactorY != 1) {
// We have to initialize the scaled surface
_scaledSurface = new Graphics::Surface();
- _scaledSurface->create(getWidth(), getHeight(), getPixelFormat());
+ _scaledSurface->create((_nextVideoTrack->getWidth() / _scaleFactorX).toInt(),
+ (_nextVideoTrack->getHeight() / _scaleFactorY).toInt(), getPixelFormat());
+ _width = _scaledSurface->w;
+ _height = _scaledSurface->h;
+ } else {
+ _width = _nextVideoTrack->getWidth().toInt();
+ _height = _nextVideoTrack->getHeight().toInt();
}
+
+ _needUpdate = true;
+ } else {
+ _needUpdate = false;
}
}
@@ -464,6 +381,7 @@ Common::QuickTimeParser::SampleDesc *QuickTimeDecoder::readSampleDesc(Track *tra
void QuickTimeDecoder::close() {
stopAudio();
+ freeAllTrackHandlers();
if (_scaledSurface) {
_scaledSurface->free();
@@ -471,93 +389,46 @@ void QuickTimeDecoder::close() {
_scaledSurface = 0;
}
+ _width = _height = 0;
+
Common::QuickTimeParser::close();
SeekableVideoDecoder::reset();
}
-Common::SeekableReadStream *QuickTimeDecoder::getNextFramePacket(uint32 &descId) {
- if (_videoTrackIndex < 0)
- return NULL;
-
- // First, we have to track down which chunk holds the sample and which sample in the chunk contains the frame we are looking for.
- int32 totalSampleCount = 0;
- int32 sampleInChunk = 0;
- int32 actualChunk = -1;
- uint32 sampleToChunkIndex = 0;
+void QuickTimeDecoder::freeAllTrackHandlers() {
+ for (uint32 i = 0; i < _handlers.size(); i++)
+ delete _handlers[i];
- for (uint32 i = 0; i < _tracks[_videoTrackIndex]->chunkCount; i++) {
- if (sampleToChunkIndex < _tracks[_videoTrackIndex]->sampleToChunkCount && i >= _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex].first)
- sampleToChunkIndex++;
-
- totalSampleCount += _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex - 1].count;
-
- if (totalSampleCount > getCurFrame()) {
- actualChunk = i;
- descId = _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex - 1].id;
- sampleInChunk = _tracks[_videoTrackIndex]->sampleToChunk[sampleToChunkIndex - 1].count - totalSampleCount + getCurFrame();
- break;
- }
- }
-
- if (actualChunk < 0) {
- warning ("Could not find data for frame %d", getCurFrame());
- return NULL;
- }
-
- // Next seek to that frame
- _fd->seek(_tracks[_videoTrackIndex]->chunkOffsets[actualChunk]);
-
- // Then, if the chunk holds more than one frame, seek to where the frame we want is located
- for (int32 i = getCurFrame() - sampleInChunk; i < getCurFrame(); i++) {
- if (_tracks[_videoTrackIndex]->sampleSize != 0)
- _fd->skip(_tracks[_videoTrackIndex]->sampleSize);
- else
- _fd->skip(_tracks[_videoTrackIndex]->sampleSizes[i]);
- }
+ _handlers.clear();
+}
- // Finally, read in the raw data for the frame
- //printf ("Frame Data[%d]: Offset = %d, Size = %d\n", getCurFrame(), _fd->pos(), _tracks[_videoTrackIndex]->sampleSizes[getCurFrame()]);
+void QuickTimeDecoder::seekToTime(Audio::Timestamp time) {
+ // Sets all tracks to this time
+ for (uint32 i = 0; i < _handlers.size(); i++)
+ _handlers[i]->seekToTime(time);
- if (_tracks[_videoTrackIndex]->sampleSize != 0)
- return _fd->readStream(_tracks[_videoTrackIndex]->sampleSize);
+ // Reset our start time
+ _startTime = g_system->getMillis() - time.msecs();
+ _setStartTime = true;
+ resetPauseStartTime();
- return _fd->readStream(_tracks[_videoTrackIndex]->sampleSizes[getCurFrame()]);
+ // Reset the next video track too
+ _nextVideoTrack = findNextVideoTrack();
+ _needUpdate = _nextVideoTrack != 0;
}
void QuickTimeDecoder::updateAudioBuffer() {
- if (!_audStream)
- return;
-
- uint32 numberOfChunksNeeded = 0;
-
- if (_videoTrackIndex < 0 || _curFrame == (int32)_tracks[_videoTrackIndex]->frameCount - 1) {
- // If we have no video, there's nothing to base our buffer against
- // However, one must ask why a QuickTimeDecoder is being used instead of the nice makeQuickTimeStream() function
-
- // If we're on the last frame, make sure all audio remaining is buffered
- numberOfChunksNeeded = _tracks[_audioTrackIndex]->chunkCount;
- } else {
- Audio::QuickTimeAudioDecoder::AudioSampleDesc *entry = (Audio::QuickTimeAudioDecoder::AudioSampleDesc *)_tracks[_audioTrackIndex]->sampleDescs[0];
-
- // Calculate the amount of chunks we need in memory until the next frame
- uint32 timeToNextFrame = getTimeToNextFrame();
- uint32 timeFilled = 0;
- uint32 curAudioChunk = _curAudioChunk - _audStream->numQueuedStreams();
-
- for (; timeFilled < timeToNextFrame && curAudioChunk < _tracks[_audioTrackIndex]->chunkCount; numberOfChunksNeeded++, curAudioChunk++) {
- uint32 sampleCount = entry->getAudioChunkSampleCount(curAudioChunk);
- assert(sampleCount);
-
- timeFilled += sampleCount * 1000 / entry->_sampleRate;
- }
+ // Updates the audio buffers for all audio tracks
+ for (uint32 i = 0; i < _handlers.size(); i++)
+ if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeAudio)
+ ((AudioTrackHandler *)_handlers[i])->updateBuffer();
+}
- // Add a couple extra to ensure we don't underrun
- numberOfChunksNeeded += 3;
- }
+Graphics::PixelFormat QuickTimeDecoder::getPixelFormat() const {
+ if (_nextVideoTrack)
+ return _nextVideoTrack->getPixelFormat();
- // Keep three streams in buffer so that if/when the first two end, it goes right into the next
- while (_audStream->numQueuedStreams() < numberOfChunksNeeded && _curAudioChunk < _tracks[_audioTrackIndex]->chunkCount)
- queueNextAudioChunk();
+ return Graphics::PixelFormat();
}
QuickTimeDecoder::VideoSampleDesc::VideoSampleDesc(Common::QuickTimeParser::Track *parentTrack, uint32 codecTag) : Common::QuickTimeParser::SampleDesc(parentTrack, codecTag) {
@@ -612,4 +483,383 @@ void QuickTimeDecoder::VideoSampleDesc::initCodec() {
}
}
+bool QuickTimeDecoder::endOfVideoTracks() const {
+ for (uint32 i = 0; i < _handlers.size(); i++)
+ if (_handlers[i]->getTrackType() == TrackHandler::kTrackTypeVideo && !_handlers[i]->endOfTrack())
+ return false;
+
+ return true;
+}
+
+QuickTimeDecoder::TrackHandler::TrackHandler(QuickTimeDecoder *decoder, Track *parent) : _decoder(decoder), _parent(parent), _fd(_decoder->_fd) {
+ _curEdit = 0;
+}
+
+bool QuickTimeDecoder::TrackHandler::endOfTrack() {
+ // A track is over when we've finished going through all edits
+ return _curEdit == _parent->editCount;
+}
+
+QuickTimeDecoder::AudioTrackHandler::AudioTrackHandler(QuickTimeDecoder *decoder, Track *parent) : TrackHandler(decoder, parent) {
+}
+
+void QuickTimeDecoder::AudioTrackHandler::updateBuffer() {
+ if (!_decoder->_audStream)
+ return;
+
+ uint32 numberOfChunksNeeded = 0;
+
+ if (_decoder->endOfVideoTracks()) {
+ // If we have no video left (or no video), there's nothing to base our buffer against
+ numberOfChunksNeeded = _parent->chunkCount;
+ } else {
+ Audio::QuickTimeAudioDecoder::AudioSampleDesc *entry = (Audio::QuickTimeAudioDecoder::AudioSampleDesc *)_parent->sampleDescs[0];
+
+ // Calculate the amount of chunks we need in memory until the next frame
+ uint32 timeToNextFrame = _decoder->getTimeToNextFrame();
+ uint32 timeFilled = 0;
+ uint32 curAudioChunk = _decoder->_curAudioChunk - _decoder->_audStream->numQueuedStreams();
+
+ for (; timeFilled < timeToNextFrame && curAudioChunk < _parent->chunkCount; numberOfChunksNeeded++, curAudioChunk++) {
+ uint32 sampleCount = entry->getAudioChunkSampleCount(curAudioChunk);
+ assert(sampleCount);
+
+ timeFilled += sampleCount * 1000 / entry->_sampleRate;
+ }
+
+ // Add a couple extra to ensure we don't underrun
+ numberOfChunksNeeded += 3;
+ }
+
+ // Keep three streams in buffer so that if/when the first two end, it goes right into the next
+ while (_decoder->_audStream->numQueuedStreams() < numberOfChunksNeeded && _decoder->_curAudioChunk < _parent->chunkCount)
+ _decoder->queueNextAudioChunk();
+}
+
+bool QuickTimeDecoder::AudioTrackHandler::endOfTrack() {
+ // TODO: Handle edits
+ return (_decoder->_curAudioChunk == _parent->chunkCount) && _decoder->_audStream->endOfData();
+}
+
+void QuickTimeDecoder::AudioTrackHandler::seekToTime(Audio::Timestamp time) {
+ if (_decoder->_audStream) {
+ // Stop all audio
+ _decoder->stopAudio();
+
+ _decoder->_audioStartOffset = time;
+
+ // Seek to the new audio location
+ _decoder->setAudioStreamPos(_decoder->_audioStartOffset);
+
+ // Restart the audio
+ _decoder->startAudio();
+
+ // Pause the audio again if we're still paused
+ if (_decoder->isPaused() && _decoder->_audStream)
+ g_system->getMixer()->pauseHandle(_decoder->_audHandle, true);
+ }
+}
+
+QuickTimeDecoder::VideoTrackHandler::VideoTrackHandler(QuickTimeDecoder *decoder, Common::QuickTimeParser::Track *parent) : TrackHandler(decoder, parent) {
+ if (_parent->scaleFactorX != 1 || _parent->scaleFactorY != 1) {
+ _scaledSurface = new Graphics::Surface();
+ _scaledSurface->create(getWidth().toInt(), getHeight().toInt(), getPixelFormat());
+ } else {
+ _scaledSurface = 0;
+ }
+
+ enterNewEditList(false);
+
+ _holdNextFrameStartTime = false;
+ _curFrame = -1;
+ _durationOverride = -1;
+
+}
+
+QuickTimeDecoder::VideoTrackHandler::~VideoTrackHandler() {
+ if (_scaledSurface) {
+ _scaledSurface->free();
+ delete _scaledSurface;
+ }
+}
+
+const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::decodeNextFrame() {
+ if (endOfTrack())
+ return 0;
+
+ const Graphics::Surface *frame = bufferNextFrame();
+
+ if (_holdNextFrameStartTime) {
+ // Don't set the next frame start time here; we just did a seek
+ _holdNextFrameStartTime = false;
+ } else if (_durationOverride >= 0) {
+ // Use our own duration from the edit list calculation
+ _nextFrameStartTime += _durationOverride;
+ _durationOverride = -1;
+ } else {
+ _nextFrameStartTime += getFrameDuration();
+ }
+
+ // Update the edit list, if applicable
+ // HACK: We're also accepting the time minus one because edit lists
+ // aren't as accurate as one would hope.
+ if (!endOfTrack() && getRateAdjustedFrameTime() >= getCurEditTimeOffset() + getCurEditTrackDuration() - 1) {
+ _curEdit++;
+
+ if (!endOfTrack())
+ enterNewEditList(true);
+ }
+
+ if (_scaledSurface) {
+ _decoder->scaleSurface(frame, _scaledSurface, _parent->scaleFactorX, _parent->scaleFactorY);
+ return _scaledSurface;
+ }
+
+ return frame;
+}
+
+void QuickTimeDecoder::VideoTrackHandler::enterNewEditList(bool bufferFrames) {
+ // Bypass all empty edit lists first
+ while (!endOfTrack() && _parent->editList[_curEdit].mediaTime == -1)
+ _curEdit++;
+
+ if (endOfTrack())
+ return;
+
+ uint32 frameNum = 0;
+ bool done = false;
+ uint32 totalDuration = 0;
+ uint32 prevDuration = 0;
+
+ // Track down where the mediaTime is in the media
+ for (int32 i = 0; i < _parent->timeToSampleCount && !done; i++) {
+ for (int32 j = 0; j < _parent->timeToSample[i].count; j++) {
+ if (totalDuration == (uint32)_parent->editList[_curEdit].mediaTime) {
+ done = true;
+ prevDuration = totalDuration;
+ break;
+ } else if (totalDuration > (uint32)_parent->editList[_curEdit].mediaTime) {
+ done = true;
+ frameNum--;
+ break;
+ }
+
+ prevDuration = totalDuration;
+ totalDuration += _parent->timeToSample[i].duration;
+ frameNum++;
+ }
+ }
+
+ if (bufferFrames) {
+ // Track down the keyframe
+ _curFrame = findKeyFrame(frameNum) - 1;
+ while (_curFrame < (int32)frameNum - 1)
+ bufferNextFrame();
+ } else {
+ _curFrame = frameNum - 1;
+ }
+
+ _nextFrameStartTime = getCurEditTimeOffset();
+
+ // Set an override for the duration since we came up in-between two frames
+ if (prevDuration != totalDuration)
+ _durationOverride = totalDuration - prevDuration;
+}
+
+const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::bufferNextFrame() {
+ _curFrame++;
+
+ // Get the next packet
+ uint32 descId;
+ Common::SeekableReadStream *frameData = getNextFramePacket(descId);
+
+ if (!frameData || !descId || descId > _parent->sampleDescs.size())
+ return 0;
+
+ // Find which video description entry we want
+ VideoSampleDesc *entry = (VideoSampleDesc *)_parent->sampleDescs[descId - 1];
+
+ if (!entry->_videoCodec)
+ return 0;
+
+ const Graphics::Surface *frame = entry->_videoCodec->decodeImage(frameData);
+ delete frameData;
+
+ // Update the palette
+ if (entry->_videoCodec->containsPalette()) {
+ // The codec itself contains a palette
+ if (entry->_videoCodec->hasDirtyPalette()) {
+ _decoder->_palette = entry->_videoCodec->getPalette();
+ _decoder->_dirtyPalette = true;
+ }
+ } else {
+ // Check if the video description has been updated
+ byte *palette = entry->_palette;
+
+ if (palette !=_decoder-> _palette) {
+ _decoder->_palette = palette;
+ _decoder->_dirtyPalette = true;
+ }
+ }
+
+ return frame;
+}
+
+uint32 QuickTimeDecoder::VideoTrackHandler::getNextFrameStartTime() {
+ if (endOfTrack())
+ return 0;
+
+ // Convert to milliseconds so the tracks can be compared
+ return getRateAdjustedFrameTime() * 1000 / _parent->timeScale;
+}
+
+uint32 QuickTimeDecoder::VideoTrackHandler::getFrameCount() {
+ return _parent->frameCount;
+}
+
+uint32 QuickTimeDecoder::VideoTrackHandler::getFrameDuration() {
+ uint32 curFrameIndex = 0;
+ for (int32 i = 0; i < _parent->timeToSampleCount; i++) {
+ curFrameIndex += _parent->timeToSample[i].count;
+ if ((uint32)_curFrame < curFrameIndex) {
+ // Ok, now we have what duration this frame has.
+ return _parent->timeToSample[i].duration;
+ }
+ }
+
+ // This should never occur
+ error("Cannot find duration for frame %d", _curFrame);
+ return 0;
+}
+
+Common::SeekableReadStream *QuickTimeDecoder::VideoTrackHandler::getNextFramePacket(uint32 &descId) {
+ // First, we have to track down which chunk holds the sample and which sample in the chunk contains the frame we are looking for.
+ int32 totalSampleCount = 0;
+ int32 sampleInChunk = 0;
+ int32 actualChunk = -1;
+ uint32 sampleToChunkIndex = 0;
+
+ for (uint32 i = 0; i < _parent->chunkCount; i++) {
+ if (sampleToChunkIndex < _parent->sampleToChunkCount && i >= _parent->sampleToChunk[sampleToChunkIndex].first)
+ sampleToChunkIndex++;
+
+ totalSampleCount += _parent->sampleToChunk[sampleToChunkIndex - 1].count;
+
+ if (totalSampleCount > _curFrame) {
+ actualChunk = i;
+ descId = _parent->sampleToChunk[sampleToChunkIndex - 1].id;
+ sampleInChunk = _parent->sampleToChunk[sampleToChunkIndex - 1].count - totalSampleCount + _curFrame;
+ break;
+ }
+ }
+
+ if (actualChunk < 0) {
+ warning("Could not find data for frame %d", _curFrame);
+ return 0;
+ }
+
+ // Next seek to that frame
+ _fd->seek(_parent->chunkOffsets[actualChunk]);
+
+ // Then, if the chunk holds more than one frame, seek to where the frame we want is located
+ for (int32 i = _curFrame - sampleInChunk; i < _curFrame; i++) {
+ if (_parent->sampleSize != 0)
+ _fd->skip(_parent->sampleSize);
+ else
+ _fd->skip(_parent->sampleSizes[i]);
+ }
+
+ // Finally, read in the raw data for the frame
+ //debug("Frame Data[%d]: Offset = %d, Size = %d", _curFrame, _fd->pos(), _parent->sampleSizes[_curFrame]);
+
+ if (_parent->sampleSize != 0)
+ return _fd->readStream(_parent->sampleSize);
+
+ return _fd->readStream(_parent->sampleSizes[_curFrame]);
+}
+
+uint32 QuickTimeDecoder::VideoTrackHandler::findKeyFrame(uint32 frame) const {
+ for (int i = _parent->keyframeCount - 1; i >= 0; i--)
+ if (_parent->keyframes[i] <= frame)
+ return _parent->keyframes[i];
+
+ // If none found, we'll assume the requested frame is a key frame
+ return frame;
+}
+
+void QuickTimeDecoder::VideoTrackHandler::seekToTime(Audio::Timestamp time) {
+ // First, figure out what edit we're in
+ time = time.convertToFramerate(_parent->timeScale);
+
+ // Continue until we get to where we need to be
+ for (_curEdit = 0; !endOfTrack(); _curEdit++)
+ if ((uint32)time.totalNumberOfFrames() >= getCurEditTimeOffset() && (uint32)time.totalNumberOfFrames() < getCurEditTimeOffset() + getCurEditTrackDuration())
+ break;
+
+ // This track is done
+ if (endOfTrack())
+ return;
+
+ enterNewEditList(false);
+
+ // One extra check for the end of a track
+ if (endOfTrack())
+ return;
+
+ // Now we're in the edit and need to figure out what frame we need
+ while (getRateAdjustedFrameTime() < (uint32)time.totalNumberOfFrames()) {
+ _curFrame++;
+ if (_durationOverride >= 0) {
+ _nextFrameStartTime += _durationOverride;
+ _durationOverride = -1;
+ } else {
+ _nextFrameStartTime += getFrameDuration();
+ }
+ }
+
+ // All that's left is to figure out what our starting time is going to be
+ // Compare the starting point for the frame to where we need to be
+ _holdNextFrameStartTime = getRateAdjustedFrameTime() != (uint32)time.totalNumberOfFrames();
+
+ // If we went past the time, go back a frame
+ if (_holdNextFrameStartTime)
+ _curFrame--;
+
+ // Handle the keyframe here
+ int32 destinationFrame = _curFrame + 1;
+
+ assert(destinationFrame < (int32)_parent->frameCount);
+ _curFrame = findKeyFrame(destinationFrame) - 1;
+ while (_curFrame < destinationFrame - 1)
+ bufferNextFrame();
+}
+
+Common::Rational QuickTimeDecoder::VideoTrackHandler::getWidth() const {
+ return Common::Rational(_parent->width) / _parent->scaleFactorX;
+}
+
+Common::Rational QuickTimeDecoder::VideoTrackHandler::getHeight() const {
+ return Common::Rational(_parent->height) / _parent->scaleFactorY;
+}
+
+Graphics::PixelFormat QuickTimeDecoder::VideoTrackHandler::getPixelFormat() const {
+ return ((VideoSampleDesc *)_parent->sampleDescs[0])->_videoCodec->getPixelFormat();
+}
+
+uint32 QuickTimeDecoder::VideoTrackHandler::getRateAdjustedFrameTime() const {
+ // Figure out what time the next frame is at taking the edit list rate into account
+ uint32 convertedTime = (Common::Rational(_nextFrameStartTime - getCurEditTimeOffset()) / _parent->editList[_curEdit].mediaRate).toInt();
+ return convertedTime + getCurEditTimeOffset();
+}
+
+uint32 QuickTimeDecoder::VideoTrackHandler::getCurEditTimeOffset() const {
+ // Need to convert to the track scale
+ return _parent->editList[_curEdit].timeOffset * _parent->timeScale / _decoder->_timeScale;
+}
+
+uint32 QuickTimeDecoder::VideoTrackHandler::getCurEditTrackDuration() const {
+ // Need to convert to the track scale
+ return _parent->editList[_curEdit].trackDuration * _parent->timeScale / _decoder->_timeScale;
+}
+
} // End of namespace Video
diff --git a/video/qt_decoder.h b/video/qt_decoder.h
index b51fd043e7..b2d7153f42 100644
--- a/video/qt_decoder.h
+++ b/video/qt_decoder.h
@@ -31,14 +31,14 @@
#ifndef VIDEO_QT_DECODER_H
#define VIDEO_QT_DECODER_H
+#include "audio/mixer.h"
+#include "audio/decoders/quicktime_intern.h"
#include "common/scummsys.h"
#include "common/rational.h"
+#include "graphics/pixelformat.h"
#include "video/video_decoder.h"
-#include "audio/mixer.h"
-#include "audio/decoders/quicktime_intern.h"
-
namespace Common {
class Rational;
}
@@ -63,13 +63,13 @@ public:
* Returns the width of the video
* @return the width of the video
*/
- uint16 getWidth() const;
+ uint16 getWidth() const { return _width; }
/**
* Returns the height of the video
* @return the height of the video
*/
- uint16 getHeight() const;
+ uint16 getHeight() const { return _height; }
/**
* Returns the amount of frames in the video
@@ -101,6 +101,8 @@ public:
const byte *getPalette() { _dirtyPalette = false; return _palette; }
bool hasDirtyPalette() const { return _dirtyPalette; }
+ int32 getCurFrame() const;
+
bool isVideoLoaded() const { return isOpen(); }
const Graphics::Surface *decodeNextFrame();
bool endOfVideo() const;
@@ -132,8 +134,6 @@ protected:
Common::QuickTimeParser::SampleDesc *readSampleDesc(Track *track, uint32 format);
private:
- Common::SeekableReadStream *getNextFramePacket(uint32 &descId);
- uint32 getFrameDuration();
void init();
void startAudio();
@@ -144,20 +144,108 @@ private:
Audio::Timestamp _audioStartOffset;
Codec *createCodec(uint32 codecTag, byte bitsPerPixel);
- Codec *findDefaultVideoCodec() const;
- uint32 _nextFrameStartTime;
- int _videoTrackIndex;
uint32 findKeyFrame(uint32 frame) const;
bool _dirtyPalette;
const byte *_palette;
+ bool _setStartTime;
+ bool _needUpdate;
+
+ uint16 _width, _height;
Graphics::Surface *_scaledSurface;
- const Graphics::Surface *scaleSurface(const Graphics::Surface *frame);
- Common::Rational getScaleFactorX() const;
- Common::Rational getScaleFactorY() const;
+ void scaleSurface(const Graphics::Surface *src, Graphics::Surface *dst,
+ Common::Rational scaleFactorX, Common::Rational scaleFactorY);
void pauseVideoIntern(bool pause);
+ bool endOfVideoTracks() const;
+
+ // The TrackHandler is a class that wraps around a QuickTime Track
+ // and handles playback in this decoder class.
+ class TrackHandler {
+ public:
+ TrackHandler(QuickTimeDecoder *decoder, Track *parent);
+ virtual ~TrackHandler() {}
+
+ enum TrackType {
+ kTrackTypeAudio,
+ kTrackTypeVideo
+ };
+
+ virtual TrackType getTrackType() const = 0;
+
+ virtual void seekToTime(Audio::Timestamp time) = 0;
+
+ virtual bool endOfTrack();
+
+ protected:
+ uint32 _curEdit;
+ QuickTimeDecoder *_decoder;
+ Common::SeekableReadStream *_fd;
+ Track *_parent;
+ };
+
+ // The AudioTrackHandler is currently just a wrapper around some
+ // QuickTimeDecoder functions. Eventually this can be made to
+ // handle multiple audio tracks, but I haven't seen a video with
+ // that yet.
+ class AudioTrackHandler : public TrackHandler {
+ public:
+ AudioTrackHandler(QuickTimeDecoder *decoder, Track *parent);
+ TrackType getTrackType() const { return kTrackTypeAudio; }
+
+ void updateBuffer();
+ void seekToTime(Audio::Timestamp time);
+ bool endOfTrack();
+ };
+
+ // The VideoTrackHandler is the bridge between the time of playback
+ // and the media for the given track. It calculates when to start
+ // tracks and at what rate to play the media using the edit list.
+ class VideoTrackHandler : public TrackHandler {
+ public:
+ VideoTrackHandler(QuickTimeDecoder *decoder, Track *parent);
+ ~VideoTrackHandler();
+
+ TrackType getTrackType() const { return kTrackTypeVideo; }
+
+ const Graphics::Surface *decodeNextFrame();
+
+ uint32 getNextFrameStartTime();
+
+ uint32 getFrameCount();
+
+ int32 getCurFrame() { return _curFrame; }
+
+ Graphics::PixelFormat getPixelFormat() const;
+
+ void seekToTime(Audio::Timestamp time);
+
+ Common::Rational getWidth() const;
+ Common::Rational getHeight() const;
+
+ private:
+ int32 _curFrame;
+ uint32 _nextFrameStartTime;
+ Graphics::Surface *_scaledSurface;
+ bool _holdNextFrameStartTime;
+ int32 _durationOverride;
+
+ Common::SeekableReadStream *getNextFramePacket(uint32 &descId);
+ uint32 getFrameDuration();
+ uint32 findKeyFrame(uint32 frame) const;
+ void enterNewEditList(bool bufferFrames);
+ const Graphics::Surface *bufferNextFrame();
+ uint32 getRateAdjustedFrameTime() const;
+ uint32 getCurEditTimeOffset() const;
+ uint32 getCurEditTrackDuration() const;
+ };
+
+ Common::Array<TrackHandler *> _handlers;
+ VideoTrackHandler *_nextVideoTrack;
+ VideoTrackHandler *findNextVideoTrack() const;
+
+ void freeAllTrackHandlers();
};
} // End of namespace Video