aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2015-05-22 22:31:21 -0400
committerPaul Gilbert2015-05-22 22:31:21 -0400
commitb4b6bf63dbfd3f952f4ca207467315396b53bd23 (patch)
tree48e6390df9c5487e73bc1b0ded246d0076561bcd
parent40f7fff42977d01c8bac81d462580c2c8ec39dc3 (diff)
parent2db07a9d39cc9557d292908d84d3fc146635fd75 (diff)
downloadscummvm-rg350-b4b6bf63dbfd3f952f4ca207467315396b53bd23.tar.gz
scummvm-rg350-b4b6bf63dbfd3f952f4ca207467315396b53bd23.tar.bz2
scummvm-rg350-b4b6bf63dbfd3f952f4ca207467315396b53bd23.zip
Merge branch 'master' into sherlock2
-rw-r--r--NEWS16
-rw-r--r--README16
-rw-r--r--audio/mods/protracker.cpp9
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp5
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp19
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h3
-rw-r--r--devtools/scumm-md5.txt5
-rw-r--r--engines/agi/agi.cpp94
-rw-r--r--engines/agi/agi.h5
-rw-r--r--engines/agi/detection.cpp57
-rw-r--r--engines/agi/detection_tables.h174
-rw-r--r--engines/agi/font.h271
-rw-r--r--engines/agi/graphics.cpp6
-rw-r--r--engines/agi/graphics.h2
-rw-r--r--engines/agi/preagi.cpp8
-rw-r--r--engines/agi/sound_pcjr.cpp13
-rw-r--r--engines/agi/text.cpp4
-rw-r--r--engines/agos/rooms.cpp3
-rw-r--r--engines/agos/saveload.cpp7
-rw-r--r--engines/cine/detection_tables.h14
-rw-r--r--engines/fullpipe/scene.cpp6
-rw-r--r--engines/kyra/sound_adlib.cpp11
-rw-r--r--engines/mads/action.cpp4
-rw-r--r--engines/mads/action.h4
-rw-r--r--engines/mads/animation.cpp4
-rw-r--r--engines/mads/animation.h4
-rw-r--r--engines/mads/assets.cpp4
-rw-r--r--engines/mads/assets.h4
-rw-r--r--engines/mads/audio.cpp4
-rw-r--r--engines/mads/audio.h4
-rw-r--r--engines/mads/compression.cpp4
-rw-r--r--engines/mads/compression.h4
-rw-r--r--engines/mads/debugger.cpp6
-rw-r--r--engines/mads/debugger.h6
-rw-r--r--engines/mads/detection.cpp4
-rw-r--r--engines/mads/detection_tables.h4
-rw-r--r--engines/mads/dialogs.cpp4
-rw-r--r--engines/mads/dialogs.h4
-rw-r--r--engines/mads/dragonsphere/dragonsphere_scenes.cpp4
-rw-r--r--engines/mads/dragonsphere/dragonsphere_scenes.h4
-rw-r--r--engines/mads/dragonsphere/game_dragonsphere.cpp4
-rw-r--r--engines/mads/dragonsphere/game_dragonsphere.h4
-rw-r--r--engines/mads/events.cpp4
-rw-r--r--engines/mads/events.h4
-rw-r--r--engines/mads/font.cpp4
-rw-r--r--engines/mads/font.h4
-rw-r--r--engines/mads/game.cpp4
-rw-r--r--engines/mads/game.h4
-rw-r--r--engines/mads/game_data.cpp4
-rw-r--r--engines/mads/game_data.h4
-rw-r--r--engines/mads/globals.cpp4
-rw-r--r--engines/mads/globals.h4
-rw-r--r--engines/mads/hotspots.cpp6
-rw-r--r--engines/mads/hotspots.h6
-rw-r--r--engines/mads/inventory.cpp4
-rw-r--r--engines/mads/inventory.h4
-rw-r--r--engines/mads/mads.cpp4
-rw-r--r--engines/mads/mads.h4
-rw-r--r--engines/mads/menu_views.cpp4
-rw-r--r--engines/mads/menu_views.h4
-rw-r--r--engines/mads/messages.cpp4
-rw-r--r--engines/mads/messages.h4
-rw-r--r--engines/mads/msurface.cpp4
-rw-r--r--engines/mads/msurface.h4
-rw-r--r--engines/mads/nebular/dialogs_nebular.cpp4
-rw-r--r--engines/mads/nebular/dialogs_nebular.h4
-rw-r--r--engines/mads/nebular/game_nebular.cpp4
-rw-r--r--engines/mads/nebular/game_nebular.h4
-rw-r--r--engines/mads/nebular/globals_nebular.cpp4
-rw-r--r--engines/mads/nebular/globals_nebular.h4
-rw-r--r--engines/mads/nebular/menu_nebular.cpp4
-rw-r--r--engines/mads/nebular/menu_nebular.h4
-rw-r--r--engines/mads/nebular/nebular_scenes.cpp4
-rw-r--r--engines/mads/nebular/nebular_scenes.h4
-rw-r--r--engines/mads/nebular/nebular_scenes1.cpp6
-rw-r--r--engines/mads/nebular/nebular_scenes1.h4
-rw-r--r--engines/mads/nebular/nebular_scenes2.cpp6
-rw-r--r--engines/mads/nebular/nebular_scenes2.h4
-rw-r--r--engines/mads/nebular/nebular_scenes3.cpp6
-rw-r--r--engines/mads/nebular/nebular_scenes3.h4
-rw-r--r--engines/mads/nebular/nebular_scenes4.cpp6
-rw-r--r--engines/mads/nebular/nebular_scenes4.h4
-rw-r--r--engines/mads/nebular/nebular_scenes5.cpp6
-rw-r--r--engines/mads/nebular/nebular_scenes5.h4
-rw-r--r--engines/mads/nebular/nebular_scenes6.cpp6
-rw-r--r--engines/mads/nebular/nebular_scenes6.h6
-rw-r--r--engines/mads/nebular/nebular_scenes7.cpp6
-rw-r--r--engines/mads/nebular/nebular_scenes7.h4
-rw-r--r--engines/mads/nebular/nebular_scenes8.cpp6
-rw-r--r--engines/mads/nebular/nebular_scenes8.h4
-rw-r--r--engines/mads/nebular/sound_nebular.cpp4
-rw-r--r--engines/mads/nebular/sound_nebular.h4
-rw-r--r--engines/mads/palette.cpp4
-rw-r--r--engines/mads/palette.h4
-rw-r--r--engines/mads/phantom/game_phantom.cpp4
-rw-r--r--engines/mads/phantom/game_phantom.h4
-rw-r--r--engines/mads/phantom/phantom_scenes.cpp4
-rw-r--r--engines/mads/phantom/phantom_scenes.h4
-rw-r--r--engines/mads/player.cpp4
-rw-r--r--engines/mads/player.h4
-rw-r--r--engines/mads/rails.cpp4
-rw-r--r--engines/mads/rails.h4
-rw-r--r--engines/mads/resources.cpp4
-rw-r--r--engines/mads/resources.h4
-rw-r--r--engines/mads/scene.cpp4
-rw-r--r--engines/mads/scene.h4
-rw-r--r--engines/mads/screen.cpp4
-rw-r--r--engines/mads/screen.h4
-rw-r--r--engines/mads/sequence.cpp4
-rw-r--r--engines/mads/sequence.h4
-rw-r--r--engines/mads/sound.cpp4
-rw-r--r--engines/mads/sound.h4
-rw-r--r--engines/mads/sprites.cpp4
-rw-r--r--engines/mads/sprites.h4
-rw-r--r--engines/mads/staticres.cpp4
-rw-r--r--engines/mads/staticres.h4
-rw-r--r--engines/mads/user_interface.cpp4
-rw-r--r--engines/mads/user_interface.h4
-rw-r--r--engines/queen/walk.cpp4
-rw-r--r--engines/saga/scene.cpp13
-rw-r--r--engines/sci/console.cpp157
-rw-r--r--engines/sci/console.h3
-rw-r--r--engines/sci/detection_tables.h6
-rw-r--r--engines/sci/engine/script.cpp332
-rw-r--r--engines/sci/engine/script.h33
-rw-r--r--engines/sci/engine/script_patches.cpp109
-rw-r--r--engines/sci/engine/workarounds.cpp4
-rw-r--r--engines/scumm/scumm-md5.h7
-rw-r--r--engines/sherlock/animation.cpp40
-rw-r--r--engines/sherlock/animation.h23
-rw-r--r--engines/sherlock/debugger.cpp6
-rw-r--r--engines/sherlock/debugger.h6
-rw-r--r--engines/sherlock/detection.cpp108
-rw-r--r--engines/sherlock/detection_tables.h23
-rw-r--r--engines/sherlock/events.cpp92
-rw-r--r--engines/sherlock/events.h66
-rw-r--r--engines/sherlock/inventory.cpp168
-rw-r--r--engines/sherlock/inventory.h67
-rw-r--r--engines/sherlock/journal.cpp266
-rw-r--r--engines/sherlock/journal.h54
-rw-r--r--engines/sherlock/map.cpp85
-rw-r--r--engines/sherlock/map.h62
-rw-r--r--engines/sherlock/objects.cpp112
-rw-r--r--engines/sherlock/objects.h98
-rw-r--r--engines/sherlock/people.cpp182
-rw-r--r--engines/sherlock/people.h68
-rw-r--r--engines/sherlock/resources.cpp264
-rw-r--r--engines/sherlock/resources.h87
-rw-r--r--engines/sherlock/saveload.cpp84
-rw-r--r--engines/sherlock/saveload.h52
-rw-r--r--engines/sherlock/scalpel/darts.cpp83
-rw-r--r--engines/sherlock/scalpel/darts.h58
-rw-r--r--engines/sherlock/scalpel/scalpel.cpp306
-rw-r--r--engines/sherlock/scalpel/scalpel.h51
-rw-r--r--engines/sherlock/scene.cpp254
-rw-r--r--engines/sherlock/scene.h118
-rw-r--r--engines/sherlock/screen.cpp171
-rw-r--r--engines/sherlock/screen.h137
-rw-r--r--engines/sherlock/settings.cpp42
-rw-r--r--engines/sherlock/settings.h12
-rw-r--r--engines/sherlock/sherlock.cpp66
-rw-r--r--engines/sherlock/sherlock.h82
-rw-r--r--engines/sherlock/sound.cpp96
-rw-r--r--engines/sherlock/sound.h48
-rw-r--r--engines/sherlock/surface.cpp103
-rw-r--r--engines/sherlock/surface.h106
-rw-r--r--engines/sherlock/talk.cpp191
-rw-r--r--engines/sherlock/talk.h89
-rw-r--r--engines/sherlock/user_interface.cpp387
-rw-r--r--engines/sherlock/user_interface.h160
-rw-r--r--engines/toon/toon.cpp2
171 files changed, 3828 insertions, 2573 deletions
diff --git a/NEWS b/NEWS
index a7e7d20ded..1422ec2818 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,15 @@ For a more comprehensive changelog of the latest experimental code, see:
General:
- Updated Munt MT-32 emulation code to version 1.5.0.
+ AGI:
+ - It is now possible to disable mouse support (except for Amiga versions
+ and fanmade games, that require a mouse).
+ - Fix incorrect volume attenuation in PCjr sound code (bug #6858).
+
+ AGOS:
+ - Fixed arpeggio effect used in music of Amiga version of Elvira 1.
+ - Fixed loading and saving progress in the PC version of Waxworks.
+
Broken Sword 1:
- Fix speech endianness detection on big endian systems for the mac
version (bug #6720).
@@ -20,8 +29,11 @@ For a more comprehensive changelog of the latest experimental code, see:
SCI:
- Handling of music priority has been greatly improved.
- - A lot of fixes for original game script bugs, which are too numerous to
- mention here.
+ - A lot of fixes for original game script bugs that also occurred when
+ using the original interpreter.
+ KQ6 (Dual Mode), LSL5, QfG1 (EGA), QfG1 (VGA), QfG2, QfG3, SQ1, SQ4 (CD)
+ - Restoring from the ScummVM in-game menu should now work all the time.
+ - Improve support for Japanese PC-9801 games.
SCUMM:
- It is now possible to play Maniac Mansion from within Day of the
diff --git a/README b/README
index 56b0a8423c..7116536222 100644
--- a/README
+++ b/README
@@ -1013,7 +1013,11 @@ site, please see the section on reporting bugs.
Inherit the Earth: Quest for the Orb
- Amiga versions aren't supported
- Simon the Sorcerer 1:
+ Lure of the Temptress
+ - No Roland MT-32 support
+ - Sound support is incomplete and doesn't sound like original
+
+ Simon the Sorcerer 1:
- Subtitles aren't available in the English and German CD versions
as they are missing the majority of subtitles.
@@ -2264,6 +2268,10 @@ Sierra games using the AGI engine add the following non-standard keywords:
originalsaveload bool If true, the original save/load screens are
used instead of the enhanced ScummVM ones
+ altamigapalette bool Use an alternative palette, common for all
+ Amiga games. This was the old behavior
+ mousesupport bool Enables mouse support. Allows to use mouse
+ for movement and in game menus
Sierra games using the SCI engine add the following non-standard keywords:
@@ -2275,6 +2283,12 @@ Sierra games using the SCI engine add the following non-standard keywords:
native_fb01 bool If true, the music driver for an IBM Music
Feature card or a Yamaha FB-01 FM synth module
is used for MIDI output
+ use_cdaudio bool Use CD audio instead of in-game audio,
+ when available
+ windows_cursors bool Use the Windows cursors (smaller and monochrome)
+ instead of the DOS ones (King's Quest 6)
+ silver_cursors bool Use the alternate set of silver cursors,
+ instead of the normal golden ones (Space Quest 4)
Broken Sword II adds the following non-standard keywords:
diff --git a/audio/mods/protracker.cpp b/audio/mods/protracker.cpp
index 82067f67bd..2578e9488a 100644
--- a/audio/mods/protracker.cpp
+++ b/audio/mods/protracker.cpp
@@ -219,11 +219,10 @@ void ProtrackerStream::updateRow() {
case 0x0:
if (exy) {
_track[track].arpeggio = true;
- if (note.period) {
- _track[track].arpeggioNotes[0] = note.note;
- _track[track].arpeggioNotes[1] = note.note + ex;
- _track[track].arpeggioNotes[2] = note.note + ey;
- }
+ byte trackNote = _module.periodToNote(_track[track].period);
+ _track[track].arpeggioNotes[0] = trackNote;
+ _track[track].arpeggioNotes[1] = trackNote + ex;
+ _track[track].arpeggioNotes[2] = trackNote + ey;
}
break;
case 0x1:
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index c71b9c9219..a2b172f14a 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -57,7 +57,10 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
}
#else
const SDL_Rect *const *availableModes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
- if (availableModes != (void *)-1) {
+ // TODO: NULL means that there are no fullscreen modes supported. We
+ // should probably use this information and disable any fullscreen support
+ // in this case.
+ if (availableModes != NULL && availableModes != (void *)-1) {
for (;*availableModes; ++availableModes) {
const SDL_Rect *mode = *availableModes;
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index d08925349a..9cb14525ee 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -125,6 +125,8 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
_hwscreen(0),
#if SDL_VERSION_ATLEAST(2, 0, 0)
_renderer(nullptr), _screenTexture(nullptr),
+#else
+ _originalBitsPerPixel(0),
#endif
_screen(0), _tmpscreen(0),
#ifdef USE_RGB_COLOR
@@ -796,7 +798,15 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
_hwscreen = g_eventRec.getSurface(_videoMode.hardwareWidth, _videoMode.hardwareHeight);
} else
#endif
- {
+ {
+ // Save the original bpp to be able to restore the video mode on unload
+#if !SDL_VERSION_ATLEAST(2, 0, 0)
+ if (_originalBitsPerPixel == 0) {
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+ _originalBitsPerPixel = videoInfo->vfmt->BitsPerPixel;
+ }
+#endif
+
_hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
_videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
);
@@ -929,6 +939,13 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
}
#endif
DestroyScalers();
+
+#if !SDL_VERSION_ATLEAST(2, 0, 0)
+ // Reset video mode to original
+ // This will ensure that any new graphic manager will use the initial BPP when listing available modes
+ if (_originalBitsPerPixel != 0)
+ SDL_SetVideoMode(_videoMode.screenWidth, _videoMode.screenHeight, _originalBitsPerPixel, _videoMode.fullscreen ? (SDL_FULLSCREEN | SDL_SWSURFACE) : SDL_SWSURFACE);
+#endif
}
bool SurfaceSdlGraphicsManager::hotswapGFXMode() {
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index 4ba15a304b..2431ce8664 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -236,6 +236,9 @@ protected:
};
VideoState _videoMode, _oldVideoMode;
+ // Original BPP to restore the video mode on unload
+ uint8 _originalBitsPerPixel;
+
/** Force full redraw on next updateScreen */
bool _forceFull;
diff --git a/devtools/scumm-md5.txt b/devtools/scumm-md5.txt
index e56f1a6a99..305c1724ed 100644
--- a/devtools/scumm-md5.txt
+++ b/devtools/scumm-md5.txt
@@ -314,7 +314,7 @@ tentacle Day of the Tentacle
4fbbe9f64b8bc547503a379a301183ce -1 it All? - CD - Andrea Petrucci
883af4b0af4f77a92f1dcf1d0a283140 -1 es All? - CD - Andrea Petrucci
cc04a076779379524ed4d9c5ee3c6fb1 282467632 en Mac - CD Mac bundle Fingolfin, Joachim Eberhard
- ede149fda3edfc1dbd7347e0737cb583 -1 fr Mac - CD Mac bundle ThierryFR
+ ede149fda3edfc1dbd7347e0737cb583 282830409 fr Mac - CD Mac bundle ThierryFR, Thierry Crozat
f73883f13b5a302749a5bad31d909780 -1 de Mac - CD Mac bundle morrissey
c83079157ec765a28de445aec9768d60 7477 en All - Demo - Fingolfin
@@ -337,7 +337,7 @@ samnmax Sam & Max Hit the Road
4ba7fb331296c283e73d8f5b2096e551 -1 es All? - CD - Andrea Petrucci
d43352a805d78b5f4936c6d7779bf575 -1 ru DOS - CD -
166553538ff320c69edafeee29525419 199195304 en Mac - CD Mac bundle Joachim Eberhard
- 3a5d13675e9a23aedac0bac7730f0ac1 -1 fr Mac - CD Mac bundle ThierryFR
+ 3a5d13675e9a23aedac0bac7730f0ac1 228446581 fr Mac - CD Mac bundle ThierryFR, Thierry Crozat
c3196c5349e53e387aaff1533d95e53a -1 en DOS Floppy Demo -
0e4c5d54a0ad4b26132e78b5ea76642a 6485 en DOS Floppy Demo WIP Fingolfin
@@ -358,6 +358,7 @@ ft Full Throttle
e72bb4c2b613db2cf50f89ff6350e70a -1 es All? - - -
fe381e45117878b1e942cb876b050fd6 513243679 en Mac - - Mac bundle Fingolfin
04401d747f1a2c1c4b388daff71ed378 535405461 de Mac - - Mac bundle Fingolfin
+ 403d2ec4d60d3cdae925e6cbf67716d6 489436643 fr Mac - - Mac bundle Thierry Crozat
32a433dea56b86a55b59e4ff7d755711 -1 en DOS Demo Demo -
9d7b67be003fea60be4dcbd193611936 11164 en Mac Demo Demo - Fingolfin
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 1e663ec29a..2b5d7137bc 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -97,50 +97,62 @@ void AgiEngine::processEvents() {
}
break;
case Common::EVENT_LBUTTONDOWN:
- key = BUTTON_LEFT;
- _mouse.button = kAgiMouseButtonLeft;
- keyEnqueue(key);
- _mouse.x = event.mouse.x;
- _mouse.y = event.mouse.y;
+ if (_game.mouseEnabled) {
+ key = BUTTON_LEFT;
+ _mouse.button = kAgiMouseButtonLeft;
+ keyEnqueue(key);
+ _mouse.x = event.mouse.x;
+ _mouse.y = event.mouse.y;
+ }
break;
case Common::EVENT_RBUTTONDOWN:
- key = BUTTON_RIGHT;
- _mouse.button = kAgiMouseButtonRight;
- keyEnqueue(key);
- _mouse.x = event.mouse.x;
- _mouse.y = event.mouse.y;
+ if (_game.mouseEnabled) {
+ key = BUTTON_RIGHT;
+ _mouse.button = kAgiMouseButtonRight;
+ keyEnqueue(key);
+ _mouse.x = event.mouse.x;
+ _mouse.y = event.mouse.y;
+ }
break;
case Common::EVENT_WHEELUP:
- key = WHEEL_UP;
- keyEnqueue(key);
+ if (_game.mouseEnabled) {
+ key = WHEEL_UP;
+ keyEnqueue(key);
+ }
break;
case Common::EVENT_WHEELDOWN:
- key = WHEEL_DOWN;
- keyEnqueue(key);
+ if (_game.mouseEnabled) {
+ key = WHEEL_DOWN;
+ keyEnqueue(key);
+ }
break;
case Common::EVENT_MOUSEMOVE:
- _mouse.x = event.mouse.x;
- _mouse.y = event.mouse.y;
-
- if (!_game.mouseFence.isEmpty()) {
- if (_mouse.x < _game.mouseFence.left)
- _mouse.x = _game.mouseFence.left;
- if (_mouse.x > _game.mouseFence.right)
- _mouse.x = _game.mouseFence.right;
- if (_mouse.y < _game.mouseFence.top)
- _mouse.y = _game.mouseFence.top;
- if (_mouse.y > _game.mouseFence.bottom)
- _mouse.y = _game.mouseFence.bottom;
-
- g_system->warpMouse(_mouse.x, _mouse.y);
+ if (_game.mouseEnabled) {
+ _mouse.x = event.mouse.x;
+ _mouse.y = event.mouse.y;
+
+ if (!_game.mouseFence.isEmpty()) {
+ if (_mouse.x < _game.mouseFence.left)
+ _mouse.x = _game.mouseFence.left;
+ if (_mouse.x > _game.mouseFence.right)
+ _mouse.x = _game.mouseFence.right;
+ if (_mouse.y < _game.mouseFence.top)
+ _mouse.y = _game.mouseFence.top;
+ if (_mouse.y > _game.mouseFence.bottom)
+ _mouse.y = _game.mouseFence.bottom;
+
+ g_system->warpMouse(_mouse.x, _mouse.y);
+ }
}
break;
case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
- _mouse.button = kAgiMouseButtonUp;
- _mouse.x = event.mouse.x;
- _mouse.y = event.mouse.y;
+ if (_game.mouseEnabled) {
+ _mouse.button = kAgiMouseButtonUp;
+ _mouse.x = event.mouse.x;
+ _mouse.y = event.mouse.y;
+ }
break;
case Common::EVENT_KEYDOWN:
if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d) {
@@ -496,12 +508,15 @@ AgiBase::AgiBase(OSystem *syst, const AGIGameDescription *gameDesc) : Engine(sys
// Assign default values to the config manager, in case settings are missing
ConfMan.registerDefault("originalsaveload", "false");
ConfMan.registerDefault("altamigapalette", "false");
+ ConfMan.registerDefault("mousesupport", "true");
_noSaveLoadAllowed = false;
_rnd = new Common::RandomSource("agi");
_sound = 0;
+ _fontData = NULL;
+
initFeatures();
initVersion();
}
@@ -550,6 +565,19 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
memset(&_debug, 0, sizeof(struct AgiDebug));
memset(&_mouse, 0, sizeof(struct Mouse));
+ _game.mouseEnabled = true;
+ if (!ConfMan.getBool("mousesupport")) {
+ // we effectively disable the mouse for games, that explicitly do not want mouse support to be enabled
+ _game.mouseEnabled = false;
+ }
+
+ // We are currently using the custom font for all fanmade games
+ if (!(getFeatures() & (GF_FANMADE | GF_AGDS))) {
+ _fontData = fontData_Sierra; // original Sierra font
+ } else {
+ _fontData = fontData_FanGames; // our (own?) custom font, that supports umlauts etc.
+ }
+
_game._vm = this;
_game.clockEnabled = false;
@@ -708,7 +736,9 @@ Common::Error AgiBase::init() {
}
Common::Error AgiEngine::go() {
- CursorMan.showMouse(true);
+ if (_game.mouseEnabled) {
+ CursorMan.showMouse(true);
+ }
setTotalPlayTime(0);
if (_game.state < STATE_LOADED) {
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 6256de05d2..04e02dcf87 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -643,6 +643,7 @@ struct AgiGame {
int simpleSave; /**< select simple savegames */
Common::Rect mouseFence; /**< rectangle set by fence.mouse command */
+ bool mouseEnabled; /**< if mouse is supposed to be active */
// IF condition handling
int testResult;
@@ -780,6 +781,8 @@ protected:
void initRenderMode();
+ const uint8 *_fontData;
+
public:
GfxMgr *_gfx;
@@ -839,6 +842,8 @@ public:
bool canLoadGameStateCurrently();
bool canSaveGameStateCurrently();
+
+ const uint8 *getFontData() { return _fontData; };
};
typedef void (*AgiCommand)(AgiGame *state, uint8 *p);
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 3230b4e5d3..823ec7be66 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -138,21 +138,41 @@ static const PlainGameDescriptor agiGames[] = {
{0, 0}
};
-static const ExtraGuiOption agiExtraGuiOption = {
- _s("Use original save/load screens"),
- _s("Use the original save/load screens, instead of the ScummVM ones"),
- "originalsaveload",
- false
-};
+#include "agi/detection_tables.h"
-static const ExtraGuiOption agiExtraGuiOptionAmiga = {
- _s("Use an alternative palette"),
- _s("Use an alternative palette, common for all Amiga games. This was the old behavior"),
- "altamigapalette",
- false
-};
+static const ADExtraGuiOptionsMap optionsList[] = {
+ {
+ GAMEOPTION_ORIGINAL_SAVELOAD,
+ {
+ _s("Use original save/load screens"),
+ _s("Use the original save/load screens, instead of the ScummVM ones"),
+ "originalsaveload",
+ false
+ }
+ },
+
+ {
+ GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE,
+ {
+ _s("Use an alternative palette"),
+ _s("Use an alternative palette, common for all Amiga games. This was the old behavior"),
+ "altamigapalette",
+ false
+ }
+ },
+
+ {
+ GAMEOPTION_DISABLE_MOUSE,
+ {
+ _s("Mouse support"),
+ _s("Enables mouse support. Allows to use mouse for movement and in game menus."),
+ "mousesupport",
+ true
+ }
+ },
-#include "agi/detection_tables.h"
+ AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
using namespace Agi;
@@ -161,7 +181,7 @@ class AgiMetaEngine : public AdvancedMetaEngine {
mutable Common::String _extra;
public:
- AgiMetaEngine() : AdvancedMetaEngine(Agi::gameDescriptions, sizeof(Agi::AGIGameDescription), agiGames) {
+ AgiMetaEngine() : AdvancedMetaEngine(Agi::gameDescriptions, sizeof(Agi::AGIGameDescription), agiGames, optionsList) {
_singleid = "agi";
_guioptions = GUIO1(GUIO_NOSPEECH);
}
@@ -175,7 +195,6 @@ public:
virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
- virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const;
virtual SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const;
virtual void removeSaveState(const char *target, int slot) const;
@@ -234,14 +253,6 @@ bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD
return res;
}
-const ExtraGuiOptions AgiMetaEngine::getExtraGuiOptions(const Common::String &target) const {
- ExtraGuiOptions options;
- options.push_back(agiExtraGuiOption);
- if (target.contains("-amiga"))
- options.push_back(agiExtraGuiOptionAmiga);
- return options;
-}
-
SaveStateList AgiMetaEngine::listSaves(const char *target) const {
const uint32 AGIflag = MKTAG('A','G','I',':');
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h
index 2d7fba3507..0ae822a538 100644
--- a/engines/agi/detection_tables.h
+++ b/engines/agi/detection_tables.h
@@ -22,7 +22,16 @@
namespace Agi {
-#define GAME_LVFPN(id,extra,fname,md5,size,lang,ver,features,gid,platform,interp) { \
+#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1
+#define GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE GUIO_GAMEOPTIONS2
+#define GAMEOPTION_DISABLE_MOUSE GUIO_GAMEOPTIONS3
+// TODO: properly implement GAMEOPTIONs
+
+#define GAMEOPTIONS_DEFAULT GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_DISABLE_MOUSE)
+#define GAMEOPTIONS_AMIGA GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE)
+#define GAMEOPTIONS_FANMADE_MOUSE GUIO1(GAMEOPTION_ORIGINAL_SAVELOAD)
+
+#define GAME_LVFPN(id,extra,fname,md5,size,lang,ver,features,gid,platform,interp,guioptions) { \
{ \
id, \
extra, \
@@ -30,7 +39,7 @@ namespace Agi {
lang, \
platform, \
ADGF_NO_FLAGS, \
- GUIO0() \
+ guioptions \
}, \
gid, \
interp, \
@@ -38,7 +47,7 @@ namespace Agi {
ver \
}
-#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \
+#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp,guioptions) { \
{ \
id, \
name, \
@@ -46,7 +55,7 @@ namespace Agi {
lang, \
platform, \
ADGF_USEEXTRAASTITLE, \
- GUIO0() \
+ guioptions \
}, \
gid, \
interp, \
@@ -54,43 +63,52 @@ namespace Agi {
ver \
}
-#define BOOTER2(id,extra,fname,md5,size,ver,gid) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,0,gid,Common::kPlatformDOS,GType_V2)
-#define GAME(id,extra,md5,ver,gid) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformDOS,GType_V2)
-#define GAME3(id,extra,fname,md5,ver,gid) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformDOS,GType_V3)
+#define BOOTER2(id,extra,fname,md5,size,ver,gid) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,0,gid,Common::kPlatformDOS,GType_V2,GAMEOPTIONS_DEFAULT)
+#define GAME(id,extra,md5,ver,gid) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformDOS,GType_V2,GAMEOPTIONS_DEFAULT)
+#define GAME3(id,extra,fname,md5,ver,gid) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformDOS,GType_V3,GAMEOPTIONS_DEFAULT)
-#define GAME_P(id,extra,md5,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2)
+#define GAME_P(id,extra,md5,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2,GAMEOPTIONS_DEFAULT)
+#define GAME_PO(id,extra,md5,ver,gid,platform,guioptions) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2,guioptions)
-#define GAME_FP(id,extra,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2)
+#define GAME_FP(id,extra,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2,GAMEOPTIONS_DEFAULT)
+#define GAME_FPO(id,extra,md5,ver,flags,gid,platform,guioptions) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2,guioptions)
#define GAME_F(id,extra,md5,ver,flags,gid) GAME_FP(id,extra,md5,ver,flags,gid,Common::kPlatformDOS)
+#define GAME_FO(id,extra,md5,ver,flags,gid,guioptions) GAME_FPO(id,extra,md5,ver,flags,gid,Common::kPlatformDOS,guioptions)
-#define GAME_PS(id,extra,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2)
+#define GAME_PS(id,extra,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2,GAMEOPTIONS_DEFAULT)
-#define GAME_LPS(id,extra,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2)
+#define GAME_LPS(id,extra,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2,GAMEOPTIONS_DEFAULT)
-#define GAME_LFPS(id,extra,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2)
+#define GAME_LFPS(id,extra,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2,GAMEOPTIONS_DEFAULT)
-#define GAME3_P(id,extra,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3)
+#define GAME3_P(id,extra,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3,GAMEOPTIONS_DEFAULT)
+#define GAME3_PO(id,extra,fname,md5,ver,flags,gid,platform,guioptions) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3,guioptions)
-#define GAMEpre_P(id,extra,fname,md5,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI)
+#define GAMEpre_P(id,extra,fname,md5,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI,GAMEOPTIONS_DEFAULT)
+#define GAMEpre_PO(id,extra,fname,md5,ver,gid,platform,guioptions) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI,guioptions)
-#define GAMEpre_PS(id,extra,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI)
+#define GAMEpre_PS(id,extra,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI,GAMEOPTIONS_DEFAULT)
-#define GAME3_PS(id,extra,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3)
+#define GAME3_PS(id,extra,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3,GAMEOPTIONS_DEFAULT)
+#define GAME3_PSO(id,extra,fname,md5,size,ver,flags,gid,platform,guioptions) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3,guioptions)
-#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformDOS,GType_V2)
+#define FANMADE_ILVFO(id,name,md5,lang,ver,features,guioptions) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformDOS,GType_V2,guioptions)
-#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2)
-#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform)
+#define FANMADE_ISVPO(id,name,md5,size,ver,platform,guioptions) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2,guioptions)
+#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVPO("agi-fanmade",name,md5,size,ver,platform,GAMEOPTIONS_DEFAULT)
-#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features)
+#define FANMADE_LVFO(name,md5,lang,ver,features,guioptions) FANMADE_ILVFO("agi-fanmade",name,md5,lang,ver,features,guioptions)
-#define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features)
+#define FANMADE_LF(name,md5,lang,features) FANMADE_LVFO(name,md5,lang,0x2917,features,GAMEOPTIONS_DEFAULT)
+#define FANMADE_LFO(name,md5,lang,features,guioptions) FANMADE_LVFO(name,md5,lang,0x2917,features,guioptions)
#define FANMADE_IF(id,name,md5,features) FANMADE_ILVF(id,name,md5,Common::EN_ANY,0x2917,features)
-#define FANMADE_V(name,md5,ver) FANMADE_LVF(name,md5,Common::EN_ANY,ver,0)
+#define FANMADE_V(name,md5,ver) FANMADE_LVFO(name,md5,Common::EN_ANY,ver,0,GAMEOPTIONS_DEFAULT)
#define FANMADE_F(name,md5,features) FANMADE_LF(name,md5,Common::EN_ANY,features)
+#define FANMADE_FO(name,md5,features,guioptions) FANMADE_LFO(name,md5,Common::EN_ANY,features,guioptions)
#define FANMADE_L(name,md5,lang) FANMADE_LF(name,md5,lang,0)
#define FANMADE_I(id,name,md5) FANMADE_IF(id,name,md5,0)
+#define FANMADE_O(name,md5,guioptions) FANMADE_FO(name,md5,0,guioptions)
#define FANMADE(name,md5) FANMADE_F(name,md5,0)
@@ -130,7 +148,7 @@ static const AGIGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GAMEOPTIONS_DEFAULT
},
GID_BC,
GType_V1,
@@ -151,7 +169,7 @@ static const AGIGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GAMEOPTIONS_DEFAULT
},
GID_BC,
GType_V1,
@@ -172,7 +190,7 @@ static const AGIGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GAMEOPTIONS_DEFAULT
},
GID_BC,
GType_V1,
@@ -181,7 +199,7 @@ static const AGIGameDescription gameDescriptions[] = {
},
// Black Cauldron (Amiga) 2.00 6/14/87
- GAME_P("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga),
+ GAME_PO("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// Black Cauldron (Apple IIgs) 1.0O 2/24/89 (CE)
// Menus not tested
@@ -210,7 +228,7 @@ static const AGIGameDescription gameDescriptions[] = {
// Donald Duck's Playground (Amiga) 1.0C
// Menus not tested
- GAME_P("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga),
+ GAME_PO("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// Donald Duck's Playground (ST) 1.0A 8/8/86
// Menus not tested
@@ -221,7 +239,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME_PS("ddp", "1.0C 1986-06-09", "550971d196f65190a5c760d2479406ef", 132, 0x2272, GID_DDP, Common::kPlatformDOS),
// Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316
- GAME3_PS("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga),
+ GAME3_PSO("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88
// Menus not tested
@@ -252,7 +270,7 @@ static const AGIGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO0()
+ GAMEOPTIONS_DEFAULT
},
GID_GOLDRUSH,
GType_V3,
@@ -269,7 +287,7 @@ static const AGIGameDescription gameDescriptions[] = {
// King's Quest 1 (Amiga) 1.0U # 2.082
// The original game did not have menus, they are enabled under ScummVM
- GAME_FP("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga),
+ GAME_FPO("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// King's Quest 1 (ST) 1.0V
// The original game did not have menus, they are enabled under ScummVM
@@ -298,7 +316,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME_P("kq2", "2.0A 1988-06-16 (CE)", "5203c8b95250a2ecfee93ddb99414753", 0x2917, GID_KQ2, Common::kPlatformApple2GS),
// King's Quest 2 (Amiga) 2.0J
- GAME_P("kq2", "2.0J 1987-01-29", "b866f0fab2fad91433a637a828cfa410", 0x2440, GID_KQ2, Common::kPlatformAmiga),
+ GAME_PO("kq2", "2.0J 1987-01-29", "b866f0fab2fad91433a637a828cfa410", 0x2440, GID_KQ2, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// King's Quest 2 (Mac) 2.0R
GAME_P("kq2", "2.0R 1988-03-23", "cbdb0083317c8e7cfb7ac35da4bc7fdc", 0x2440, GID_KQ2, Common::kPlatformMacintosh),
@@ -324,7 +342,7 @@ static const AGIGameDescription gameDescriptions[] = {
// King's Quest 3 (Amiga) 1.01 11/8/86
// The original game did not have menus, they are enabled under ScummVM
- GAME_FP("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga),
+ GAME_FPO("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// King's Quest 3 (ST) 1.02 11/18/86
// Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
@@ -340,7 +358,7 @@ static const AGIGameDescription gameDescriptions[] = {
// Original pauses with ESC, has menus accessible with mouse.
// ver = 0x3086 -> menus accessible with ESC or mouse, bug #2835581 (KQ3: Game Crash When Leaving Tavern as Fly).
// ver = 0x3149 -> menus accessible with mouse, ESC pauses game, bug #2835581 disappears.
- GAME3_PS("kq3", "2.15 1989-11-15", "dirs", "8e35bded2bc5cf20f5eec2b15523b155", 1805, 0x3149, 0, GID_KQ3, Common::kPlatformAmiga),
+ GAME3_PSO("kq3", "2.15 1989-11-15", "dirs", "8e35bded2bc5cf20f5eec2b15523b155", 1805, 0x3149, 0, GID_KQ3, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// King's Quest 3 (PC) 1.01 11/08/86 [AGI 2.272]
// Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
@@ -405,7 +423,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME_P("lsl1", "1.04 1987-06-18", "8b579f8673fe9448c2538f5ed9887cf0", 0x2440, GID_LSL1, Common::kPlatformAtariST),
// Leisure Suit Larry 1 (Amiga) 1.05 6/26/87 # x.yyy
- GAME_P("lsl1", "1.05 1987-06-26", "3f5d26d8834ca49c147fb60936869d56", 0x2440, GID_LSL1, Common::kPlatformAmiga),
+ GAME_PO("lsl1", "1.05 1987-06-26", "3f5d26d8834ca49c147fb60936869d56", 0x2440, GID_LSL1, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// Leisure Suit Larry 1 (IIgs) 1.0E
GAME_P("lsl1", "1.0E 1987", "5f9e1dd68d626c6d303131c119582ad4", 0x2440, GID_LSL1, Common::kPlatformApple2GS),
@@ -423,7 +441,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME3_P("mh1", "2.0E 1988-10-05 (CE)", "mhdir", "2f1509f76f24e6e7d213f2dadebbf156", 0x3149, 0, GID_MH1, Common::kPlatformApple2GS),
// Manhunter NY (Amiga) 1.06 3/18/89
- GAME3_P("mh1", "1.06 1989-03-18", "dirs", "92c6183042d1c2bb76236236a7d7a847", 0x3149, GF_OLDAMIGAV20, GID_MH1, Common::kPlatformAmiga),
+ GAME3_PO("mh1", "1.06 1989-03-18", "dirs", "92c6183042d1c2bb76236236a7d7a847", 0x3149, GF_OLDAMIGAV20, GID_MH1, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// reported by Filippos (thebluegr) in bugreport #1654500
// Manhunter NY (PC 5.25") 1.22 8/31/88 [AGI 3.002.107]
@@ -442,7 +460,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME3_P("mh2", "1.0 1989-07-29", "mh2dir", "5e3581495708b952fea24438a6c7e040", 0x3149, 0, GID_MH1, Common::kPlatformAtariST),
// Manhunter SF (Amiga) 3.06 8/17/89 # 2.333
- GAME3_PS("mh2", "3.06 1989-08-17", "dirs", "b412e8a126368b76696696f7632d4c16", 2573, 0x3086, GF_OLDAMIGAV20, GID_MH2, Common::kPlatformAmiga),
+ GAME3_PSO("mh2", "3.06 1989-08-17", "dirs", "b412e8a126368b76696696f7632d4c16", 2573, 0x3086, GF_OLDAMIGAV20, GID_MH2, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// Manhunter SF (PC 5.25") 3.03 8/17/89 [AGI 3.002.149]
GAME3("mh2", "3.03 1989-08-17 5.25\"", "mh2dir", "b90e4795413c43de469a715fb3c1fa93", 0x3149, GID_MH2),
@@ -464,7 +482,7 @@ static const AGIGameDescription gameDescriptions[] = {
// Mixed-Up Mother Goose (Amiga) 1.1
// Problematic: crashes
// Menus not tested
- GAME3_PS("mixedup", "1.1 1986-12-10", "dirs", "5c1295fe6daaf95831195ba12894dbd9", 2021, 0x3086, 0, GID_MIXEDUP, Common::kPlatformAmiga),
+ GAME3_PSO("mixedup", "1.1 1986-12-10", "dirs", "5c1295fe6daaf95831195ba12894dbd9", 2021, 0x3086, 0, GID_MIXEDUP, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
#endif
// Mixed Up Mother Goose (IIgs)
@@ -486,7 +504,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME_P("pq1", "2.0B 1988-04-21", "e7c175918372336461e3811d594f482f", 0x2917, GID_PQ1, Common::kPlatformApple2GS),
// Police Quest 1 (Amiga) 2.0B 2/22/89 # 2.310
- GAME3_PS("pq1", "2.0B 1989-02-22", "dirs", "cfa93e5f2aa7378bddd10ad6746a2ffb", 1613, 0x3149, 0, GID_PQ1, Common::kPlatformAmiga),
+ GAME3_PSO("pq1", "2.0B 1989-02-22", "dirs", "cfa93e5f2aa7378bddd10ad6746a2ffb", 1613, 0x3149, 0, GID_PQ1, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// Police Quest 1 (IIgs) 2.0A-88318
GAME_P("pq1", "2.0A 1988-03-18", "8994e39d0901de3d07cecfb954075bb5", 0x2917, GID_PQ1, Common::kPlatformApple2GS),
@@ -524,7 +542,7 @@ static const AGIGameDescription gameDescriptions[] = {
// Space Quest 1 (Amiga) 1.2 # 2.082
// The original game did not have menus, they are enabled under ScummVM
- GAME_FP("sq1", "1.2 1986", "0b216d931e95750f1f4837d6a4b821e5", 0x2440, GF_MENUS | GF_OLDAMIGAV20, GID_SQ1, Common::kPlatformAmiga),
+ GAME_FPO("sq1", "1.2 1986", "0b216d931e95750f1f4837d6a4b821e5", 0x2440, GF_MENUS | GF_OLDAMIGAV20, GID_SQ1, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// Space Quest 1 (Mac) 1.5D
GAME_P("sq1", "1.5D 1987-04-02", "ce88419aadd073d1c6682d859b3d8aa2", 0x2440, GID_SQ1, Common::kPlatformMacintosh),
@@ -570,7 +588,7 @@ static const AGIGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformAmiga,
ADGF_NO_FLAGS,
- GUIO0()
+ GAMEOPTIONS_AMIGA
},
GID_SQ2,
GType_V2,
@@ -616,7 +634,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAMEpre_P("winnie", "", "title.pic", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformDOS),
// Winnie the Pooh in the Hundred Acre Wood (Amiga)
- GAMEpre_P("winnie", "", "title", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformAmiga),
+ GAMEpre_PO("winnie", "", "title", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformAmiga, GAMEOPTIONS_AMIGA),
// Winnie the Pooh in the Hundred Acre Wood (C64)
GAMEpre_P("winnie", "", "title.pic", "d4eb97cffc866110f71e1ec9f84fe643", 0x0000, GID_WINNIE, Common::kPlatformC64),
@@ -630,15 +648,15 @@ static const AGIGameDescription gameDescriptions[] = {
// Xmas Card 1986 (CoCo3 360k) [AGI 2.072]
GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3),
- FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE),
+ FANMADE_FO("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("AGI Combat", "0be6a8a9e19203dcca0067d280798871"),
FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"),
FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"),
- FANMADE("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904"),
- FANMADE("AGI Mouse Demo 0.60 demo 2", "cc49d8b88ed6faf4f53ce92c84e0fe1b"),
- FANMADE("AGI Mouse Demo 0.70", "3497c291e4afb6f758e61740678a2aec"),
- FANMADE_F("AGI Mouse Demo 1.00", "20397f0bf0ef936f416bb321fb768fc7", GF_AGIMOUSE),
- FANMADE_F("AGI Mouse Demo 1.10", "f4ad396b496d6167635ad0b410312ab8", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_O("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904", GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_O("AGI Mouse Demo 0.60 demo 2", "cc49d8b88ed6faf4f53ce92c84e0fe1b", GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_O("AGI Mouse Demo 0.70", "3497c291e4afb6f758e61740678a2aec", GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_FO("AGI Mouse Demo 1.00", "20397f0bf0ef936f416bb321fb768fc7", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_FO("AGI Mouse Demo 1.10", "f4ad396b496d6167635ad0b410312ab8", GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("AGI Piano (v1.0)", "8778b3d89eb93c1d50a70ef06ef10310"),
FANMADE("AGI Quest (v1.46-TJ0)", "1cf1a5307c1a0a405f5039354f679814"),
GAME("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a", 0x2917, GID_FANMADE),
@@ -657,15 +675,15 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Al Pond 1 - Al Lives Forever (v1.0)", "e8921c3043b749b056ff51f56d1b451b"),
FANMADE("Al Pond 1 - Al Lives Forever (v1.3)", "fb4699474054962e0dbfb4cf12ca52f6"),
FANMADE("Apocalyptic Quest (v0.03 Teaser)", "42ced528b67965d3bc3b52c635f94a57"),
- FANMADE_F("Apocalyptic Quest (v4.00 Alpha 1)", "e15581628d84949b8d352d224ec3184b", GF_AGIMOUSE),
- FANMADE_F("Apocalyptic Quest (v4.00 Alpha 2)", "0eee850005860e46345b38fea093d194", GF_AGIMOUSE),
- FANMADE_F("Band Quest (Demo)", "7326abefd793571cc17ed0db647bdf34", GF_AGIMOUSE),
- FANMADE_F("Band Quest (Early Demo)", "de4758dd34676b248c8301b32d93bc6f", GF_AGIMOUSE),
+ FANMADE_FO("Apocalyptic Quest (v4.00 Alpha 1)", "e15581628d84949b8d352d224ec3184b", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_FO("Apocalyptic Quest (v4.00 Alpha 2)", "0eee850005860e46345b38fea093d194", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_FO("Band Quest (Demo)", "7326abefd793571cc17ed0db647bdf34", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_FO("Band Quest (Early Demo)", "de4758dd34676b248c8301b32d93bc6f", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Beyond the Titanic 2", "9b8de38dc64ffb3f52b7877ea3ebcef9"),
FANMADE("Biri Quest 1", "1b08f34f2c43e626c775c9d6649e2f17"),
FANMADE("Bob The Farmboy", "e4b7df9d0830addee5af946d380e66d7"),
- FANMADE_F("Boring Man 1: The Toad to Robinland", "d74481cbd227f67ace37ce6a5493039f", GF_AGIMOUSE),
- FANMADE_F("Boring Man 2: Ho Man! This Game Sucks!", "250032ba105bdf7c1bc4fed767c2d37e", GF_AGIMOUSE),
+ FANMADE_FO("Boring Man 1: The Toad to Robinland", "d74481cbd227f67ace37ce6a5493039f", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_FO("Boring Man 2: Ho Man! This Game Sucks!", "250032ba105bdf7c1bc4fed767c2d37e", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Botz", "a8fabe4e807adfe5ec02bfec6d983695"),
FANMADE("Brian's Quest (v1.0)", "0964aa79b9cdcff7f33a12b1d7e04b9c"),
FANMADE("CPU-21 (v1.0)", "35b7cdb4d17e890e4c52018d96e9cbf4"),
@@ -676,12 +694,12 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Coco Coq (English) - Coco Coq In Grostesteing's Base (v.1.0.3)", "97631f8e710544a58bd6da9e780f9320"),
FANMADE_L("Coco Coq (French) - Coco Coq Dans la Base de Grostesteing (v1.0.2)", "ef579ebccfe5e356f9a557eb3b2d8649", Common::FR_FRA),
FANMADE("Corby's Murder Mystery (v1.0)", "4ebe62ac24c5a8c7b7898c8eb070efe5"),
- FANMADE_F("DG: The AGIMouse Adventure (English v1.1)", "efe453b92bc1487ea69fbebede4d5f26", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_LF("DG: The AGIMouse Adventure (French v1.1)", "eb3d17ca466d672cbb95947e8d6e846a", Common::FR_FRA, GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_FO("DG: The AGIMouse Adventure (English v1.1)", "efe453b92bc1487ea69fbebede4d5f26", GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_LFO("DG: The AGIMouse Adventure (French v1.1)", "eb3d17ca466d672cbb95947e8d6e846a", Common::FR_FRA, GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("DG: The Adventure Game (English v1.1)", "0d6376d493fa7a21ec4da1a063e12b25"),
FANMADE_L("DG: The Adventure Game (French v1.1)", "258bdb3bb8e61c92b71f2f456cc69e23", Common::FR_FRA),
FANMADE("Dashiki (16 Colors)", "9b2c7b9b0283ab9f12bedc0cb6770a07"),
- FANMADE_F("Dashiki (256 Colors)", "c68052bb209e23b39b55ff3d759958e6", GF_AGIMOUSE|GF_AGI256),
+ FANMADE_FO("Dashiki (256 Colors)", "c68052bb209e23b39b55ff3d759958e6", GF_AGIMOUSE|GF_AGI256, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Date Quest 1 (v1.0)", "ba3dcb2600645be53a13170aa1a12e69"),
FANMADE("Date Quest 2 (v1.0 Demo)", "1602d6a2874856e928d9a8c8d2d166e9"),
FANMADE("Date Quest 2 (v1.0)", "f13f6fc85aa3e6e02b0c20408fb63b47"),
@@ -708,20 +726,20 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Good Man (demo v3.41)", "3facd8a8f856b7b6e0f6c3200274d88c"),
GAME_LVFPNF("agi-fanmade", "Groza (russian) [AGDS sample]", "logdir", "421da3a18004122a966d64ab6bd86d2e", -1,
- Common::RU_RUS, 0x2440, GF_AGDS, GID_FANMADE, Common::kPlatformDOS,GType_V2),
+ Common::RU_RUS, 0x2440, GF_AGDS, GID_FANMADE, Common::kPlatformDOS,GType_V2,GAMEOPTIONS_DEFAULT),
GAME_LVFPNF("agi-fanmade", "Get Outta Space Quest", "logdir", "aaea5b4a348acb669d13b0e6f22d4dc9", -1,
- Common::EN_ANY, 0x2440, GF_FANMADE, GID_GETOUTTASQ, Common::kPlatformDOS,GType_V2),
+ Common::EN_ANY, 0x2440, GF_FANMADE, GID_GETOUTTASQ, Common::kPlatformDOS,GType_V2,GAMEOPTIONS_DEFAULT),
- FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE),
+ FANMADE_FO("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Hank's Quest (v1.0 English) - Victim of Society", "64c15b3d0483d17888129100dc5af213"),
FANMADE("Hank's Quest (v1.1 English) - Victim of Society", "86d1f1dd9b0c4858d096e2a60cca8a14"),
FANMADE_L("Hank's Quest (v1.81 Dutch) - Slachtoffer Van Het Gebeuren", "41e53972d55ff3dff9e90d15fe1b659f", Common::NL_NLD),
FANMADE("Hank's Quest (v1.81 English) - Victim of Society", "7a776383282f62a57c3a960dafca62d1"),
FANMADE("Herbao (v0.2)", "6a5186fc8383a9060517403e85214fc2"),
- FANMADE_F("Hitler's Legacy (v.0004q)", "a412881269ba34584bd0a3268e5a9863", GF_AGIMOUSE),
+ FANMADE_FO("Hitler's Legacy (v.0004q)", "a412881269ba34584bd0a3268e5a9863", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Hobbits", "4a1c1ef3a7901baf0ab45fde0cfadd89"),
- FANMADE_F("Isabella Coq - A Present For My Dad", "55c6819f2330c4d5d6459874c9f123d9", GF_AGIMOUSE),
+ FANMADE_FO("Isabella Coq - A Present For My Dad", "55c6819f2330c4d5d6459874c9f123d9", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Jack & Julia - VAMPYR", "8aa0b9a26f8d5a4421067ab8cc3706f6"),
FANMADE("Jeff's Quest (v.5 alpha Jun 1)", "10f1720eed40c12b02a0f32df3e72ded"),
FANMADE("Jeff's Quest (v.5 alpha May 31)", "51ff71c0ed90db4e987a488ed3bf0551"),
@@ -730,8 +748,8 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Jiggy Jiggy Uh! Uh!", "bc331588a71e7a1c8840f6cc9b9487e4"),
FANMADE("Jimmy In: The Alien Attack (v0.1)", "a4e9db0564a494728de7873684a4307c"),
FANMADE("Joe McMuffin In \"What's Cooking, Doc\" (v1.0)", "8a3de7e61a99cb605fa6d233dd91c8e1"),
- FANMADE_LVF("Jolimie, le Village Maudit (v0.5)", "21818501636b3cb8ad5de5c1a66de5c2", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_LVF("Jolimie, le Village Maudit (v1.1)", "68d7aef1161bb5972fe03efdf29ccb7f", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_LVFO("Jolimie, le Village Maudit (v0.5)", "21818501636b3cb8ad5de5c1a66de5c2", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_LVFO("Jolimie, le Village Maudit (v1.1)", "68d7aef1161bb5972fe03efdf29ccb7f", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Journey Of Chef", "aa0a0b5a6364801ae65fdb96d6741df5"),
FANMADE("Jukebox (v1.0)", "c4b9c5528cc67f6ba777033830de7751"),
FANMADE("Justin Quest (v1.0 in development)", "103050989da7e0ffdc1c5e1793a4e1ec"),
@@ -747,18 +765,18 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("MD Quest - The Search for Michiel (v0.10)", "2a6fcb21d2b5e4144c38ed817fabe8ee"),
FANMADE("Maale Adummin Quest", "ddfbeb33feb7cf78504fe4dba14ec63b"),
FANMADE("Monkey Man", "2322d03f997e8cc235d4578efff69cfa"),
- FANMADE_F("Napalm Quest (v0.5)", "b659afb491d967bb34810d1c6ce22093", GF_AGIMOUSE),
+ FANMADE_FO("Napalm Quest (v0.5)", "b659afb491d967bb34810d1c6ce22093", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Naturette 1 (English v1.2)", "0a75884e7f010974a230bdf269651117"),
FANMADE("Naturette 1 (English v1.3)", "f15bbf999ac55ebd404aa1eb84f7c1d9"),
FANMADE_L("Naturette 1 (French v1.2)", "d3665622cc41aeb9c7ecf4fa43f20e53", Common::FR_FRA),
- FANMADE_F("Naturette 2: Daughter of the Moon (v1.0)", "bdf76a45621c7f56d1c9d40292c6137a", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_F("Naturette 3: Adventure in Treeworld (v1.0a)", "6dbb0e7fc75fec442e6d9e5a06f1530e", GF_AGIMOUSE|GF_AGIPAL),
- FANMADE_F("Naturette 4: From a Planet to Another Planet (Not Finished)", "13be8cd9cf35aeff0a39b8757057fbc8", GF_AGIMOUSE),
+ FANMADE_FO("Naturette 2: Daughter of the Moon (v1.0)", "bdf76a45621c7f56d1c9d40292c6137a", GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_FO("Naturette 3: Adventure in Treeworld (v1.0a)", "6dbb0e7fc75fec442e6d9e5a06f1530e", GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
+ FANMADE_FO("Naturette 4: From a Planet to Another Planet (Not Finished)", "13be8cd9cf35aeff0a39b8757057fbc8", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
// FIXME: Actually Naturette 4 has both English and French language support built into it. How to add that information?
- FANMADE_F("Naturette 4: From a Planet to Another Planet (2007-10-05)", "8253706b6ef5423a79413b216760297c", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_FO("Naturette 4: From a Planet to Another Planet (2007-10-05)", "8253706b6ef5423a79413b216760297c", GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("New AGI Hangman Test", "d69c0e9050ccc29fd662b74d9fc73a15"),
FANMADE("Nick's Quest - In Pursuit of QuakeMovie (v2.1 Gold)", "e29cbf9222551aee40397fabc83eeca0"),
- FANMADE_F("Open Mic Night (v0.1)", "70000a2f67aac27d1133d019df70246d", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_FO("Open Mic Night (v0.1)", "70000a2f67aac27d1133d019df70246d", GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Operation: Recon", "0679ce8405411866ccffc8a6743370d0"),
FANMADE("Patrick's Quest (Demo v1.0)", "f254f5b894b98fec5f92acc07fb62841"),
FANMADE("Phantasmagoria", "87d20c1c11aee99a4baad3797b63146b"),
@@ -802,14 +820,14 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Save Santa (v1.3)", "f8afdb6efc5af5e7c0228b44633066af"),
FANMADE("Schiller (preview 1)", "ade39dea968c959cfebe1cf935d653e9"),
FANMADE("Schiller (preview 2)", "62cd1f8fc758bf6b4aa334e553624cef"),
- GAME_F("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE),
+ GAME_FO("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE, GAMEOPTIONS_FANMADE_MOUSE),
// FIXME: The following two entries have identical MD5 checksums?
- GAME_F("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE),
- GAME_F("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE),
- GAME_F("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", 0x2917, GF_FANMADE|GF_AGIMOUSE, GID_FANMADE),
- GAME_F("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE),
+ GAME_FO("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE, GAMEOPTIONS_FANMADE_MOUSE),
+ GAME_FO("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE, GAMEOPTIONS_FANMADE_MOUSE),
+ GAME_FO("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", 0x2917, GF_FANMADE|GF_AGIMOUSE, GID_FANMADE, GAMEOPTIONS_FANMADE_MOUSE),
+ GAME_FO("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Shifty (v1.0)", "2a07984d27b938364bf6bd243ac75080"),
- FANMADE_F("Sliding Tile Game (v1.00)", "949bfff5d8a81c3139152eed4d84ca75", GF_AGIMOUSE),
+ FANMADE_FO("Sliding Tile Game (v1.00)", "949bfff5d8a81c3139152eed4d84ca75", GF_AGIMOUSE, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"),
FANMADE("Solar System Tour", "b5a3d0f392dfd76a6aa63f3d5f578403"),
FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"),
@@ -819,7 +837,7 @@ static const AGIGameDescription gameDescriptions[] = {
GAME("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1", 0x2917, GID_FANMADE),
GAME("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910", 0x2917, GID_FANMADE),
GAME_PS("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, GID_FANMADE, Common::kPlatformCoCo3),
- FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL),
+ FANMADE_FO("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL, GAMEOPTIONS_FANMADE_MOUSE),
FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS),
FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"),
FANMADE("Speeder Bike Challenge (v1.0)", "2deb25bab379285ca955df398d96c1e7"),
@@ -862,7 +880,7 @@ static const AGIGameDescription gameDescriptions[] = {
Common::EN_ANY,
Common::kPlatformDOS,
ADGF_USEEXTRAASTITLE,
- GUIO0()
+ GAMEOPTIONS_DEFAULT
},
GID_FANMADE,
GType_V3,
@@ -890,7 +908,7 @@ static AGIGameDescription g_fallbackDesc = {
Common::UNK_LANG,
Common::kPlatformDOS,
ADGF_NO_FLAGS,
- GUIO0()
+ GAMEOPTIONS_DEFAULT
},
GID_FANMADE,
GType_V2,
diff --git a/engines/agi/font.h b/engines/agi/font.h
index c77d8cf0c3..0e6b15f06b 100644
--- a/engines/agi/font.h
+++ b/engines/agi/font.h
@@ -26,7 +26,7 @@
namespace Agi {
// 8x8 font patterns
-static const uint8 curFont[] = {
+static const uint8 fontData_Sierra[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7E, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7E, // cursor hollow
0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, // cursor solid
@@ -59,6 +59,267 @@ static const uint8 curFont[] = {
0x00, 0x24, 0x42, 0xFF, 0x42, 0x24, 0x00, 0x00,
0x00, 0x10, 0x38, 0x7C, 0xFE, 0xFE, 0x00, 0x00,
0x00, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00,
+ // original sierra font starts here
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 Space
+ 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
+ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00,
+ 0x30, 0x7C, 0xC0, 0x78, 0x0C, 0xF8, 0x30, 0x00,
+ 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00,
+ 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00,
+ 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
+ 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
+ 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00,
+ 0x00, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
+ 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
+ 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00,
+ 0x7C, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0x7C, 0x00, // 0x30
+ 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00,
+ 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00,
+ 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00,
+ 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00,
+ 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00,
+ 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00,
+ 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00,
+ 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00,
+ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
+ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
+ 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00,
+ 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00,
+ 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00,
+ 0x78, 0xCC, 0x0C, 0x18, 0x30, 0x00, 0x30, 0x00,
+ 0x7C, 0xC6, 0xDE, 0xDE, 0xDE, 0xC0, 0x78, 0x00, // 0x40
+ 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00,
+ 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00,
+ 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00,
+ 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00,
+ 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00,
+ 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00,
+ 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3E, 0x00,
+ 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00,
+ 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00,
+ 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00,
+ 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00,
+ 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
+ 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00,
+ 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00,
+ 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, // 0x50
+ 0x78, 0xCC, 0xCC, 0xCC, 0xDC, 0x78, 0x1C, 0x00,
+ 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00,
+ 0x78, 0xCC, 0xE0, 0x70, 0x1C, 0xCC, 0x78, 0x00,
+ 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
+ 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00,
+ 0xC6, 0xC6, 0x6C, 0x38, 0x38, 0x6C, 0xC6, 0x00,
+ 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00,
+ 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00,
+ 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
+ 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00,
+ 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
+ 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60
+ 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
+ 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00,
+ 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00,
+ 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00,
+ 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
+ 0x38, 0x6C, 0x60, 0xF0, 0x60, 0x60, 0xF0, 0x00,
+ 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
+ 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00,
+ 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x0C, 0x00, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78,
+ 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00,
+ 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xC6, 0x00,
+ 0x00, 0x00, 0xF8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
+ 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0, // 0x70
+ 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E,
+ 0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0xF0, 0x00,
+ 0x00, 0x00, 0x7C, 0xC0, 0x78, 0x0C, 0xF8, 0x00,
+ 0x10, 0x30, 0x7C, 0x30, 0x30, 0x34, 0x18, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
+ 0x00, 0x00, 0xC6, 0xD6, 0xFE, 0xFE, 0x6C, 0x00,
+ 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
+ 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00,
+ 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00,
+ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
+ 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00,
+ 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ // custom font starting here at 0x80
+ 0x1E, 0x36, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00, // 0x80
+ 0x7C, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00,
+ 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00,
+ 0x7E, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
+ 0x38, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0xFE, 0xC6,
+ 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E, 0x00,
+ 0xDB, 0xDB, 0x7E, 0x3C, 0x7E, 0xDB, 0xDB, 0x00,
+ 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00,
+ 0x66, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00,
+ 0x3C, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00,
+ 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00,
+ 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00,
+ 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
+ 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00,
+ 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00,
+ 0x7E, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00,
+ 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x00,
+ 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00,
+ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x66, 0x66, 0x66, 0x3E, 0x06, 0x66, 0x3C, 0x00,
+ 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x00,
+ 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7F, 0x03,
+ 0x66, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x00,
+ 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x03,
+ 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00,
+ 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00,
+ 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00,
+ 0x78, 0x8C, 0x06, 0x3E, 0x06, 0x8C, 0x78, 0x00,
+ 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00,
+ 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x00,
+ 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3A, 0x00,
+ 0x00, 0x3C, 0x60, 0x3C, 0x66, 0x66, 0x3C, 0x00,
+ 0x00, 0x00, 0x7C, 0x66, 0x7C, 0x66, 0x7C, 0x00,
+ 0x00, 0x00, 0x7E, 0x60, 0x60, 0x60, 0x60, 0x00,
+ 0x00, 0x00, 0x3C, 0x6C, 0x6C, 0x6C, 0xFE, 0xC6,
+ 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00,
+ 0x00, 0x00, 0xDB, 0x7E, 0x3C, 0x7E, 0xDB, 0x00,
+ 0x00, 0x00, 0x3C, 0x66, 0x0C, 0x66, 0x3C, 0x00,
+ 0x00, 0x00, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x00,
+ 0x00, 0x18, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x00,
+ 0x00, 0x00, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00,
+ 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x00,
+ 0x00, 0x00, 0xC6, 0xFE, 0xFE, 0xD6, 0xC6, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00,
+ 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00,
+ 0x00, 0x00, 0x7E, 0x66, 0x66, 0x66, 0x66, 0x00,
+ 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
+ 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18,
+ 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36,
+ 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x36,
+ 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x00,
+ 0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0x00,
+ 0x00, 0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x3E, 0x06, 0x7C, 0x00,
+ 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x18, 0x00,
+ 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7F, 0x03,
+ 0x00, 0x00, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x00,
+ 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x00,
+ 0x00, 0x00, 0xDB, 0xDB, 0xDB, 0xDB, 0xFF, 0x03,
+ 0x00, 0x00, 0xE0, 0x60, 0x7C, 0x66, 0x7C, 0x00,
+ 0x00, 0x00, 0xC6, 0xC6, 0xF6, 0xDE, 0xF6, 0x00,
+ 0x00, 0x00, 0x60, 0x60, 0x7C, 0x66, 0x7C, 0x00,
+ 0x00, 0x00, 0x7C, 0x06, 0x3E, 0x06, 0x7C, 0x00,
+ 0x00, 0x00, 0xCE, 0xDB, 0xFB, 0xDB, 0xCE, 0x00,
+ 0x00, 0x00, 0x3E, 0x66, 0x3E, 0x36, 0x66, 0x00,
+ 0x00, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00,
+ 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00, 0x7C, 0x00,
+ 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30,
+ 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C,
+ 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70,
+ 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18,
+ 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00,
+ 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00,
+ 0x03, 0x02, 0x06, 0x04, 0xCC, 0x68, 0x38, 0x10,
+ 0x3C, 0x42, 0x99, 0xA1, 0xA1, 0x99, 0x42, 0x3C,
+ 0x30, 0x48, 0x10, 0x20, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x7E, 0x00
+};
+
+static const uint8 fontData_FanGames[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7E, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7E, /* cursor hollow */
+ 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, /* cursor solid */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cursor empty */
+ 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00,
+ 0x3C, 0x3C, 0x18, 0xFF, 0xE7, 0x18, 0x3C, 0x00,
+ 0x10, 0x38, 0x7C, 0xFE, 0xEE, 0x10, 0x38, 0x00,
+ 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00,
+ 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF,
+ 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* \n */
+ 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78,
+ 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18,
+ 0x08, 0x0C, 0x0A, 0x0A, 0x08, 0x78, 0xF0, 0x00,
+ 0x18, 0x14, 0x1A, 0x16, 0x72, 0xE2, 0x0E, 0x1C,
+ 0x10, 0x54, 0x38, 0xEE, 0x38, 0x54, 0x10, 0x00,
+ 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00,
+ 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00,
+ 0x18, 0x3C, 0x5A, 0x18, 0x5A, 0x3C, 0x18, 0x00,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
+ 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x00,
+ 0x1C, 0x22, 0x38, 0x44, 0x44, 0x38, 0x88, 0x70,
+ 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00,
+ 0x18, 0x3C, 0x5A, 0x18, 0x5A, 0x3C, 0x18, 0x7E,
+ 0x18, 0x3C, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x5A, 0x3C, 0x18, 0x00,
+ 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00,
+ 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00,
+ 0x00, 0x24, 0x42, 0xFF, 0x42, 0x24, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x7C, 0xFE, 0xFE, 0x00, 0x00,
+ 0x00, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00,
0x6C, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -154,9 +415,7 @@ static const uint8 curFont[] = {
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
0xE0, 0x30, 0x30, 0x18, 0x30, 0x30, 0xE0, 0x00,
0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- //0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //replacement 0x7F
-
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*replacement 0x7F */
0x1E, 0x36, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00,
0x7C, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00,
0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00,
@@ -287,7 +546,7 @@ static const uint8 curFont[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x7E, 0x00
};
-static const uint8 mickey_fontdata[] = {
+static const uint8 fontData_Mickey[] = {
0x00, 0x36, 0x7F, 0x7F, 0x3E, 0x1C, 0x08, 0x00,
0x00, 0x00, 0x3F, 0x20, 0x2F, 0x28, 0x28, 0x28,
0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
@@ -546,7 +805,7 @@ static const uint8 mickey_fontdata[] = {
0x10, 0x18, 0x1C, 0x1E, 0x1C, 0x18, 0x10, 0x00,
};
-static const uint8 ibm_fontdata[] = {
+static const uint8 fontData_IBM[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E,
0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E,
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index 2b1bd8c829..32d0fdc06a 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -616,6 +616,8 @@ void GfxMgr::putTextCharacter(int l, int x, int y, unsigned char c, int fg, int
int x1, y1, xx, yy, cc;
const uint8 *p;
+ assert(font);
+
p = font + ((unsigned int)c * CHAR_LINES);
for (y1 = 0; y1 < CHAR_LINES; y1++) {
for (x1 = 0; x1 < CHAR_COLS; x1++) {
@@ -699,7 +701,7 @@ void GfxMgr::printCharacter(int x, int y, char c, int fg, int bg) {
x *= CHAR_COLS;
y *= CHAR_LINES;
- putTextCharacter(0, x, y, c, fg, bg);
+ putTextCharacter(0, x, y, c, fg, bg, false, _vm->getFontData());
// redundant! already inside put_text_character!
// flush_block (x, y, x + CHAR_COLS - 1, y + CHAR_LINES - 1);
}
@@ -754,7 +756,7 @@ void GfxMgr::rawDrawButton(int x, int y, const char *s, int fgcolor, int bgcolor
drawRectangle(x1, y1, x2, y2, border ? BUTTON_BORDER : MSG_BOX_COLOR);
while (*s) {
- putTextCharacter(0, x + textOffset, y + textOffset, *s++, fgcolor, bgcolor);
+ putTextCharacter(0, x + textOffset, y + textOffset, *s++, fgcolor, bgcolor, false, _vm->getFontData());
x += CHAR_COLS;
}
diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h
index 15668fbed3..506a9d93d6 100644
--- a/engines/agi/graphics.h
+++ b/engines/agi/graphics.h
@@ -56,7 +56,7 @@ public:
void gfxPutBlock(int x1, int y1, int x2, int y2);
- void putTextCharacter(int, int, int, unsigned char, int, int, bool checkerboard = false, const uint8 *font = curFont);
+ void putTextCharacter(int, int, int, unsigned char, int, int, bool checkerboard = false, const uint8 *font = fontData_Sierra);
void shakeScreen(int);
void shakeStart();
void shakeEnd();
diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp
index daadb5ffef..c368c7b195 100644
--- a/engines/agi/preagi.cpp
+++ b/engines/agi/preagi.cpp
@@ -59,6 +59,12 @@ void PreAgiEngine::initialize() {
_gfx = new GfxMgr(this);
_picture = new PictureMgr(this, _gfx);
+ if (getGameID() == GID_MICKEY) {
+ _fontData = fontData_Mickey;
+ } else {
+ _fontData = fontData_IBM;
+ }
+
_gfx->initMachine();
_game.gameFlags = 0;
@@ -137,7 +143,7 @@ void PreAgiEngine::drawStr(int row, int col, int attr, const char *buffer) {
break;
default:
- _gfx->putTextCharacter(1, col * 8 , row * 8, static_cast<char>(code), attr & 0x0f, (attr & 0xf0) / 0x10, false, getGameID() == GID_MICKEY ? mickey_fontdata : ibm_fontdata);
+ _gfx->putTextCharacter(1, col * 8 , row * 8, static_cast<char>(code), attr & 0x0f, (attr & 0xf0) / 0x10, false, _fontData);
if (++col == 320 / 8) {
col = 0;
diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp
index 51b2d067a4..ea7a2789e0 100644
--- a/engines/agi/sound_pcjr.cpp
+++ b/engines/agi/sound_pcjr.cpp
@@ -120,8 +120,6 @@ SoundGenPCJr::SoundGenPCJr(AgiBase *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMi
else
_dissolveMethod = 0;
- _dissolveMethod = 3;
-
memset(_channel, 0, sizeof(_channel));
memset(_tchannel, 0, sizeof(_tchannel));
@@ -207,9 +205,6 @@ int SoundGenPCJr::volumeCalc(SndGenChan *chan) {
chan->attenuationCopy = attenuation;
attenuation &= 0x0F;
- attenuation += _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 17;
- if (attenuation > 0x0F)
- attenuation = 0x0F;
}
}
//if (computer_type == 2) && (attenuation < 8)
@@ -411,7 +406,7 @@ int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) {
if (tpcm->noteCount <= 0) {
// get new tone data
if ((tpcm->avail) && (getNextNote(chan) == 0)) {
- tpcm->atten = _channel[chan].attenuation;
+ tpcm->atten = volumeCalc(&_channel[chan]);
tpcm->freqCount = _channel[chan].freqCount;
tpcm->genType = _channel[chan].genType;
@@ -477,8 +472,9 @@ int SoundGenPCJr::fillSquare(ToneChan *t, int16 *buf, int len) {
count = len;
+ int16 amp = (int16)(volTable[t->atten] * _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / Audio::Mixer::kMaxMixerVolume);
while (count > 0) {
- *(buf++) = t->sign ? volTable[t->atten] : -volTable[t->atten];
+ *(buf++) = t->sign ? amp : -amp;
count--;
// get next sample
@@ -515,8 +511,9 @@ int SoundGenPCJr::fillNoise(ToneChan *t, int16 *buf, int len) {
count = len;
+ int16 amp = (int16)(volTable[t->atten] * _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / Audio::Mixer::kMaxMixerVolume);
while (count > 0) {
- *(buf++) = t->sign ? volTable[t->atten] : -volTable[t->atten];
+ *(buf++) = t->sign ? amp : -amp;
count--;
// get next sample
diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp
index eb48857bf2..16c8284ce0 100644
--- a/engines/agi/text.cpp
+++ b/engines/agi/text.cpp
@@ -50,7 +50,7 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff,
// FR: strings with len == 1 were not printed
if (len == 1) {
- _gfx->putTextCharacter(l, xoff + foff, yoff, *msg, fg, bg, checkerboard);
+ _gfx->putTextCharacter(l, xoff + foff, yoff, *msg, fg, bg, checkerboard, _fontData);
maxx = 1;
minx = 0;
ofoff = foff;
@@ -74,7 +74,7 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff,
if (xpos >= GFX_WIDTH)
continue;
- _gfx->putTextCharacter(l, xpos, ypos, *m, fg, bg, checkerboard);
+ _gfx->putTextCharacter(l, xpos, ypos, *m, fg, bg, checkerboard, _fontData);
if (x1 > maxx)
maxx = x1;
diff --git a/engines/agos/rooms.cpp b/engines/agos/rooms.cpp
index 6185653d42..d1d6f2b99d 100644
--- a/engines/agos/rooms.cpp
+++ b/engines/agos/rooms.cpp
@@ -383,7 +383,7 @@ bool AGOSEngine::loadRoomItems(uint16 room) {
for (uint16 z = minNum; z <= maxNum; z++) {
uint16 itemNum = z + 2;
item = derefItem(itemNum);
- item->parent = 0;
+ _itemArrayPtr[itemNum] = 0;
uint16 num = (itemNum - _itemArrayInited);
_roomStates[num].state = item->state;
@@ -453,6 +453,7 @@ bool AGOSEngine::loadRoomItems(uint16 room) {
item->classFlags = _roomStates[num].classFlags;
SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
subRoom->roomExitStates = _roomStates[num].roomExitStates;
+
}
in.close();
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index 5d5e2d7b03..b968ae645c 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -1261,7 +1261,6 @@ bool AGOSEngine_Elvira2::loadGame(const Common::String &filename, bool restartMo
uint16 room = _currentRoom;
_currentRoom = f->readUint16BE();
-
if (_roomsListPtr) {
byte *p = _roomsListPtr;
if (room == _currentRoom) {
@@ -1293,8 +1292,7 @@ bool AGOSEngine_Elvira2::loadGame(const Common::String &filename, bool restartMo
for (uint16 z = minNum; z <= maxNum; z++) {
uint16 itemNum = z + 2;
- Item *item = derefItem(itemNum);
- item->parent = 0;
+ _itemArrayPtr[itemNum] = 0;
}
}
}
@@ -1318,6 +1316,9 @@ bool AGOSEngine_Elvira2::loadGame(const Common::String &filename, bool restartMo
uint parent = f->readUint16BE();
uint next = f->readUint16BE();
+ if (getGameType() == GType_WW && getPlatform() == Common::kPlatformDOS && derefItem(item->parent) == NULL)
+ item->parent = 0;
+
parent_item = derefItem(parent);
setItemParent(item, parent_item);
diff --git a/engines/cine/detection_tables.h b/engines/cine/detection_tables.h
index 6069e3a99b..1188deb1a6 100644
--- a/engines/cine/detection_tables.h
+++ b/engines/cine/detection_tables.h
@@ -379,6 +379,20 @@ static const CINEGameDescription gameDescriptions[] = {
{
{
"os",
+ "Demo",
+ AD_ENTRY1("demo_os", "043859e4cfe3977ad95b6efd00b21c62"),
+ Common::EN_GRB,
+ Common::kPlatformDOS,
+ ADGF_DEMO | ADGF_UNSTABLE,
+ GUIO0()
+ },
+ GType_OS,
+ GF_DEMO,
+ },
+
+ {
+ {
+ "os",
"",
AD_ENTRY1("procs0", "a9da5531ead0ebf9ad387fa588c0cbb0"),
Common::EN_GRB,
diff --git a/engines/fullpipe/scene.cpp b/engines/fullpipe/scene.cpp
index 00dd70c1b2..5a3fbe34b6 100644
--- a/engines/fullpipe/scene.cpp
+++ b/engines/fullpipe/scene.cpp
@@ -672,11 +672,6 @@ void Scene::drawContent(int minPri, int maxPri, bool drawBg) {
debug(1, "_bigPict: %d objlist: %d", _bigPictureArray1Count, _picObjList.size());
- for (uint i = 0; i < _picObjList.size(); i++) {
- debug(1, "%d: %d", i, ((PictureObject *)_picObjList[i])->_priority);
- }
-
-
if (drawBg && _bigPictureArray1Count && _picObjList.size()) {
_bigPictureArray[0][0]->getDimensions(&point);
@@ -743,7 +738,6 @@ void Scene::drawContent(int minPri, int maxPri, bool drawBg) {
for (uint i = 1; i < _picObjList.size(); i++) {
PictureObject *obj = (PictureObject *)_picObjList[i];
- debug(8, "pri: %d", obj->_priority);
if (obj->_priority < minPri || obj->_priority >= maxPri)
continue;
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp
index 89ee41e859..c0e0f67b8e 100644
--- a/engines/kyra/sound_adlib.cpp
+++ b/engines/kyra/sound_adlib.cpp
@@ -947,15 +947,10 @@ void AdLibDriver::unkOutput2(uint8 chan) {
//
// This is very strange behavior, and causes problems with the ancient
// FMOPL code we borrowed from AdPlug. I've added a workaround. See
- // fmopl.cpp for more details.
+ // audio/softsynth/opl/mame.cpp for more details.
//
- // More recent versions of the MAME FMOPL don't seem to have this
- // problem, but cannot currently be used because of licensing and
- // performance issues.
- //
- // Ken Silverman's AdLib emulator (which can be found on his Web page -
- // http://www.advsys.net/ken - and as part of AdPlug) also seems to be
- // immune, but is apparently not as feature complete as MAME's.
+ // Fortunately, the more modern DOSBox FMOPL code does not seem to have
+ // any trouble with this.
writeOPL(0xB0 + chan, 0x20);
}
diff --git a/engines/mads/action.cpp b/engines/mads/action.cpp
index 628f03526f..f1c562675f 100644
--- a/engines/mads/action.cpp
+++ b/engines/mads/action.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/action.h b/engines/mads/action.h
index cfd5a3be3f..3ea10cd964 100644
--- a/engines/mads/action.h
+++ b/engines/mads/action.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp
index cf02e7b0b5..e4f44fc308 100644
--- a/engines/mads/animation.cpp
+++ b/engines/mads/animation.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/animation.h b/engines/mads/animation.h
index 1c87273e62..46ef85c5eb 100644
--- a/engines/mads/animation.h
+++ b/engines/mads/animation.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/assets.cpp b/engines/mads/assets.cpp
index a2d495f311..1d4634e383 100644
--- a/engines/mads/assets.cpp
+++ b/engines/mads/assets.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/assets.h b/engines/mads/assets.h
index 155590f9bd..8a0dc2cd44 100644
--- a/engines/mads/assets.h
+++ b/engines/mads/assets.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/audio.cpp b/engines/mads/audio.cpp
index def2cd6c62..8f33f22243 100644
--- a/engines/mads/audio.cpp
+++ b/engines/mads/audio.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/audio.h b/engines/mads/audio.h
index 13c540bf85..5c3cd5e682 100644
--- a/engines/mads/audio.h
+++ b/engines/mads/audio.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/compression.cpp b/engines/mads/compression.cpp
index 79cd1786de..1f6f1ee202 100644
--- a/engines/mads/compression.cpp
+++ b/engines/mads/compression.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/compression.h b/engines/mads/compression.h
index f7381e4af3..b560ed33c1 100644
--- a/engines/mads/compression.h
+++ b/engines/mads/compression.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/debugger.cpp b/engines/mads/debugger.cpp
index 99251f9fbb..a6a4d3edbc 100644
--- a/engines/mads/debugger.cpp
+++ b/engines/mads/debugger.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/debugger.h b/engines/mads/debugger.h
index c8fee5f5b2..70b2cadc65 100644
--- a/engines/mads/debugger.h
+++ b/engines/mads/debugger.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/detection.cpp b/engines/mads/detection.cpp
index ea71fc8539..57f4776e82 100644
--- a/engines/mads/detection.cpp
+++ b/engines/mads/detection.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h
index faf73996ac..56df09577c 100644
--- a/engines/mads/detection_tables.h
+++ b/engines/mads/detection_tables.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp
index 7f0b02bc65..d9b27ce926 100644
--- a/engines/mads/dialogs.cpp
+++ b/engines/mads/dialogs.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/dialogs.h b/engines/mads/dialogs.h
index 317c7bd792..efd2871d89 100644
--- a/engines/mads/dialogs.h
+++ b/engines/mads/dialogs.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.cpp b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
index f32d17d9c9..ff01c32174 100644
--- a/engines/mads/dragonsphere/dragonsphere_scenes.cpp
+++ b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.h b/engines/mads/dragonsphere/dragonsphere_scenes.h
index a6c778eca7..173cc667ce 100644
--- a/engines/mads/dragonsphere/dragonsphere_scenes.h
+++ b/engines/mads/dragonsphere/dragonsphere_scenes.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/dragonsphere/game_dragonsphere.cpp b/engines/mads/dragonsphere/game_dragonsphere.cpp
index 3836adb6d2..b07eab9daa 100644
--- a/engines/mads/dragonsphere/game_dragonsphere.cpp
+++ b/engines/mads/dragonsphere/game_dragonsphere.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/dragonsphere/game_dragonsphere.h b/engines/mads/dragonsphere/game_dragonsphere.h
index 7869dc87b4..b57f8833c6 100644
--- a/engines/mads/dragonsphere/game_dragonsphere.h
+++ b/engines/mads/dragonsphere/game_dragonsphere.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp
index 52569af375..7ba9098935 100644
--- a/engines/mads/events.cpp
+++ b/engines/mads/events.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/events.h b/engines/mads/events.h
index 1a92754f10..1a2579cae0 100644
--- a/engines/mads/events.h
+++ b/engines/mads/events.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp
index f7c1c52703..3e6d23fe6f 100644
--- a/engines/mads/font.cpp
+++ b/engines/mads/font.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/font.h b/engines/mads/font.h
index 47df647637..486cadcfff 100644
--- a/engines/mads/font.h
+++ b/engines/mads/font.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp
index 3d1c194612..91f6cd5630 100644
--- a/engines/mads/game.cpp
+++ b/engines/mads/game.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/game.h b/engines/mads/game.h
index d246aa501e..95b54b0d1a 100644
--- a/engines/mads/game.h
+++ b/engines/mads/game.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/game_data.cpp b/engines/mads/game_data.cpp
index 70e9e6c30b..6421d057e8 100644
--- a/engines/mads/game_data.cpp
+++ b/engines/mads/game_data.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/game_data.h b/engines/mads/game_data.h
index 65a9ae1553..e9bf45d8a5 100644
--- a/engines/mads/game_data.h
+++ b/engines/mads/game_data.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/globals.cpp b/engines/mads/globals.cpp
index 1d088992ea..e4a681d551 100644
--- a/engines/mads/globals.cpp
+++ b/engines/mads/globals.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/globals.h b/engines/mads/globals.h
index a6c9b628dd..27553a2b06 100644
--- a/engines/mads/globals.h
+++ b/engines/mads/globals.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/hotspots.cpp b/engines/mads/hotspots.cpp
index 2af421a112..bd28645504 100644
--- a/engines/mads/hotspots.cpp
+++ b/engines/mads/hotspots.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/hotspots.h b/engines/mads/hotspots.h
index f9334eace8..902275bb21 100644
--- a/engines/mads/hotspots.h
+++ b/engines/mads/hotspots.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/inventory.cpp b/engines/mads/inventory.cpp
index ca05575ec5..fe1d24baea 100644
--- a/engines/mads/inventory.cpp
+++ b/engines/mads/inventory.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/inventory.h b/engines/mads/inventory.h
index cf82de59f1..2897f950e4 100644
--- a/engines/mads/inventory.h
+++ b/engines/mads/inventory.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp
index 374e373035..8c7b6b1ce3 100644
--- a/engines/mads/mads.cpp
+++ b/engines/mads/mads.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/mads.h b/engines/mads/mads.h
index 1d641e7c87..901035320a 100644
--- a/engines/mads/mads.h
+++ b/engines/mads/mads.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp
index 319f5b0f87..cfc3b09461 100644
--- a/engines/mads/menu_views.cpp
+++ b/engines/mads/menu_views.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/menu_views.h b/engines/mads/menu_views.h
index f39ea4c3b5..6c8a2a8bdd 100644
--- a/engines/mads/menu_views.h
+++ b/engines/mads/menu_views.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/messages.cpp b/engines/mads/messages.cpp
index 304c79aa46..d88806150d 100644
--- a/engines/mads/messages.cpp
+++ b/engines/mads/messages.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/messages.h b/engines/mads/messages.h
index 22ae0b24b5..764477a7fc 100644
--- a/engines/mads/messages.h
+++ b/engines/mads/messages.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp
index 702b9e5f08..f768624278 100644
--- a/engines/mads/msurface.cpp
+++ b/engines/mads/msurface.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
index 754e70bf7f..80891afb83 100644
--- a/engines/mads/msurface.h
+++ b/engines/mads/msurface.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp
index 5b9942db07..960a2cc2f4 100644
--- a/engines/mads/nebular/dialogs_nebular.cpp
+++ b/engines/mads/nebular/dialogs_nebular.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h
index 0f086f6ec1..4935ee4b8c 100644
--- a/engines/mads/nebular/dialogs_nebular.h
+++ b/engines/mads/nebular/dialogs_nebular.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp
index e9a3d0b716..e8e0a4f42c 100644
--- a/engines/mads/nebular/game_nebular.cpp
+++ b/engines/mads/nebular/game_nebular.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/game_nebular.h b/engines/mads/nebular/game_nebular.h
index 1b89d11412..3cf7aefc18 100644
--- a/engines/mads/nebular/game_nebular.h
+++ b/engines/mads/nebular/game_nebular.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/globals_nebular.cpp b/engines/mads/nebular/globals_nebular.cpp
index 9f8b8a7888..c44506e546 100644
--- a/engines/mads/nebular/globals_nebular.cpp
+++ b/engines/mads/nebular/globals_nebular.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/globals_nebular.h b/engines/mads/nebular/globals_nebular.h
index 8d0c26d96d..7c7069892e 100644
--- a/engines/mads/nebular/globals_nebular.h
+++ b/engines/mads/nebular/globals_nebular.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp
index 2fdef3443d..6fe17f3beb 100644
--- a/engines/mads/nebular/menu_nebular.cpp
+++ b/engines/mads/nebular/menu_nebular.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/menu_nebular.h b/engines/mads/nebular/menu_nebular.h
index 77b8b6fc6e..35af0bb34f 100644
--- a/engines/mads/nebular/menu_nebular.h
+++ b/engines/mads/nebular/menu_nebular.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp
index 14cf71d0fc..eb6f7a5610 100644
--- a/engines/mads/nebular/nebular_scenes.cpp
+++ b/engines/mads/nebular/nebular_scenes.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes.h b/engines/mads/nebular/nebular_scenes.h
index db7738f13b..58a6d1c98f 100644
--- a/engines/mads/nebular/nebular_scenes.h
+++ b/engines/mads/nebular/nebular_scenes.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp
index c9eda08859..fd97f71727 100644
--- a/engines/mads/nebular/nebular_scenes1.cpp
+++ b/engines/mads/nebular/nebular_scenes1.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes1.h b/engines/mads/nebular/nebular_scenes1.h
index 1afa7fccc1..d8c9059846 100644
--- a/engines/mads/nebular/nebular_scenes1.h
+++ b/engines/mads/nebular/nebular_scenes1.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp
index 84910c4de3..1cbd6f56ef 100644
--- a/engines/mads/nebular/nebular_scenes2.cpp
+++ b/engines/mads/nebular/nebular_scenes2.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes2.h b/engines/mads/nebular/nebular_scenes2.h
index c860db9470..0ea4702eea 100644
--- a/engines/mads/nebular/nebular_scenes2.h
+++ b/engines/mads/nebular/nebular_scenes2.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp
index 4e7781e7a2..5a6edbf995 100644
--- a/engines/mads/nebular/nebular_scenes3.cpp
+++ b/engines/mads/nebular/nebular_scenes3.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes3.h b/engines/mads/nebular/nebular_scenes3.h
index 9efd38e9a4..cf925b3867 100644
--- a/engines/mads/nebular/nebular_scenes3.h
+++ b/engines/mads/nebular/nebular_scenes3.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes4.cpp b/engines/mads/nebular/nebular_scenes4.cpp
index 29b17c42c0..c981f6a6e4 100644
--- a/engines/mads/nebular/nebular_scenes4.cpp
+++ b/engines/mads/nebular/nebular_scenes4.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes4.h b/engines/mads/nebular/nebular_scenes4.h
index fbd5ce81f0..de11bd4129 100644
--- a/engines/mads/nebular/nebular_scenes4.h
+++ b/engines/mads/nebular/nebular_scenes4.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp
index 2470137b2e..95eb429193 100644
--- a/engines/mads/nebular/nebular_scenes5.cpp
+++ b/engines/mads/nebular/nebular_scenes5.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes5.h b/engines/mads/nebular/nebular_scenes5.h
index 2face26508..f314ae8513 100644
--- a/engines/mads/nebular/nebular_scenes5.h
+++ b/engines/mads/nebular/nebular_scenes5.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp
index d94fb17fd4..d97e37ea0b 100644
--- a/engines/mads/nebular/nebular_scenes6.cpp
+++ b/engines/mads/nebular/nebular_scenes6.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes6.h b/engines/mads/nebular/nebular_scenes6.h
index c5cac56626..4fc4a2e8ae 100644
--- a/engines/mads/nebular/nebular_scenes6.h
+++ b/engines/mads/nebular/nebular_scenes6.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp
index b40a8054f7..c2a249e5f8 100644
--- a/engines/mads/nebular/nebular_scenes7.cpp
+++ b/engines/mads/nebular/nebular_scenes7.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes7.h b/engines/mads/nebular/nebular_scenes7.h
index dfb3c0f16e..b5aeba818c 100644
--- a/engines/mads/nebular/nebular_scenes7.h
+++ b/engines/mads/nebular/nebular_scenes7.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp
index 5f8417cee1..a904569624 100644
--- a/engines/mads/nebular/nebular_scenes8.cpp
+++ b/engines/mads/nebular/nebular_scenes8.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/nebular_scenes8.h b/engines/mads/nebular/nebular_scenes8.h
index 7f2c34a843..439815f05c 100644
--- a/engines/mads/nebular/nebular_scenes8.h
+++ b/engines/mads/nebular/nebular_scenes8.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp
index 9716e6d522..240c18f6dc 100644
--- a/engines/mads/nebular/sound_nebular.cpp
+++ b/engines/mads/nebular/sound_nebular.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h
index d2fc552eec..9bc1a49458 100644
--- a/engines/mads/nebular/sound_nebular.h
+++ b/engines/mads/nebular/sound_nebular.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp
index b5ea136abd..36c9e5694f 100644
--- a/engines/mads/palette.cpp
+++ b/engines/mads/palette.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/palette.h b/engines/mads/palette.h
index 5d3bc3a82e..6c98947384 100644
--- a/engines/mads/palette.h
+++ b/engines/mads/palette.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/phantom/game_phantom.cpp b/engines/mads/phantom/game_phantom.cpp
index 0b2531ef65..cbeb6b0d26 100644
--- a/engines/mads/phantom/game_phantom.cpp
+++ b/engines/mads/phantom/game_phantom.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/phantom/game_phantom.h b/engines/mads/phantom/game_phantom.h
index 99cc2c1230..5504054bcf 100644
--- a/engines/mads/phantom/game_phantom.h
+++ b/engines/mads/phantom/game_phantom.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/phantom/phantom_scenes.cpp b/engines/mads/phantom/phantom_scenes.cpp
index 7fd7ce642d..c2cec47bd9 100644
--- a/engines/mads/phantom/phantom_scenes.cpp
+++ b/engines/mads/phantom/phantom_scenes.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/phantom/phantom_scenes.h b/engines/mads/phantom/phantom_scenes.h
index cd295a28b6..0e22610086 100644
--- a/engines/mads/phantom/phantom_scenes.h
+++ b/engines/mads/phantom/phantom_scenes.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp
index f61a5a1592..bb747f4b52 100644
--- a/engines/mads/player.cpp
+++ b/engines/mads/player.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/player.h b/engines/mads/player.h
index 671ac9d16e..e5765a9bca 100644
--- a/engines/mads/player.h
+++ b/engines/mads/player.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/rails.cpp b/engines/mads/rails.cpp
index 322e6e7cb3..9b2ec71de6 100644
--- a/engines/mads/rails.cpp
+++ b/engines/mads/rails.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/rails.h b/engines/mads/rails.h
index e6cab08f85..c95f5c47a6 100644
--- a/engines/mads/rails.h
+++ b/engines/mads/rails.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/resources.cpp b/engines/mads/resources.cpp
index 1fb75e6ba2..d5352fb205 100644
--- a/engines/mads/resources.cpp
+++ b/engines/mads/resources.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/resources.h b/engines/mads/resources.h
index 8d9ab1e39f..95ea17d3c4 100644
--- a/engines/mads/resources.h
+++ b/engines/mads/resources.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp
index 463d4a62fd..5662d8349a 100644
--- a/engines/mads/scene.cpp
+++ b/engines/mads/scene.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/scene.h b/engines/mads/scene.h
index 5927f4e70f..c0784c3812 100644
--- a/engines/mads/scene.h
+++ b/engines/mads/scene.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp
index 3e2fe22611..3c27001ae0 100644
--- a/engines/mads/screen.cpp
+++ b/engines/mads/screen.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/screen.h b/engines/mads/screen.h
index 85c55419ca..d910e88633 100644
--- a/engines/mads/screen.h
+++ b/engines/mads/screen.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp
index ba0111a844..e5bf1631c2 100644
--- a/engines/mads/sequence.cpp
+++ b/engines/mads/sequence.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/sequence.h b/engines/mads/sequence.h
index 8b236af15e..c3a277c5a5 100644
--- a/engines/mads/sequence.h
+++ b/engines/mads/sequence.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp
index 4036ee8112..7b9388eee3 100644
--- a/engines/mads/sound.cpp
+++ b/engines/mads/sound.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/sound.h b/engines/mads/sound.h
index 5884323474..16128f8284 100644
--- a/engines/mads/sound.h
+++ b/engines/mads/sound.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp
index f15d6456d3..0a1c0b710d 100644
--- a/engines/mads/sprites.cpp
+++ b/engines/mads/sprites.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/sprites.h b/engines/mads/sprites.h
index bb5fdbe964..3db922c40b 100644
--- a/engines/mads/sprites.h
+++ b/engines/mads/sprites.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/staticres.cpp b/engines/mads/staticres.cpp
index 189e5f72e7..b659d9a27c 100644
--- a/engines/mads/staticres.cpp
+++ b/engines/mads/staticres.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/staticres.h b/engines/mads/staticres.h
index 560fd12e67..b805729327 100644
--- a/engines/mads/staticres.h
+++ b/engines/mads/staticres.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp
index 1e5a1d80d2..62fd036c03 100644
--- a/engines/mads/user_interface.cpp
+++ b/engines/mads/user_interface.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h
index 71c6f64c2a..1366aa2c32 100644
--- a/engines/mads/user_interface.h
+++ b/engines/mads/user_interface.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/queen/walk.cpp b/engines/queen/walk.cpp
index dd7e46c765..17d12b0b9f 100644
--- a/engines/queen/walk.cpp
+++ b/engines/queen/walk.cpp
@@ -130,7 +130,7 @@ void Walk::animateJoe() {
_vm->logic()->joeScale(pbs->scale);
pbs->scaleWalkSpeed(6);
_vm->update(true);
- if (_vm->input()->cutawayQuit() || _vm->logic()->joeWalk() == JWM_EXECUTE) {
+ if (_vm->input()->cutawayQuit() || _vm->logic()->joeWalk() == JWM_EXECUTE || _vm->shouldQuit()) {
stopJoe();
break;
}
@@ -249,7 +249,7 @@ void Walk::animatePerson(const MovePersonData *mpd, uint16 image, uint16 bobNum,
_vm->update();
pbs->scale = pwd->area->calcScale(pbs->y);
pbs->scaleWalkSpeed(mpd->moveSpeed);
- if (_vm->input()->cutawayQuit()) {
+ if (_vm->input()->cutawayQuit() || _vm->shouldQuit()) {
stopPerson(bobNum);
break;
}
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index f19645dd99..4fa15d09e5 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -835,13 +835,14 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) {
loadSceneParams.sceneProc(SCENE_BEGIN, this);
}
- // We probably don't want "followers" to go into scene -1 , 0. At the very
- // least we don't want garbage to be drawn that early in the ITE intro.
- if (_sceneNumber > 0 && _sceneNumber != ITE_SCENE_PUZZLE)
- _vm->_actor->updateActorsScene(loadSceneParams.actorsEntrance);
-
- if (_sceneNumber == ITE_SCENE_PUZZLE)
+ if (_vm->getGameId() == GID_ITE && _sceneNumber == ITE_SCENE_PUZZLE) {
_vm->_puzzle->execute();
+ } else {
+ // We probably don't want "followers" to go into scene -1 , 0. At the very
+ // least we don't want garbage to be drawn that early in the ITE intro.
+ if (_sceneNumber > 0)
+ _vm->_actor->updateActorsScene(loadSceneParams.actorsEntrance);
+ }
if (getFlags() & kSceneFlagShowCursor) {
// Activate user interface
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index bc9ad362ab..1e95393e4d 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -209,8 +209,11 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
registerCmd("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias
// VM
registerCmd("script_steps", WRAP_METHOD(Console, cmdScriptSteps));
+ registerCmd("script_objects", WRAP_METHOD(Console, cmdScriptObjects));
+ registerCmd("scro", WRAP_METHOD(Console, cmdScriptObjects));
registerCmd("script_strings", WRAP_METHOD(Console, cmdScriptStrings));
registerCmd("scrs", WRAP_METHOD(Console, cmdScriptStrings));
+ registerCmd("script_said", WRAP_METHOD(Console, cmdScriptSaid));
registerCmd("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist));
registerCmd("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias
registerCmd("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias
@@ -2830,28 +2833,86 @@ bool Console::cmdScriptSteps(int argc, const char **argv) {
return true;
}
-bool Console::cmdScriptStrings(int argc, const char **argv) {
- SegManager *segMan = _engine->_gamestate->_segMan;
+bool Console::cmdScriptObjects(int argc, const char **argv) {
int curScriptNr = -1;
- SegmentId curSegmentNr;
- Common::List<SegmentId> segmentNrList;
- SegmentType curSegmentType = SEG_TYPE_INVALID;
- SegmentObj *curSegmentObj = NULL;
- Script *curScriptObj = NULL;
+ if (argc < 2) {
+ debugPrintf("Shows all objects inside a specified script.\n");
+ debugPrintf("Usage: %s <script number>\n", argv[0]);
+ debugPrintf("Example: %s 999\n", argv[0]);
+ debugPrintf("<script number> may be * to show objects inside all loaded scripts\n");
+ return true;
+ }
+
+ if (strcmp(argv[1], "*") == 0) {
+ // get said-strings of all currently loaded scripts
+ curScriptNr = -1;
+ } else {
+ curScriptNr = atoi(argv[1]);
+ }
+
+ printOffsets(curScriptNr, SCI_SCR_OFFSET_TYPE_OBJECT);
+ return true;
+}
+
+bool Console::cmdScriptStrings(int argc, const char **argv) {
+ int curScriptNr = -1;
if (argc < 2) {
- debugPrintf("Shows the strings inside a specified script.\n");
+ debugPrintf("Shows all strings inside a specified script.\n");
debugPrintf("Usage: %s <script number>\n", argv[0]);
debugPrintf("Example: %s 999\n", argv[0]);
debugPrintf("<script number> may be * to show strings inside all loaded scripts\n");
return true;
}
- segmentNrList.clear();
-
if (strcmp(argv[1], "*") == 0) {
// get strings of all currently loaded scripts
+ curScriptNr = -1;
+ } else {
+ curScriptNr = atoi(argv[1]);
+ }
+
+ printOffsets(curScriptNr, SCI_SCR_OFFSET_TYPE_STRING);
+ return true;
+}
+
+bool Console::cmdScriptSaid(int argc, const char **argv) {
+ int curScriptNr = -1;
+
+ if (argc < 2) {
+ debugPrintf("Shows all said-strings inside a specified script.\n");
+ debugPrintf("Usage: %s <script number>\n", argv[0]);
+ debugPrintf("Example: %s 999\n", argv[0]);
+ debugPrintf("<script number> may be * to show said-strings inside all loaded scripts\n");
+ return true;
+ }
+
+ if (strcmp(argv[1], "*") == 0) {
+ // get said-strings of all currently loaded scripts
+ curScriptNr = -1;
+ } else {
+ curScriptNr = atoi(argv[1]);
+ }
+
+ printOffsets(curScriptNr, SCI_SCR_OFFSET_TYPE_SAID);
+ return true;
+}
+
+void Console::printOffsets(int scriptNr, uint16 showType) {
+ SegManager *segMan = _engine->_gamestate->_segMan;
+ Vocabulary *vocab = _engine->_vocabulary;
+ SegmentId curSegmentNr;
+ Common::List<SegmentId> segmentNrList;
+
+ SegmentType curSegmentType = SEG_TYPE_INVALID;
+ SegmentObj *curSegmentObj = NULL;
+ Script *curScriptObj = NULL;
+ const byte *curScriptData = NULL;
+
+ segmentNrList.clear();
+ if (scriptNr < 0) {
+ // get offsets of all currently loaded scripts
for (curSegmentNr = 0; curSegmentNr < segMan->_heap.size(); curSegmentNr++) {
curSegmentObj = segMan->_heap[curSegmentNr];
if (curSegmentObj && curSegmentObj->getType() == SEG_TYPE_SCRIPT) {
@@ -2860,15 +2921,23 @@ bool Console::cmdScriptStrings(int argc, const char **argv) {
}
} else {
- curScriptNr = atoi(argv[1]);
- curSegmentNr = segMan->getScriptSegment(curScriptNr);
+ curSegmentNr = segMan->getScriptSegment(scriptNr);
if (!curSegmentNr) {
- debugPrintf("Script %d is currently not loaded/available\n", curScriptNr);
- return true;
+ debugPrintf("Script %d is currently not loaded/available\n", scriptNr);
+ return;
}
segmentNrList.push_back(curSegmentNr);
}
+ const offsetLookupArrayType *scriptOffsetLookupArray;
+ offsetLookupArrayType::const_iterator arrayIterator;
+ int showTypeCount = 0;
+
+ reg_t objectPos;
+ const char *objectNamePtr = NULL;
+ const byte *stringPtr = NULL;
+ const byte *saidPtr = NULL;
+
Common::List<SegmentId>::iterator it;
const Common::List<SegmentId>::iterator end = segmentNrList.end();
@@ -2884,15 +2953,64 @@ bool Console::cmdScriptStrings(int argc, const char **argv) {
continue;
curScriptObj = (Script *)curSegmentObj;
- debugPrintf("=== SCRIPT %d from Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr);
- debugN("=== SCRIPT %d from Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr);
+ debugPrintf("=== SCRIPT %d inside Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr);
+ debugN("=== SCRIPT %d inside Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr);
+
+ // now print the list
+ scriptOffsetLookupArray = curScriptObj->getOffsetArray();
+ curScriptData = curScriptObj->getBuf();
+ showTypeCount = 0;
+
+ for (arrayIterator = scriptOffsetLookupArray->begin(); arrayIterator != scriptOffsetLookupArray->end(); arrayIterator++) {
+ if (arrayIterator->type == showType) {
+ switch (showType) {
+ case SCI_SCR_OFFSET_TYPE_OBJECT:
+ objectPos = make_reg(curSegmentNr, arrayIterator->offset);
+ objectNamePtr = segMan->getObjectName(objectPos);
+ debugPrintf(" %03d:%04x: %s\n", arrayIterator->id, arrayIterator->offset, objectNamePtr);
+ debugN(" %03d:%04x: %s\n", arrayIterator->id, arrayIterator->offset, objectNamePtr);
+ break;
+ case SCI_SCR_OFFSET_TYPE_STRING:
+ stringPtr = curScriptData + arrayIterator->offset;
+ debugPrintf(" %03d:%04x: '%s' (size %d)\n", arrayIterator->id, arrayIterator->offset, stringPtr, arrayIterator->stringSize);
+ debugN(" %03d:%04x: '%s' (size %d)\n", arrayIterator->id, arrayIterator->offset, stringPtr, arrayIterator->stringSize);
+ break;
+ case SCI_SCR_OFFSET_TYPE_SAID:
+ saidPtr = curScriptData + arrayIterator->offset;
+ debugPrintf(" %03d:%04x:\n", arrayIterator->id, arrayIterator->offset);
+ debugN(" %03d:%04x: ", arrayIterator->id, arrayIterator->offset);
+ vocab->debugDecipherSaidBlock(saidPtr);
+ debugN("\n");
+ break;
+ default:
+ break;
+ }
+ showTypeCount++;
+ }
+ }
+
+ if (showTypeCount == 0) {
+ switch (showType) {
+ case SCI_SCR_OFFSET_TYPE_OBJECT:
+ debugPrintf(" no objects\n");
+ debugN(" no objects\n");
+ break;
+ case SCI_SCR_OFFSET_TYPE_STRING:
+ debugPrintf(" no strings\n");
+ debugN(" no strings\n");
+ break;
+ case SCI_SCR_OFFSET_TYPE_SAID:
+ debugPrintf(" no said-strings\n");
+ debugN(" no said-strings\n");
+ break;
+ default:
+ break;
+ }
+ }
- // now print the string list
- curScriptObj->debugPrintStrings(this);
debugPrintf("\n");
debugN("\n");
}
- return true;
}
bool Console::cmdBacktrace(int argc, const char **argv) {
@@ -3374,6 +3492,7 @@ bool Console::cmdSend(int argc, const char **argv) {
// We call run_engine explictly so we can restore the value of r_acc
// after execution.
run_vm(_engine->_gamestate);
+ _engine->_gamestate->xs = old_xstack;
}
diff --git a/engines/sci/console.h b/engines/sci/console.h
index 00d95b511f..8b10912fbe 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -147,7 +147,9 @@ private:
bool cmdBreakpointFunction(int argc, const char **argv);
// VM
bool cmdScriptSteps(int argc, const char **argv);
+ bool cmdScriptObjects(int argc, const char **argv);
bool cmdScriptStrings(int argc, const char **argv);
+ bool cmdScriptSaid(int argc, const char **argv);
bool cmdVMVarlist(int argc, const char **argv);
bool cmdVMVars(int argc, const char **argv);
bool cmdStack(int argc, const char **argv);
@@ -167,6 +169,7 @@ private:
void printList(List *list);
int printNode(reg_t addr);
void hexDumpReg(const reg_t *data, int len, int regsPerLine = 4, int startOffset = 0, bool isArray = false);
+ void printOffsets(int scriptNr, uint16 showType);
private:
/**
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 312069025b..7cadcfc27e 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -904,16 +904,14 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
-#if 0 // TODO: unknown if these files are corrupt
- // Hoyle 1 - English Amiga (from www.back2roots.org)
- // SCI interpreter version 0.000.519 - FIXME: some have 0.000.530, others x.yyy.zzz
+ // Hoyle 1 - English Amiga (from www.back2roots.org - verified by waltervn in bug report #6870)
+ // Game version 1.000.139, SCI interpreter version x.yyy.zzz
{"hoyle1", "", {
{"resource.map", 0, "2a72b1aba65fa6e339370eb86d8601d1", 5166},
{"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 218755},
{"resource.002", 0, "e0dd44069a62a463fd124974b915f10d", 439502},
AD_LISTEND},
Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
-#endif
// Hoyle 2 - English DOS
// SCI interpreter version 0.000.572
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 69f52495e0..6034378ef6 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -65,7 +65,11 @@ void Script::freeScript() {
_lockers = 1;
_markedAsDeleted = false;
_objects.clear();
- _stringLookupList.clear();
+
+ _offsetLookupArray.clear();
+ _offsetLookupObjectCount = 0;
+ _offsetLookupStringCount = 0;
+ _offsetLookupSaidCount = 0;
}
void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptPatcher) {
@@ -208,39 +212,45 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP
}
// find all strings of this script
- identifyStrings();
+ identifyOffsets();
}
-void Script::identifyStrings() {
- stringLookupListEntry listEntry;
- byte *scriptDataPtr = NULL;
- byte *stringStartPtr = NULL;
- byte *stringDataPtr = NULL;
- int scriptDataLeft = 0;
- int stringDataLeft = 0;
+void Script::identifyOffsets() {
+ offsetLookupArrayEntry arrayEntry;
+ const byte *scriptDataPtr = NULL;
+ const byte *stringStartPtr = NULL;
+ const byte *stringDataPtr = NULL;
+ uint32 scriptDataLeft = 0;
+ uint32 stringDataLeft = 0;
byte stringDataByte = 0;
+ uint16 typeObject_id = 0;
+ uint16 typeString_id = 0;
+ uint16 typeSaid_id = 0;
+
+ uint16 blockType = 0;
+ uint16 blockSize = 0;
- _stringLookupList.clear();
- //stringLookupListType _stringLookupList; // Table of string data, that is inside the currently loaded script
+ _offsetLookupArray.clear();
+ _offsetLookupObjectCount = 0;
+ _offsetLookupStringCount = 0;
+ _offsetLookupSaidCount = 0;
if (getSciVersion() < SCI_VERSION_1_1) {
+ // SCI0 + SCI1
scriptDataPtr = _buf;
scriptDataLeft = _bufSize;
- // Go through all SCI_OBJ_STRINGS blocks
+ // Go through all blocks
if (getSciVersion() == SCI_VERSION_0_EARLY) {
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script %d", _nr);
scriptDataPtr += 2;
scriptDataLeft -= 2;
}
-
- uint16 blockType;
- uint16 blockSize;
do {
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script %d", _nr);
blockType = READ_LE_UINT16(scriptDataPtr);
scriptDataPtr += 2;
@@ -249,29 +259,50 @@ void Script::identifyStrings() {
break;
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script %d", _nr);
blockSize = READ_LE_UINT16(scriptDataPtr);
if (blockSize < 4)
- error("Script::identifyStrings(): invalid block size");
+ error("Script::identifyOffsets(): invalid block size in script %d", _nr);
blockSize -= 4; // block size includes block-type UINT16 and block-size UINT16
scriptDataPtr += 2;
scriptDataLeft -= 2;
if (scriptDataLeft < blockSize)
- error("Script::identifyStrings(): invalid block size");
-
- if (blockType == SCI_OBJ_STRINGS) {
+ error("Script::identifyOffsets(): invalid block size in script %d", _nr);
+
+ switch (blockType) {
+ case SCI_OBJ_OBJECT:
+ case SCI_OBJ_CLASS:
+ typeObject_id++;
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_OBJECT;
+ arrayEntry.id = typeObject_id;
+ arrayEntry.offset = scriptDataPtr - _buf + 8; // Calculate offset inside script data (VM uses +8)
+ arrayEntry.stringSize = 0;
+ _offsetLookupArray.push_back(arrayEntry);
+ _offsetLookupObjectCount++;
+ break;
+
+ case SCI_OBJ_STRINGS:
// string block detected, we now grab all NUL terminated strings out of this block
stringDataPtr = scriptDataPtr;
stringDataLeft = blockSize;
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_STRING;
+
do {
if (stringDataLeft < 1) // no more bytes left
break;
stringStartPtr = stringDataPtr;
- listEntry.ptrOffset = stringStartPtr - _buf; // Calculate offset inside script data
+
+ if (stringDataLeft == 1) {
+ // only 1 byte left and that byte is a [00], in that case we also exit
+ stringDataByte = *stringStartPtr;
+ if (stringDataByte == 0x00)
+ break;
+ }
+
// now look for terminating [NUL]
do {
stringDataByte = *stringDataPtr;
@@ -279,13 +310,77 @@ void Script::identifyStrings() {
stringDataLeft--;
if (!stringDataByte) // NUL found, exit this loop
break;
+ if (stringDataLeft < 1) {
+ // no more bytes left
+ warning("Script::identifyOffsets(): string without terminating NUL in script %d", _nr);
+ break;
+ }
+ } while (1);
+
+ if (stringDataByte)
+ break;
+
+ typeString_id++;
+ arrayEntry.id = typeString_id;
+ arrayEntry.offset = stringStartPtr - _buf; // Calculate offset inside script data
+ arrayEntry.stringSize = stringDataPtr - stringStartPtr;
+ _offsetLookupArray.push_back(arrayEntry);
+ _offsetLookupStringCount++;
+ } while (1);
+ break;
+
+ case SCI_OBJ_SAID:
+ // said block detected, we now try to find every single said "string" inside this block
+ // said strings are terminated with a 0xFF, the string itself may contain words (2 bytes), where
+ // the second byte of a word may also be a 0xFF.
+ stringDataPtr = scriptDataPtr;
+ stringDataLeft = blockSize;
+
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_SAID;
+
+ do {
+ if (stringDataLeft < 1) // no more bytes left
+ break;
+
+ stringStartPtr = stringDataPtr;
+ if (stringDataLeft == 1) {
+ // only 1 byte left and that byte is a [00], in that case we also exit
+ // happens in some scripts, for example Conquests of Camelot, script 997
+ // may have been a bug in the compiler or just an intentional filler byte
+ stringDataByte = *stringStartPtr;
+ if (stringDataByte == 0x00)
+ break;
+ }
+
+ // now look for terminating 0xFF
+ do {
+ stringDataByte = *stringDataPtr;
+ stringDataPtr++;
+ stringDataLeft--;
+ if (stringDataByte == 0xFF) // Terminator found, exit this loop
+ break;
if (stringDataLeft < 1) // no more bytes left
- error("Script::identifyStrings(): string without terminating NUL");
+ error("Script::identifyOffsets(): said-string without terminator in script %d", _nr);
+ if (stringDataByte < 0xF0) {
+ // Part of a word, skip second byte
+ stringDataPtr++;
+ stringDataLeft--;
+ if (stringDataLeft < 1) // no more bytes left
+ error("Script::identifyOffsets(): said-string without terminator in script %d", _nr);
+ }
} while (1);
- listEntry.stringSize = stringDataPtr - stringStartPtr;
- _stringLookupList.push_back(listEntry);
+ typeSaid_id++;
+ arrayEntry.id = typeSaid_id;
+ arrayEntry.offset = stringStartPtr - _buf; // Calculate offset inside script data
+ arrayEntry.stringSize = 0;
+ _offsetLookupArray.push_back(arrayEntry);
+ _offsetLookupSaidCount++;
} while (1);
+ break;
+
+ default:
+ break;
}
scriptDataPtr += blockSize;
@@ -293,33 +388,30 @@ void Script::identifyStrings() {
} while (1);
} else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
- // Strings in SCI1.1 come after the object instances
+ // Strings in SCI1.1 up to SCI2 come after the object instances
scriptDataPtr = _heapStart;
scriptDataLeft = _heapSize;
if (scriptDataLeft < 4)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script in script %d", _nr);
uint16 endOfStringOffset = READ_SCI11ENDIAN_UINT16(scriptDataPtr);
uint16 objectStartOffset = READ_SCI11ENDIAN_UINT16(scriptDataPtr + 2) * 2 + 4;
if (scriptDataLeft < objectStartOffset)
- error("Script::identifyStrings(): object start is beyond heap size");
+ error("Script::identifyOffsets(): object start is beyond heap size in script %d", _nr);
if (scriptDataLeft < endOfStringOffset)
- error("Script::identifyStrings(): end of string is beyond heap size");
+ error("Script::identifyOffsets(): end of string is beyond heap size in script %d", _nr);
- byte *endOfStringPtr = scriptDataPtr + endOfStringOffset;
+ const byte *endOfStringPtr = scriptDataPtr + endOfStringOffset;
scriptDataPtr += objectStartOffset;
scriptDataLeft -= objectStartOffset;
- uint16 blockType;
- uint16 blockSize;
-
- // skip all objects
+ // go through all objects
do {
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script %d", _nr);
blockType = READ_SCI11ENDIAN_UINT16(scriptDataPtr);
scriptDataPtr += 2;
@@ -327,15 +419,26 @@ void Script::identifyStrings() {
if (blockType != SCRIPT_OBJECT_MAGIC_NUMBER)
break;
+ // Object found, add offset of object
+ typeObject_id++;
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_OBJECT;
+ arrayEntry.id = typeObject_id;
+ arrayEntry.offset = scriptDataPtr - _buf - 2; // the VM uses a pointer to the Magic-Number
+ arrayEntry.stringSize = 0;
+ _offsetLookupArray.push_back(arrayEntry);
+ _offsetLookupObjectCount++;
+
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script in script %d", _nr);
blockSize = READ_SCI11ENDIAN_UINT16(scriptDataPtr) * 2;
+ if (blockSize < 4)
+ error("Script::identifyOffsets(): invalid block size in script %d", _nr);
scriptDataPtr += 2;
scriptDataLeft -= 2;
blockSize -= 4; // blocksize contains UINT16 type and UINT16 size
if (scriptDataLeft < blockSize)
- error("Script::identifyStrings(): invalid block size");
+ error("Script::identifyOffsets(): invalid block size in script %d", _nr);
scriptDataPtr += blockSize;
scriptDataLeft -= blockSize;
@@ -343,17 +446,17 @@ void Script::identifyStrings() {
// now scriptDataPtr points to right at the start of the strings
if (scriptDataPtr > endOfStringPtr)
- error("Script::identifyStrings(): string block / end-of-string block mismatch");
+ error("Script::identifyOffsets(): string block / end-of-string block mismatch in script %d", _nr);
stringDataPtr = scriptDataPtr;
stringDataLeft = endOfStringPtr - scriptDataPtr; // Calculate byte count within string-block
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_STRING;
do {
if (stringDataLeft < 1) // no more bytes left
break;
stringStartPtr = stringDataPtr;
- listEntry.ptrOffset = stringStartPtr - _buf; // Calculate offset inside script data
// now look for terminating [NUL]
do {
stringDataByte = *stringDataPtr;
@@ -361,35 +464,142 @@ void Script::identifyStrings() {
stringDataLeft--;
if (!stringDataByte) // NUL found, exit this loop
break;
- if (stringDataLeft < 1) // no more bytes left
- error("Script::identifyStrings(): string without terminating NUL");
+ if (stringDataLeft < 1) {
+ // no more bytes left
+ warning("Script::identifyOffsets(): string without terminating NUL in script %d", _nr);
+ break;
+ }
} while (1);
- listEntry.stringSize = stringDataPtr - stringStartPtr;
- _stringLookupList.push_back(listEntry);
+ if (stringDataByte)
+ break;
+
+ typeString_id++;
+ arrayEntry.id = typeString_id;
+ arrayEntry.offset = stringStartPtr - _buf; // Calculate offset inside script data
+ arrayEntry.stringSize = stringDataPtr - stringStartPtr;
+ _offsetLookupArray.push_back(arrayEntry);
+ _offsetLookupStringCount++;
} while (1);
} else if (getSciVersion() == SCI_VERSION_3) {
- warning("TODO: identifyStrings(): Implement SCI3 variant");
- return;
- }
-}
+ // SCI3
+ uint32 sci3StringOffset = 0;
+ uint32 sci3RelocationOffset = 0;
+ uint32 sci3BoundaryOffset = 0;
-void Script::debugPrintStrings(Console *con) {
- stringLookupListType::iterator it;
- const stringLookupListType::iterator end = _stringLookupList.end();
- byte *stringPtr;
+ if (_bufSize < 22)
+ error("Script::identifyOffsets(): script %d smaller than expected SCI3-header", _nr);
- if (!_stringLookupList.size()) {
- con->debugPrintf(" no strings\n");
- debugN(" no strings\n");
- return;
- }
+ sci3StringOffset = READ_LE_UINT32(_buf + 4);
+ sci3RelocationOffset = READ_LE_UINT32(_buf + 8);
+
+ if (sci3RelocationOffset > _bufSize)
+ error("Script::identifyOffsets(): relocation offset is beyond end of script %d", _nr);
+
+ // First we get all the objects
+ scriptDataPtr = getSci3ObjectsPointer();
+ scriptDataLeft = _bufSize - (scriptDataPtr - _buf);
+ do {
+ if (scriptDataLeft < 2)
+ error("Script::identifyOffsets(): unexpected end of script %d", _nr);
+
+ blockType = READ_SCI11ENDIAN_UINT16(scriptDataPtr);
+ scriptDataPtr += 2;
+ scriptDataLeft -= 2;
+ if (blockType != SCRIPT_OBJECT_MAGIC_NUMBER)
+ break;
+
+ // Object found, add offset of object
+ typeObject_id++;
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_OBJECT;
+ arrayEntry.id = typeObject_id;
+ arrayEntry.offset = scriptDataPtr - _buf - 2; // the VM uses a pointer to the Magic-Number
+ arrayEntry.stringSize = 0;
+ _offsetLookupArray.push_back(arrayEntry);
+ _offsetLookupObjectCount++;
+
+ if (scriptDataLeft < 2)
+ error("Script::identifyOffsets(): unexpected end of script in script %d", _nr);
- for (it = _stringLookupList.begin(); it != end; ++it) {
- stringPtr = _buf + it->ptrOffset;
- con->debugPrintf(" %04x: '%s' (size %d)\n", it->ptrOffset, stringPtr, it->stringSize);
- debugN(" %04x: '%s' (size %d)\n", it->ptrOffset, stringPtr, it->stringSize);
+ blockSize = READ_SCI11ENDIAN_UINT16(scriptDataPtr);
+ if (blockSize < 4)
+ error("Script::identifyOffsets(): invalid block size in script %d", _nr);
+ scriptDataPtr += 2;
+ scriptDataLeft -= 2;
+ blockSize -= 4; // blocksize contains UINT16 type and UINT16 size
+ if (scriptDataLeft < blockSize)
+ error("Script::identifyOffsets(): invalid block size in script %d", _nr);
+
+ scriptDataPtr += blockSize;
+ scriptDataLeft -= blockSize;
+ } while (1);
+
+ // And now we get all the strings
+ if (sci3StringOffset > 0) {
+ // string offset set, we expect strings
+ if (sci3StringOffset > _bufSize)
+ error("Script::identifyOffsets(): string offset is beyond end of script %d", _nr);
+
+ if (sci3RelocationOffset < sci3StringOffset)
+ error("Script::identifyOffsets(): string offset points beyond relocation offset in script %d", _nr);
+
+ stringDataPtr = _buf + sci3StringOffset;
+ stringDataLeft = sci3RelocationOffset - sci3StringOffset;
+
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_STRING;
+
+ do {
+ if (stringDataLeft < 1) // no more bytes left
+ break;
+
+ stringStartPtr = stringDataPtr;
+
+ if (stringDataLeft == 1) {
+ // only 1 byte left and that byte is a [00], in that case we also exit
+ stringDataByte = *stringStartPtr;
+ if (stringDataByte == 0x00)
+ break;
+ }
+
+ // now look for terminating [NUL]
+ do {
+ stringDataByte = *stringDataPtr;
+ stringDataPtr++;
+ stringDataLeft--;
+ if (!stringDataByte) // NUL found, exit this loop
+ break;
+ if (stringDataLeft < 1) {
+ // no more bytes left
+ warning("Script::identifyOffsets(): string without terminating NUL in script %d", _nr);
+ break;
+ }
+ } while (1);
+
+ if (stringDataByte)
+ break;
+
+ typeString_id++;
+ arrayEntry.id = typeString_id;
+ arrayEntry.offset = stringStartPtr - _buf; // Calculate offset inside script data
+ arrayEntry.stringSize = stringDataPtr - stringStartPtr;
+ _offsetLookupArray.push_back(arrayEntry);
+ _offsetLookupStringCount++;
+
+ // SCI3 seems to have aligned all string on DWORD boundaries
+ sci3BoundaryOffset = stringDataPtr - _buf; // Calculate current offset inside script data
+ sci3BoundaryOffset = sci3BoundaryOffset & 3; // Check boundary offset
+ if (sci3BoundaryOffset) {
+ // lower 2 bits are set? Then we have to adjust the offset
+ sci3BoundaryOffset = 4 - sci3BoundaryOffset;
+ if (stringDataLeft < sci3BoundaryOffset)
+ error("Script::identifyOffsets(): SCI3 string boundary adjustment goes beyond end of string block in script %d", _nr);
+ stringDataLeft -= sci3BoundaryOffset;
+ stringDataPtr += sci3BoundaryOffset;
+ }
+ } while (1);
+ }
+ return;
}
}
diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h
index fe774aeab5..755e2f3698 100644
--- a/engines/sci/engine/script.h
+++ b/engines/sci/engine/script.h
@@ -49,12 +49,20 @@ enum ScriptObjectTypes {
typedef Common::HashMap<uint16, Object> ObjMap;
-struct stringLookupListEntry {
- uint16 ptrOffset; // offset of the string
+enum ScriptOffsetEntryTypes {
+ SCI_SCR_OFFSET_TYPE_OBJECT = 0, // classes are handled by this type as well
+ SCI_SCR_OFFSET_TYPE_STRING,
+ SCI_SCR_OFFSET_TYPE_SAID
+};
+
+struct offsetLookupArrayEntry {
+ uint16 type; // type of entry
+ uint16 id; // id of this type, first item inside script data is 1, second item is 2, etc.
+ uint32 offset; // offset of entry within script resource data
uint16 stringSize; // size of string, including terminating [NUL]
};
-typedef Common::List<stringLookupListEntry> stringLookupListType;
+typedef Common::Array<offsetLookupArrayEntry> offsetLookupArrayType;
class Script : public SegmentObj {
private:
@@ -82,7 +90,13 @@ private:
ObjMap _objects; /**< Table for objects, contains property variables */
- stringLookupListType _stringLookupList; // Table of string data, that is inside the currently loaded script
+protected:
+ offsetLookupArrayType _offsetLookupArray; // Table of all elements of currently loaded script, that may get pointed to
+
+private:
+ uint16 _offsetLookupObjectCount;
+ uint16 _offsetLookupStringCount;
+ uint16 _offsetLookupSaidCount;
public:
int getLocalsOffset() const { return _localsOffset; }
@@ -258,9 +272,12 @@ public:
int getCodeBlockOffsetSci3() { return READ_SCI11ENDIAN_UINT32(_buf); }
/**
- * Print string lookup table (list) to debug console
+ * Get the offset array
*/
- void debugPrintStrings(Console *con);
+ const offsetLookupArrayType *getOffsetArray() { return &_offsetLookupArray; };
+ uint16 getOffsetObjectCount() { return _offsetLookupObjectCount; };
+ uint16 getOffsetStringCount() { return _offsetLookupStringCount; };
+ uint16 getOffsetSaidCount() { return _offsetLookupSaidCount; };
private:
/**
@@ -310,9 +327,9 @@ private:
LocalVariables *allocLocalsSegment(SegManager *segMan);
/**
- * Identifies strings within script data and set up lookup-table
+ * Identifies certain offsets within script data and set up lookup-table
*/
- void identifyStrings();
+ void identifyOffsets();
};
} // End of namespace Sci
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 4011273ca3..6915e12a0e 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -2123,21 +2123,30 @@ static const uint16 qfg1vgaPatchMoveToCrusher[] = {
// Same pathfinding bug as above, where Ego is set to move to an impossible
// spot when sneaking. In GuardsTrumpet::changeState, we change the final
-// location where Ego is moved from 111, 111 to 114, 114.
+// location where Ego is moved from 111, 111 to 116, 116.
+// target coordinate is really problematic here.
+//
+// 114, 114 works when the speed slider is all the way up, but doesn't work
+// when the speed slider is not.
+//
+// It seems that this bug was fixed by Sierra for the Macintosh version.
+//
+// Applies to at least: English PC floppy
+// Responsible method: GuardsTrumpet::changeState(8)
// Fixes bug: #6248
static const uint16 qfg1vgaSignatureMoveToCastleGate[] = {
+ 0x51, SIG_ADDTOOFFSET(+1), // class MoveTo
SIG_MAGICDWORD,
- 0x51, 0x1f, // class MoveTo
0x36, // push
- 0x39, 0x6f, // pushi 6f (111 - x)
- 0x3c, // dup (111 - y)
+ 0x39, 0x6f, // pushi 6f (111d)
+ 0x3c, // dup (111d) - coordinates 111, 111
0x7c, // pushSelf
SIG_END
};
static const uint16 qfg1vgaPatchMoveToCastleGate[] = {
PATCH_ADDTOOFFSET(+3),
- 0x39, 0x72, // pushi 72 (114 - x)
+ 0x39, 0x74, // pushi 74 (116d), changes coordinates to 116, 116
PATCH_END
};
@@ -2335,29 +2344,37 @@ static const SciScriptPatcherEntry qfg1vgaSignatures[] = {
// which finally re-enables controls
//
// A fix is difficult to implement. The code in script 20 is generic and used by multiple objects
-// That's why I have decided to change the responsible globals (66h and A1h) during mountSaurus::changeState(5)
//
-// This fix could cause issues in case there is a cutscene, that contains ego getting on a saurus and
-// requires controls not getting re-enabled after getting back up on the saurus.
+// Originally I decided to change the responsible globals (66h and A1h) during mountSaurus::changeState(5).
+// This worked as far as for controls, but mountSaurus::init changes a few selectors of ego as well, which
+// won't get restored in that situation, which then messes up room changes and other things.
+//
+// I have now decided to change sheepScript::changeState(2) in script 665 instead.
+//
+// This fix could cause issues in case there is a cutscene, where ego is supposed to get onto the saurus using
+// sheepScript.
//
// Applies to at least: English PC Floppy, English Amiga Floppy
// Responsible method: mountSaurus::changeState(), mountSaurus::init(), mountSaurus::dispose()
// Fixes bug: #5156
static const uint16 qfg2SignatureSaurusFreeze[] = {
0x3c, // dup
- 0x35, 0x05, // ldi 5
+ 0x35, 0x02, // ldi 5
SIG_MAGICDWORD,
0x1a, // eq?
- 0x30, SIG_UINT16(0x004e), // bnt [ret]
- 0x39, SIG_SELECTOR8(contains), // pushi [selector contains]
- 0x78, // push1
+ 0x30, SIG_UINT16(0x0043), // bnt [ret]
+ 0x76, // push0
+ SIG_ADDTOOFFSET(+61), // skip to dispose code
+ 0x39, SIG_SELECTOR8(dispose), // pushi "dispose"
+ 0x76, // push0
+ 0x54, 0x04, // self 04
SIG_END
};
static const uint16 qfg2PatchSaurusFreeze[] = {
- 0x35, 0x01, // ldi 1
- 0xa1, 0x66, // sag 66h
- 0xa0, SIG_UINT16(0x00a1), // sag 00A1h
+ 0x81, 0x66, // lag 66h
+ 0x2e, SIG_UINT16(0x0040), // bt [to dispose code]
+ 0x35, 0x00, // ldi 0 (waste 2 bytes)
PATCH_END
};
@@ -2441,7 +2458,7 @@ static const uint16 qfg2PatchImportCharType[] = {
// script, description, signature patch
static const SciScriptPatcherEntry qfg2Signatures[] = {
- { true, 660, "getting back on saurus freeze fix", 1, qfg2SignatureSaurusFreeze, qfg2PatchSaurusFreeze },
+ { true, 665, "getting back on saurus freeze fix", 1, qfg2SignatureSaurusFreeze, qfg2PatchSaurusFreeze },
{ true, 805, "import character type fix", 1, qfg2SignatureImportCharType, qfg2PatchImportCharType },
{ true, 944, "import dialog continuous calls", 1, qfg2SignatureImportDialog, qfg2PatchImportDialog },
SCI_SIGNATUREENTRY_TERMINATOR
@@ -2758,9 +2775,64 @@ static const uint16 sq4CdSignatureWalkInFromBelowRoom45[] = {
static const uint16 sq4CdPatchWalkInFromBelowRoom45[] = {
PATCH_ADDTOOFFSET(+2),
- 0x38, PATCH_UINT16(0x00bc), // pushi 00BCh
+ 0x38, PATCH_UINT16(0x00bc), // pushi 00BCh
PATCH_ADDTOOFFSET(+15),
- 0x38, PATCH_UINT16(0x00bb), // pushi 00BBh
+ 0x38, PATCH_UINT16(0x00bb), // pushi 00BBh
+ PATCH_END
+};
+
+// It seems that Sierra forgot to set a script flag, when cleaning out the bank account
+// in Space Quest 4 CD. This was probably caused by the whole bank account interaction
+// getting a rewrite and polish in the CD version.
+//
+// Because of this bug, points for changing back clothes will not get awarded, which
+// makes it impossible to get a perfect point score in the CD version of the game.
+// The points are awarded by rm371::doit in script 371.
+//
+// We fix this. Bug also happened, when using the original interpreter.
+// Bug does not happen for PC floppy.
+//
+// Attention: Some Let's Plays on youtube show that points are in fact awarded. Which is true.
+// But those Let's Plays were actually created by playing a hacked Space Quest 4 version
+// (which is part Floppy, part CD version - we consider it to be effectively pirated)
+// and not the actual CD version of Space Quest 4.
+// It's easy to identify - talkie + store called "Radio Shack" -> is hacked version.
+//
+// Applies to at least: English PC CD
+// Responsible method: but2Script::changeState(2)
+// Fixes bug: #6866
+static const uint16 sq4CdSignatureGetPointsForChangingBackClothes[] = {
+ 0x35, 0x02, // ldi 02
+ SIG_MAGICDWORD,
+ 0x1a, // eq?
+ 0x30, SIG_UINT16(0x006a), // bnt [state 3]
+ 0x76,
+ SIG_ADDTOOFFSET(+46), // jump over "withdraw funds" code
+ 0x33, 0x33, // jmp [end of state 2, set cycles code]
+ SIG_ADDTOOFFSET(+51), // jump over "clean bank account" code
+ 0x35, 0x02, // ldi 02
+ 0x65, 0x1a, // aTop cycles
+ 0x33, 0x0b, // jmp [toss/ret]
+ 0x3c, // dup
+ 0x35, 0x03, // ldi 03
+ 0x1a, // eq?
+ 0x31, 0x05, // bnt [toss/ret]
+ SIG_END
+};
+
+static const uint16 sq4CdPatchGetPointsForChangingBackClothes[] = {
+ PATCH_ADDTOOFFSET(+3),
+ 0x30, PATCH_UINT16(0x0070), // bnt [state 3]
+ PATCH_ADDTOOFFSET(+47), // "withdraw funds" code
+ 0x33, 0x39, // jmp [end of state 2, set cycles code]
+ PATCH_ADDTOOFFSET(+51),
+ 0x78, // push1
+ 0x39, 0x1d, // ldi 1Dh
+ 0x45, 0x07, 0x02, // call export 7 of script 0 (set flag) -> effectively sets global 73h, bit 2
+ 0x35, 0x02, // ldi 02
+ 0x65, 0x1c, // aTop cycles
+ 0x33, 0x05, // jmp [toss/ret]
+ // check for state 3 code removed to save 6 bytes
PATCH_END
};
@@ -2859,6 +2931,7 @@ static const SciScriptPatcherEntry sq4Signatures[] = {
{ true, 298, "Floppy: endless flight", 1, sq4FloppySignatureEndlessFlight, sq4FloppyPatchEndlessFlight },
{ true, 700, "Floppy: throw stuff at sequel police bug", 1, sq4FloppySignatureThrowStuffAtSequelPoliceBug, sq4FloppyPatchThrowStuffAtSequelPoliceBug },
{ true, 45, "CD: walk in from below for room 45 fix", 1, sq4CdSignatureWalkInFromBelowRoom45, sq4CdPatchWalkInFromBelowRoom45 },
+ { true, 396, "CD: get points for changing back clothes fix",1, sq4CdSignatureGetPointsForChangingBackClothes, sq4CdPatchGetPointsForChangingBackClothes },
{ true, 0, "CD: Babble icon speech and subtitles fix", 1, sq4CdSignatureBabbleIcon, sq4CdPatchBabbleIcon },
{ true, 818, "CD: Speech and subtitles option", 1, sq4CdSignatureTextOptions, sq4CdPatchTextOptions },
{ true, 818, "CD: Speech and subtitles option button", 1, sq4CdSignatureTextOptionsButton, sq4CdPatchTextOptionsButton },
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index ea3443e551..aab32032f7 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -603,8 +603,8 @@ const SciWorkaroundEntry kGraphRedrawBox_workarounds[] = {
{ GID_SQ4, 405, 405, 0, "swimAfterEgo", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified
{ GID_SQ4, 405, 405, 0, "", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573
{ GID_SQ4, 406, 406, 0, "egoFollowed", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // FLOPPY: when getting shot by the police - accidental additional parameter specified
- { GID_SQ4, 406, 406, 0, "swimAndShoot", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified
- { GID_SQ4, 406, 406, 0, "", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 (is for both egoFollowed and swimAndShoot)
+ { GID_SQ4, -1, 406, 0, "swimAndShoot", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified
+ { GID_SQ4, -1, 406, 0, "", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573 (is for both egoFollowed and swimAndShoot)
{ GID_SQ4, 410, 410, 0, "swimAfterEgo", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified
{ GID_SQ4, 410, 410, 0, "", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air... Russian version - bug #5573
{ GID_SQ4, 411, 411, 0, "swimAndShoot", "changeState", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // skateOrama when "swimming" in the air - accidental additional parameter specified
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index bac7a4665b..1cbefee105 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Thu May 7 20:24:51 2015
+ This file was generated by the md5table tool on Sun May 10 14:23:43 2015
DO NOT EDIT MANUALLY!
*/
@@ -180,7 +180,7 @@ static const MD5Table md5table[] = {
{ "3a03dab514e4038df192d8a8de469788", "atlantis", "Floppy", "Floppy", -1, Common::EN_ANY, Common::kPlatformAmiga },
{ "3a0c35f3c147b98a2bdf8d400cfc4ab5", "indy3", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns },
{ "3a3e592b074f595489f7f11e150c398d", "puttzoo", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformWindows },
- { "3a5d13675e9a23aedac0bac7730f0ac1", "samnmax", "", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh },
+ { "3a5d13675e9a23aedac0bac7730f0ac1", "samnmax", "", "CD", 228446581, Common::FR_FRA, Common::kPlatformMacintosh },
{ "3a5ec90d556d4920976c5578bfbfaf79", "maniac", "NES", "", -1, Common::DE_DEU, Common::kPlatformNES },
{ "3ae7f002d9256b8bdf76aaf8a3a069f8", "freddi", "HE 100", "", 34837, Common::EN_GRB, Common::kPlatformWii },
{ "3af61c5edf8e15b43dbafd285b2e9777", "puttcircus", "", "Demo", -1, Common::HE_ISR, Common::kPlatformWindows },
@@ -193,6 +193,7 @@ static const MD5Table md5table[] = {
{ "3df6ead57930488bc61e6e41901d0e97", "fbear", "HE 62", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "3e48298920fab9b7aec5a971e1bd1fab", "pajama3", "", "Demo", -1, Common::EN_GRB, Common::kPlatformWindows },
{ "3e861421f494711bc6f619d4aba60285", "airport", "", "", 93231, Common::RU_RUS, Common::kPlatformWindows },
+ { "403d2ec4d60d3cdae925e6cbf67716d6", "ft", "", "", 489436643, Common::FR_FRA, Common::kPlatformMacintosh },
{ "40564ec47da48a67787d1f9bd043902a", "maniac", "V2 Demo", "V2 Demo", 1988, Common::EN_ANY, Common::kPlatformDOS },
{ "4167a92a1d46baa4f4127d918d561f88", "tentacle", "", "CD", 7932, Common::EN_ANY, Common::kPlatformUnknown },
{ "41958e24d03181ff9a381a66d048a581", "ft", "", "", -1, Common::PT_BRA, Common::kPlatformUnknown },
@@ -643,7 +644,7 @@ static const MD5Table md5table[] = {
{ "ecc4340c2b801f5af8da4e00c0e432d9", "puttcircus", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "ed2b074bc3166087a747acb2a3c6abb0", "freddi3", "HE 98.5", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "ed361270102e355afe5236954216aba2", "lost", "", "", -1, Common::EN_USA, Common::kPlatformUnknown },
- { "ede149fda3edfc1dbd7347e0737cb583", "tentacle", "", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh },
+ { "ede149fda3edfc1dbd7347e0737cb583", "tentacle", "", "CD", 282830409, Common::FR_FRA, Common::kPlatformMacintosh },
{ "edfdb24a499d92c59f824c52987c0eec", "atlantis", "Floppy", "Floppy", -1, Common::FR_FRA, Common::kPlatformDOS },
{ "ee41f6afbc5b26fa475754b56fe92048", "puttputt", "HE 61", "", 8032, Common::JA_JPN, Common::kPlatform3DO },
{ "ee785fe2569bc9965526e774f7ab86f1", "spyfox", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformMacintosh },
diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp
index 1d6c12f668..21d63633d3 100644
--- a/engines/sherlock/animation.cpp
+++ b/engines/sherlock/animation.cpp
@@ -28,19 +28,15 @@ namespace Sherlock {
static const int NO_FRAMES = FRAMES_END;
-Animation::Animation(SherlockEngine *vm): _vm(vm) {
+Animation::Animation(SherlockEngine *vm) : _vm(vm) {
}
-/**
- * Play a full-screen animation
- */
bool Animation::play(const Common::String &filename, int minDelay, int fade,
bool setPalette, int speed) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
int soundNumber = 0;
- sound._playingEpilogue = true;
// Check for any any sound frames for the given animation
const int *soundFrames = checkForSoundFrames(filename);
@@ -50,8 +46,8 @@ bool Animation::play(const Common::String &filename, int minDelay, int fade,
// Load the animation
Common::SeekableReadStream *stream;
- if (!_vm->_titleOverride.empty())
- stream = _vm->_res->load(vdxName, _vm->_titleOverride);
+ if (!_gfxLibraryFilename.empty())
+ stream = _vm->_res->load(vdxName, _gfxLibraryFilename);
else if (_vm->_useEpilogue2)
stream = _vm->_res->load(vdxName, "epilog2.lib");
else
@@ -106,12 +102,12 @@ bool Animation::play(const Common::String &filename, int minDelay, int fade,
if (frameNumber++ == *soundFrames) {
++soundNumber;
++soundFrames;
- Common::String fname = _vm->_soundOverride.empty() ?
+ Common::String fname = _soundLibraryFilename.empty() ?
Common::String::format("%s%01d", filename.c_str(), soundNumber) :
Common::String::format("%s%02d", filename.c_str(), soundNumber);
if (sound._voices)
- sound.playSound(fname, WAIT_RETURN_IMMEDIATELY);
+ sound.playSound(fname, WAIT_RETURN_IMMEDIATELY, 100, _soundLibraryFilename.c_str());
}
events.wait(speed * 3);
@@ -133,23 +129,16 @@ bool Animation::play(const Common::String &filename, int minDelay, int fade,
events.clearEvents();
sound.stopSound();
delete stream;
- sound._playingEpilogue = false;
return !skipped && !_vm->shouldQuit();
}
-/**
- * Load the prologue name array
- */
void Animation::setPrologueNames(const char *const *names, int count) {
- for (int idx = 0; idx < count; ++idx, names++) {
+ for (int idx = 0; idx < count; ++idx, ++names) {
_prologueNames.push_back(*names);
}
}
-/**
- * Load the prologue frame array
- */
void Animation::setPrologueFrames(const int *frames, int count, int maxFrames) {
_prologueFrames.resize(count);
@@ -159,18 +148,12 @@ void Animation::setPrologueFrames(const int *frames, int count, int maxFrames) {
}
}
-/**
- * Load the title name array
- */
void Animation::setTitleNames(const char *const *names, int count) {
- for (int idx = 0; idx < count; ++idx, names++) {
+ for (int idx = 0; idx < count; ++idx, ++names) {
_titleNames.push_back(*names);
}
}
-/**
- * Load the title frame array
- */
void Animation::setTitleFrames(const int *frames, int count, int maxFrames) {
_titleFrames.resize(count);
@@ -180,21 +163,18 @@ void Animation::setTitleFrames(const int *frames, int count, int maxFrames) {
}
}
-/**
- * Checks for whether an animation is being played that has associated sound
- */
const int *Animation::checkForSoundFrames(const Common::String &filename) {
const int *frames = &NO_FRAMES;
- if (_vm->_soundOverride.empty()) {
- for (Common::Array<const char *>::size_type idx = 0; idx < _prologueNames.size(); ++idx) {
+ if (_soundLibraryFilename.empty()) {
+ for (uint idx = 0; idx < _prologueNames.size(); ++idx) {
if (filename.equalsIgnoreCase(_prologueNames[idx])) {
frames = &_prologueFrames[idx][0];
break;
}
}
} else {
- for (Common::Array<const char *>::size_type idx = 0; idx < _titleNames.size(); ++idx) {
+ for (uint idx = 0; idx < _titleNames.size(); ++idx) {
if (filename.equalsIgnoreCase(_titleNames[idx])) {
frames = &_titleFrames[idx][0];
break;
diff --git a/engines/sherlock/animation.h b/engines/sherlock/animation.h
index 06614df6b1..b7811d3fa8 100644
--- a/engines/sherlock/animation.h
+++ b/engines/sherlock/animation.h
@@ -39,21 +39,42 @@ private:
Common::Array<const char *> _prologueNames;
Common::Array<Common::Array<int> > _prologueFrames;
-
Common::Array<const char *> _titleNames;
Common::Array<Common::Array<int> > _titleFrames;
+ /**
+ * Checks for whether an animation is being played that has associated sound
+ */
const int *checkForSoundFrames(const Common::String &filename);
public:
+ Common::String _soundLibraryFilename;
+ Common::String _gfxLibraryFilename;
public:
Animation(SherlockEngine *vm);
+ /**
+ * Load the prologue name array
+ */
void setPrologueNames(const char *const *names, int count);
+
+ /**
+ * Load the prologue frame array
+ */
void setPrologueFrames(const int *frames, int count, int maxFrames);
+ /**
+ * Load the title name array
+ */
void setTitleNames(const char *const *names, int count);
+
+ /**
+ * Load the title frame array
+ */
void setTitleFrames(const int *frames, int count, int maxFrames);
+ /**
+ * Play a full-screen animation
+ */
bool play(const Common::String &filename, int minDelay, int fade, bool setPalette, int speed);
};
diff --git a/engines/sherlock/debugger.cpp b/engines/sherlock/debugger.cpp
index ecd3f2ee08..cfbea2bc24 100644
--- a/engines/sherlock/debugger.cpp
+++ b/engines/sherlock/debugger.cpp
@@ -30,9 +30,6 @@ Debugger::Debugger(SherlockEngine *vm) : GUI::Debugger(), _vm(vm) {
registerCmd("scene", WRAP_METHOD(Debugger, cmdScene));
}
-/**
- * Converts a decimal or hexadecimal string into a number
- */
int Debugger::strToInt(const char *s) {
if (!*s)
// No string at all
@@ -49,9 +46,6 @@ int Debugger::strToInt(const char *s) {
return (int)tmp;
}
-/**
- * Switch to another scene
- */
bool Debugger::cmdScene(int argc, const char **argv) {
if (argc != 2) {
debugPrintf("Format: scene <room>\n");
diff --git a/engines/sherlock/debugger.h b/engines/sherlock/debugger.h
index 6021bb7d0d..e6a3aba828 100644
--- a/engines/sherlock/debugger.h
+++ b/engines/sherlock/debugger.h
@@ -34,8 +34,14 @@ class Debugger : public GUI::Debugger {
private:
SherlockEngine *_vm;
+ /**
+ * Converts a decimal or hexadecimal string into a number
+ */
int strToInt(const char *s);
+ /**
+ * Switch to another scene
+ */
bool cmdScene(int argc, const char **argv);
public:
Debugger(SherlockEngine *vm);
diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp
index 2804ec1d31..ea68d79a1b 100644
--- a/engines/sherlock/detection.cpp
+++ b/engines/sherlock/detection.cpp
@@ -36,16 +36,10 @@ struct SherlockGameDescription {
GameType gameID;
};
-/**
- * Returns the Id of the game
- */
GameType SherlockEngine::getGameID() const {
return _gameDescription->gameID;
}
-/**
- * Returns the platform the game's datafiles are for
- */
Common::Platform SherlockEngine::getPlatform() const {
return _gameDescription->desc.platform;
}
@@ -60,26 +54,71 @@ static const PlainGameDescriptor sherlockGames[] = {
#define GAMEOPTION_ORIGINAL_SAVES GUIO_GAMEOPTIONS1
+#define GAMEOPTION_FADE_STYLE GUIO_GAMEOPTIONS2
+#define GAMEOPTION_HELP_STYLE GUIO_GAMEOPTIONS3
+#define GAMEOPTION_PORTRAITS_ON GUIO_GAMEOPTIONS4
+#define GAMEOPTION_WINDOW_STYLE GUIO_GAMEOPTIONS5
static const ADExtraGuiOptionsMap optionsList[] = {
{
GAMEOPTION_ORIGINAL_SAVES,
{
_s("Use original savegame dialog"),
- _s("Files button in-game shows original savegame dialog rather than ScummVM menu"),
+ _s("Files button in-game shows original savegame dialog rather than the ScummVM menu"),
"originalsaveload",
false
}
},
+ {
+ GAMEOPTION_FADE_STYLE,
+ {
+ _s("Pixellated scene transitions"),
+ _s("When changing scenes, a randomized pixel transition is done"),
+ "fade_style",
+ true
+ }
+ },
+
+ {
+ GAMEOPTION_HELP_STYLE,
+ {
+ _s("Don't show hotspots when moving mouse"),
+ _s("Only show hotspot names after you actually click on a hotspot or action button"),
+ "help_style",
+ false
+ }
+ },
+
+ {
+ GAMEOPTION_PORTRAITS_ON,
+ {
+ _s("Show character portraits"),
+ _s("Show portraits for the characters when conversing"),
+ "portraits_on",
+ true
+ }
+ },
+
+ {
+ GAMEOPTION_WINDOW_STYLE,
+ {
+ _s("Slide dialogs into view"),
+ _s("Slide UI dialogs into view, rather than simply showing them immediately"),
+ "window_style",
+ true
+ }
+ },
+
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};
+
#include "sherlock/detection_tables.h"
class SherlockMetaEngine : public AdvancedMetaEngine {
public:
- SherlockMetaEngine() : AdvancedMetaEngine(Sherlock::gameDescriptions, sizeof(Sherlock::SherlockGameDescription),
+ SherlockMetaEngine() : AdvancedMetaEngine(Sherlock::gameDescriptions, sizeof(Sherlock::SherlockGameDescription),
sherlockGames, optionsList) {}
virtual const char *getName() const {
@@ -90,17 +129,37 @@ public:
return "Sherlock Engine (C) 1992-1996 Mythos Software, 1992-1996 (C) Electronic Arts";
}
+ /**
+ * Creates an instance of the game engine
+ */
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+
+ /**
+ * Returns a list of features the game's MetaEngine support
+ */
virtual bool hasFeature(MetaEngineFeature f) const;
+
+ /**
+ * Return a list of savegames
+ */
virtual SaveStateList listSaves(const char *target) const;
+
+ /**
+ * Returns the maximum number of allowed save slots
+ */
virtual int getMaximumSaveSlot() const;
+
+ /**
+ * Deletes a savegame in the specified slot
+ */
virtual void removeSaveState(const char *target, int slot) const;
+
+ /**
+ * Given a specified savegame slot, returns extended information for the save
+ */
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
};
-/**
- * Creates an instance of the game engine
- */
bool SherlockMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
const Sherlock::SherlockGameDescription *gd = (const Sherlock::SherlockGameDescription *)desc;
if (gd) {
@@ -119,9 +178,6 @@ bool SherlockMetaEngine::createInstance(OSystem *syst, Engine **engine, const AD
return gd != 0;
}
-/**
- * Returns a list of features the game's MetaEngine support
- */
bool SherlockMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves) ||
@@ -131,9 +187,6 @@ bool SherlockMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSavesSupportThumbnail);
}
-/**
- * Returns a list of features the game itself supports
- */
bool Sherlock::SherlockEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsRTL) ||
@@ -141,38 +194,23 @@ bool Sherlock::SherlockEngine::hasFeature(EngineFeature f) const {
(f == kSupportsSavingDuringRuntime);
}
-/**
- * Returns whether the version is a demo
- */
-bool Sherlock::SherlockEngine::getIsDemo() const {
+bool Sherlock::SherlockEngine::isDemo() const {
return _gameDescription->desc.flags & ADGF_DEMO;
}
-/**
- * Return a list of savegames
- */
SaveStateList SherlockMetaEngine::listSaves(const char *target) const {
return Sherlock::SaveManager::getSavegameList(target);
}
-/**
- * Returns the maximum number of allowed save slots
- */
int SherlockMetaEngine::getMaximumSaveSlot() const {
return MAX_SAVEGAME_SLOTS;
}
-/**
- * Deletes a savegame in the specified slot
- */
void SherlockMetaEngine::removeSaveState(const char *target, int slot) const {
Common::String filename = Sherlock::SaveManager(nullptr, target).generateSaveName(slot);
g_system->getSavefileManager()->removeSavefile(filename);
}
-/**
- * Given a specified savegame slot, returns extended information for the save
- */
SaveStateDescriptor SherlockMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
Common::String filename = Sherlock::SaveManager(nullptr, target).generateSaveName(slot);
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename);
@@ -197,7 +235,7 @@ SaveStateDescriptor SherlockMetaEngine::querySaveMetaInfos(const char *target, i
#if PLUGIN_ENABLED_DYNAMIC(SHERLOCK)
-REGISTER_PLUGIN_DYNAMIC(SHERLOCK, PLUGIN_TYPE_ENGINE, SherlockMetaEngine);
+ REGISTER_PLUGIN_DYNAMIC(SHERLOCK, PLUGIN_TYPE_ENGINE, SherlockMetaEngine);
#else
-REGISTER_PLUGIN_STATIC(SHERLOCK, PLUGIN_TYPE_ENGINE, SherlockMetaEngine);
+ REGISTER_PLUGIN_STATIC(SHERLOCK, PLUGIN_TYPE_ENGINE, SherlockMetaEngine);
#endif
diff --git a/engines/sherlock/detection_tables.h b/engines/sherlock/detection_tables.h
index 8300a0ffcf..208b6710af 100644
--- a/engines/sherlock/detection_tables.h
+++ b/engines/sherlock/detection_tables.h
@@ -32,8 +32,9 @@ static const SherlockGameDescription gameDescriptions[] = {
AD_ENTRY1s("talk.lib", "ad0c4d6865edf15da4e9204c08815875", 238928),
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_UNSTABLE | ADGF_NO_FLAGS,
- GUIO2(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVES)
+ ADGF_UNSTABLE,
+ GUIO6(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVES, GAMEOPTION_FADE_STYLE, GAMEOPTION_HELP_STYLE,
+ GAMEOPTION_PORTRAITS_ON, GAMEOPTION_WINDOW_STYLE)
},
GType_SerratedScalpel,
},
@@ -79,7 +80,8 @@ static const SherlockGameDescription gameDescriptions[] = {
Common::kPlatformDOS,
ADGF_UNSTABLE,
GUIO0()
- }
+ },
+ GType_RoseTattoo
},
{
@@ -97,6 +99,21 @@ static const SherlockGameDescription gameDescriptions[] = {
GType_RoseTattoo,
},
+ {
+ // Case of the Rose Tattoo - German CD
+ // Provided by m_kiewitz
+ {
+ "rosetattoo",
+ "CD",
+ AD_ENTRY1s("talk.lib", "5027aa72f0d263ed3b1c764a6c397911", 873864),
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ GType_RoseTattoo,
+ },
+
{ AD_TABLE_END_MARKER, (GameType)0 }
};
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
index 3b0b0dacc6..94ddc9a792 100644
--- a/engines/sherlock/events.cpp
+++ b/engines/sherlock/events.cpp
@@ -30,6 +30,8 @@
namespace Sherlock {
+enum ButtonFlag { LEFT_BUTTON = 1, RIGHT_BUTTON = 2 };
+
Events::Events(SherlockEngine *vm) {
_vm = vm;
_cursorImages = nullptr;
@@ -46,9 +48,6 @@ Events::~Events() {
delete _cursorImages;
}
-/**
- * Load a set of cursors from the specified file
- */
void Events::loadCursors(const Common::String &filename) {
hideCursor();
delete _cursorImages;
@@ -57,9 +56,6 @@ void Events::loadCursors(const Common::String &filename) {
_cursorId = INVALID_CURSOR;
}
-/**
- * Set the cursor to show
- */
void Events::setCursor(CursorId cursorId) {
if (cursorId == _cursorId)
return;
@@ -67,58 +63,36 @@ void Events::setCursor(CursorId cursorId) {
_cursorId = cursorId;
// Set the cursor data
- Graphics::Surface &s = (*_cursorImages)[cursorId];
+ Graphics::Surface &s = (*_cursorImages)[cursorId]._frame;
setCursor(s);
}
-/**
- * Set the cursor to show from a passed frame
- */
void Events::setCursor(const Graphics::Surface &src) {
CursorMan.replaceCursor(src.getPixels(), src.w, src.h, 0, 0, 0xff);
showCursor();
}
-/**
- * Show the mouse cursor
- */
void Events::showCursor() {
CursorMan.showMouse(true);
}
-/**
- * Hide the mouse cursor
- */
void Events::hideCursor() {
CursorMan.showMouse(false);
}
-/**
- * Returns the cursor
- */
CursorId Events::getCursor() const {
return _cursorId;
}
-/**
- * Returns true if the mouse cursor is visible
- */
bool Events::isCursorVisible() const {
return CursorMan.isVisible();
}
-/**
- * Move the mouse
- */
void Events::moveMouse(const Common::Point &pt) {
g_system->warpMouse(pt.x, pt.y);
}
-
-/**
- * Check for any pending events
- */
void Events::pollEvents() {
checkForNextFrameCounter();
@@ -143,38 +117,28 @@ void Events::pollEvents() {
case Common::EVENT_KEYUP:
return;
case Common::EVENT_LBUTTONDOWN:
- _mouseButtons |= 1;
+ _mouseButtons |= LEFT_BUTTON;
return;
case Common::EVENT_RBUTTONDOWN:
- _mouseButtons |= 2;
+ _mouseButtons |= RIGHT_BUTTON;
return;
case Common::EVENT_LBUTTONUP:
- _mouseButtons &= ~1;
+ _mouseButtons &= ~LEFT_BUTTON;
return;
case Common::EVENT_RBUTTONUP:
- _mouseButtons &= ~2;
+ _mouseButtons &= ~RIGHT_BUTTON;
return;
- case Common::EVENT_MOUSEMOVE:
- _mousePos = event.mouse;
- break;
default:
break;
}
}
}
-/**
- * Poll for events and introduce a small delay, to allow the system to
- * yield to other running programs
- */
void Events::pollEventsAndWait() {
pollEvents();
g_system->delayMillis(10);
}
-/**
- * Check whether it's time to display the next screen frame
- */
bool Events::checkForNextFrameCounter() {
// Check for next game frame
uint32 milli = g_system->getMillis();
@@ -194,20 +158,14 @@ bool Events::checkForNextFrameCounter() {
return false;
}
-/**
- * Get a pending keypress
- */
-Common::KeyState Events::getKey() {
- Common::KeyState keyState = _pendingKeys.pop();
- if ((keyState.flags & Common::KBD_SHIFT) != 0)
- keyState.ascii = toupper(keyState.ascii);
+Common::Point Events::mousePos() const {
+ return g_system->getEventManager()->getMousePos();
+}
- return keyState;
+Common::KeyState Events::getKey() {
+ return _pendingKeys.pop();
}
-/**
- * Clear any current keypress or mouse click
- */
void Events::clearEvents() {
_pendingKeys.clear();
_mouseButtons = 0;
@@ -216,24 +174,15 @@ void Events::clearEvents() {
_oldButtons = _oldRightButton = false;
}
-/**
- * Clear any pending keyboard inputs
- */
void Events::clearKeyboard() {
_pendingKeys.clear();
}
-/**
- * Delay for a given number of game frames, where each frame is 1/60th of a second
- */
void Events::wait(int numFrames) {
uint32 totalMilli = numFrames * 1000 / GAME_FRAME_RATE;
delay(totalMilli);
}
-/**
- * Does a delay of the specified number of milliseconds
- */
bool Events::delay(uint32 time, bool interruptable) {
// Different handling for really short versus extended times
if (time < 10) {
@@ -263,34 +212,25 @@ bool Events::delay(uint32 time, bool interruptable) {
}
}
-/**
- * Sets the pressed and released button flags on the raw button state previously set in pollEvents calls.
- * @remarks The events manager has separate variables for the raw immediate and old button state
- * versus the current buttons states for the frame. This method is expected to be called only once
- * per game frame
- */
void Events::setButtonState() {
_released = _rightReleased = false;
- if (_mouseButtons & 1)
+ if (_mouseButtons & LEFT_BUTTON)
_pressed = _oldButtons = true;
- if ((_mouseButtons & 1) == 0 && _oldButtons) {
+ if ((_mouseButtons & LEFT_BUTTON) == 0 && _oldButtons) {
_pressed = _oldButtons = false;
_released = true;
}
- if (_mouseButtons & 2)
+ if (_mouseButtons & RIGHT_BUTTON)
_rightPressed = _oldRightButton = true;
- if ((_mouseButtons & 2) == 0 && _oldRightButton) {
+ if ((_mouseButtons & RIGHT_BUTTON) == 0 && _oldRightButton) {
_rightPressed = _oldRightButton = false;
_rightReleased = true;
}
}
-/**
- * Checks to see to see if a key or a mouse button is pressed.
- */
bool Events::checkInput() {
setButtonState();
return kbHit() || _pressed || _released || _rightPressed || _rightReleased;
diff --git a/engines/sherlock/events.h b/engines/sherlock/events.h
index 199e14f03a..c19a92de8c 100644
--- a/engines/sherlock/events.h
+++ b/engines/sherlock/events.h
@@ -42,10 +42,12 @@ private:
SherlockEngine *_vm;
uint32 _frameCounter;
uint32 _priorFrameTime;
- Common::Point _mousePos;
ImageFile *_cursorImages;
int _mouseButtons;
+ /**
+ * Check whether it's time to display the next screen frame
+ */
bool checkForNextFrameCounter();
public:
CursorId _cursorId;
@@ -60,42 +62,102 @@ public:
Events(SherlockEngine *vm);
~Events();
+ /**
+ * Load a set of cursors from the specified file
+ */
void loadCursors(const Common::String &filename);
+ /**
+ * Set the cursor to show
+ */
void setCursor(CursorId cursorId);
+
+ /**
+ * Set the cursor to show from a passed frame
+ */
void setCursor(const Graphics::Surface &src);
+ /**
+ * Show the mouse cursor
+ */
void showCursor();
+ /**
+ * Hide the mouse cursor
+ */
void hideCursor();
+ /**
+ * Returns the cursor
+ */
CursorId getCursor() const;
+ /**
+ * Returns true if the mouse cursor is visible
+ */
bool isCursorVisible() const;
+ /**
+ * Move the mouse
+ */
void moveMouse(const Common::Point &pt);
+ /**
+ * Check for any pending events
+ */
void pollEvents();
+ /**
+ * Poll for events and introduce a small delay, to allow the system to
+ * yield to other running programs
+ */
void pollEventsAndWait();
- Common::Point mousePos() const { return _mousePos; }
+ /**
+ * Get the current mouse position
+ */
+ Common::Point mousePos() const;
uint32 getFrameCounter() const { return _frameCounter; }
bool kbHit() const { return !_pendingKeys.empty(); }
+ /**
+ * Get a pending keypress
+ */
Common::KeyState getKey();
+ /**
+ * Clear any current keypress or mouse click
+ */
void clearEvents();
+
+ /**
+ * Clear any pending keyboard inputs
+ */
void clearKeyboard();
+ /**
+ * Delay for a given number of game frames, where each frame is 1/60th of a second
+ */
void wait(int numFrames);
+ /**
+ * Does a delay of the specified number of milliseconds
+ */
bool delay(uint32 time, bool interruptable = false);
+ /**
+ * Sets the pressed and released button flags on the raw button state previously set in pollEvents calls.
+ * @remarks The events manager has separate variables for the raw immediate and old button state
+ * versus the current buttons states for the frame. This method is expected to be called only once
+ * per game frame
+ */
void setButtonState();
+ /**
+ * Checks to see to see if a key or a mouse button is pressed.
+ */
bool checkInput();
};
diff --git a/engines/sherlock/inventory.cpp b/engines/sherlock/inventory.cpp
index 397575dfd9..bbb7c75aea 100644
--- a/engines/sherlock/inventory.cpp
+++ b/engines/sherlock/inventory.cpp
@@ -31,9 +31,6 @@ InventoryItem::InventoryItem(int requiredFlag, const Common::String &name,
_examine(examine), _lookFlag(0) {
}
-/**
- * Synchronize the data for an inventory item
- */
void InventoryItem::synchronize(Common::Serializer &s) {
s.syncAsSint16LE(_requiredFlag);
s.syncAsSint16LE(_lookFlag);
@@ -50,15 +47,14 @@ Inventory::Inventory(SherlockEngine *vm) : Common::Array<InventoryItem>(), _vm(v
_invIndex = 0;
_holdings = 0;
_invMode = INVMODE_EXIT;
+ for (int i = 0; i < 6; ++i)
+ _invShapes[i] = nullptr;
}
Inventory::~Inventory() {
freeGraphics();
}
-/**
- * Free inventory data
- */
void Inventory::freeInv() {
freeGraphics();
@@ -66,9 +62,6 @@ void Inventory::freeInv() {
_invGraphicsLoaded = false;
}
-/**
- * Free any loaded inventory graphics
- */
void Inventory::freeGraphics() {
for (uint idx = 0; idx < MAX_VISIBLE_INVENTORY; ++idx)
delete _invShapes[idx];
@@ -77,10 +70,6 @@ void Inventory::freeGraphics() {
_invGraphicsLoaded = false;
}
-/**
- * Load the list of names the inventory items correspond to, if not already loaded,
- * and then calls loadGraphics to load the associated graphics
- */
void Inventory::loadInv() {
// Exit if the inventory names are already loaded
if (_names.size() > 0)
@@ -104,9 +93,6 @@ void Inventory::loadInv() {
loadGraphics();
}
-/**
- * Load the list of names of graphics for the inventory
- */
void Inventory::loadGraphics() {
if (_invGraphicsLoaded)
return;
@@ -126,38 +112,29 @@ void Inventory::loadGraphics() {
_invGraphicsLoaded = true;
}
-/**
- * Searches through the list of names that correspond to the inventory items
- * and returns the numer that matches the passed name
- */
int Inventory::findInv(const Common::String &name) {
for (int idx = 0; idx < (int)_names.size(); ++idx) {
- if (scumm_stricmp(name.c_str(), _names[idx].c_str()) == 0)
+ if (name.equalsIgnoreCase(_names[idx]))
return idx;
}
- return 1;
+ // Couldn't find the desired item
+ error("Couldn't find inventory item - %s", name.c_str());
}
-/**
- * Display the character's inventory. The slamIt parameter specifies:
- * 0 = Draw it on the back buffer, and don't display it
- * 1 = Draw it on the back buffer, and then display it
- * 2 = Draw it on the secondary back buffer, and don't display it
- */
-void Inventory::putInv(int slamIt) {
+void Inventory::putInv(InvSlamMode slamIt) {
Screen &screen = *_vm->_screen;
UserInterface &ui = *_vm->_ui;
// If an inventory item has disappeared (due to using it or giving it),
- // a blank space slot may haave appeared. If so, adjust the inventory
+ // a blank space slot may have appeared. If so, adjust the inventory
if (_invIndex > 0 && _invIndex > (_holdings - 6)) {
--_invIndex;
freeGraphics();
loadGraphics();
}
- if (slamIt != 2) {
+ if (slamIt != SLAM_SECONDARY_BUFFER) {
screen.makePanel(Common::Rect(6, 163, 54, 197));
screen.makePanel(Common::Rect(58, 163, 106, 197));
screen.makePanel(Common::Rect(110, 163, 158, 197));
@@ -169,53 +146,45 @@ void Inventory::putInv(int slamIt) {
// Iterate through displaying up to 6 objects at a time
for (int idx = _invIndex; idx < _holdings && (idx - _invIndex) < MAX_VISIBLE_INVENTORY; ++idx) {
int itemNum = idx - _invIndex;
- Surface &bb = slamIt == 2 ? screen._backBuffer2 : screen._backBuffer1;
+ Surface &bb = slamIt == SLAM_SECONDARY_BUFFER ? screen._backBuffer2 : screen._backBuffer1;
Common::Rect r(8 + itemNum * 52, 165, 51 + itemNum * 52, 194);
// Draw the background
if (idx == ui._selector) {
bb.fillRect(r, 235);
- } else if (slamIt == 2) {
+ } else if (slamIt == SLAM_SECONDARY_BUFFER) {
bb.fillRect(r, BUTTON_MIDDLE);
}
// Draw the item image
- Graphics::Surface &img = (*_invShapes[itemNum])[0]._frame;
- bb.transBlitFrom(img, Common::Point(6 + itemNum * 52 + ((47 - img.w) / 2),
- 163 + ((33 - img.h) / 2)));
+ ImageFrame &frame = (*_invShapes[itemNum])[0];
+ bb.transBlitFrom(frame, Common::Point(6 + itemNum * 52 + ((47 - frame._width) / 2),
+ 163 + ((33 - frame._height) / 2)));
}
- if (slamIt == 1)
+ if (slamIt == SLAM_DISPLAY)
screen.slamArea(6, 163, 308, 34);
- if (slamIt != 2)
+ if (slamIt != SLAM_SECONDARY_BUFFER)
ui.clearInfo();
if (slamIt == 0) {
invCommands(0);
- } else if (slamIt == 2) {
+ } else if (slamIt == SLAM_SECONDARY_BUFFER) {
screen._backBuffer = &screen._backBuffer2;
invCommands(0);
screen._backBuffer = &screen._backBuffer1;
}
}
-/**
- * Put the game into inventory mode and open the interface window.
- * The flag parameter specifies the mode:
- * 0 = plain inventory mode
- * 2 = use inventory mode
- * 3 = give inventory mode
- * 128 = Draw window in the back buffer, but don't display it
- */
-void Inventory::drawInventory(int flag) {
+void Inventory::drawInventory(InvNewMode mode) {
Screen &screen = *_vm->_screen;
UserInterface &ui = *_vm->_ui;
- int tempFlag = flag;
+ InvNewMode tempMode = mode;
loadInv();
- if (flag == 128) {
+ if (mode == INVENTORY_DONT_DISPLAY) {
screen._backBuffer = &screen._backBuffer2;
}
@@ -248,21 +217,21 @@ void Inventory::drawInventory(int flag) {
screen.makeButton(Common::Rect(INVENTORY_POINTS[7][0], CONTROLS_Y1, INVENTORY_POINTS[7][1],
CONTROLS_Y1 + 10), INVENTORY_POINTS[7][2], "__");
- if (tempFlag == 128)
- flag = 1;
- _invMode = (InvMode)flag;
+ if (tempMode == INVENTORY_DONT_DISPLAY)
+ mode = LOOK_INVENTORY_MODE;
+ _invMode = (InvMode)mode;
- if (flag) {
- ui._oldKey = INVENTORY_COMMANDS[flag];
+ if (mode != PLAIN_INVENTORY) {
+ ui._oldKey = INVENTORY_COMMANDS[(int)mode];
} else {
ui._oldKey = -1;
}
invCommands(0);
- putInv(0);
+ putInv(SLAM_DONT_DISPLAY);
- if (tempFlag != 128) {
- if (!ui._windowStyle) {
+ if (tempMode != INVENTORY_DONT_DISPLAY) {
+ if (!ui._slideWindows) {
screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
} else {
ui.summonWindow(false, CONTROLS_Y1);
@@ -278,26 +247,22 @@ void Inventory::drawInventory(int flag) {
((ScalpelUserInterface *)_vm->_ui)->_oldUse = -1;
}
-/**
- * Prints the line of inventory commands at the top of an inventory window with
- * the correct highlighting
- */
void Inventory::invCommands(bool slamIt) {
Screen &screen = *_vm->_screen;
UserInterface &ui = *_vm->_ui;
if (slamIt) {
screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1),
- _invMode == 0 ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND,
+ _invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND,
true, "Exit");
screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1),
- _invMode == 1 ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND,
+ _invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED :COMMAND_FOREGROUND,
true, "Look");
screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1),
- _invMode == 2 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
+ _invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
true, "Use");
screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1),
- _invMode == 3 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
+ _invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
true, "Give");
screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1),
_invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
@@ -311,20 +276,20 @@ void Inventory::invCommands(bool slamIt) {
screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1),
(_holdings - _invIndex <= 6) ? COMMAND_NULL : COMMAND_FOREGROUND,
"__");
- if (_invMode != 1)
+ if (_invMode != INVMODE_LOOK)
ui.clearInfo();
} else {
screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1),
- _invMode == 0 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
+ _invMode == INVMODE_EXIT ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
false, "Exit");
screen.buttonPrint(Common::Point(INVENTORY_POINTS[1][2], CONTROLS_Y1),
- _invMode == 1 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
+ _invMode == INVMODE_LOOK ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
false, "Look");
screen.buttonPrint(Common::Point(INVENTORY_POINTS[2][2], CONTROLS_Y1),
- _invMode == 2 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
+ _invMode == INVMODE_USE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
false, "Use");
screen.buttonPrint(Common::Point(INVENTORY_POINTS[3][2], CONTROLS_Y1),
- _invMode == 3 ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
+ _invMode == INVMODE_GIVE ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND,
false, "Give");
screen.gPrint(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1),
_invIndex == 0 ? COMMAND_NULL : COMMAND_FOREGROUND,
@@ -341,31 +306,49 @@ void Inventory::invCommands(bool slamIt) {
}
}
-/**
- * Set the highlighting color of a given inventory item
- */
void Inventory::highlight(int index, byte color) {
Screen &screen = *_vm->_screen;
Surface &bb = *screen._backBuffer;
int slot = index - _invIndex;
- Graphics::Surface &img = (*_invShapes[slot])[0]._frame;
+ ImageFrame &frame = (*_invShapes[slot])[0];
bb.fillRect(Common::Rect(8 + slot * 52, 165, (slot + 1) * 52, 194), color);
- bb.transBlitFrom(img, Common::Point(6 + slot * 52 + ((47 - img.w) / 2),
- 163 + ((33 - img.h) / 2)));
+ bb.transBlitFrom(frame, Common::Point(6 + slot * 52 + ((47 - frame._width) / 2),
+ 163 + ((33 - frame._height) / 2)));
screen.slamArea(8 + slot * 52, 165, 44, 30);
}
-/**
- * Adds a shape from the scene to the player's inventory
- */
+void Inventory::refreshInv() {
+ if (IS_ROSE_TATTOO)
+ return;
+
+ Screen &screen = *_vm->_screen;
+ Talk &talk = *_vm->_talk;
+ ScalpelUserInterface &ui = *(ScalpelUserInterface *)_vm->_ui;
+
+ ui._invLookFlag = true;
+ freeInv();
+
+ ui._infoFlag = true;
+ ui.clearInfo();
+
+ screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
+ Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
+ ui.examine();
+
+ if (!talk._talkToAbort) {
+ screen._backBuffer2.blitFrom((*ui._controlPanel)[0], Common::Point(0, CONTROLS_Y));
+ loadInv();
+ }
+}
+
int Inventory::putNameInInventory(const Common::String &name) {
Scene &scene = *_vm->_scene;
int matches = 0;
for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
Object &o = scene._bgShapes[idx];
- if (scumm_stricmp(name.c_str(), o._name.c_str()) == 0 && o._type != INVALID) {
+ if (name.equalsIgnoreCase(o._name) && o._type != INVALID) {
putItemInInventory(o);
++matches;
}
@@ -374,10 +357,6 @@ int Inventory::putNameInInventory(const Common::String &name) {
return matches;
}
-/**
- * Moves a specified item into the player's inventory If the item has a *PICKUP* use action,
- * then the item in the use action are added to the inventory.
- */
int Inventory::putItemInInventory(Object &obj) {
Scene &scene = *_vm->_scene;
int matches = 0;
@@ -386,14 +365,14 @@ int Inventory::putItemInInventory(Object &obj) {
if (obj._pickupFlag)
_vm->setFlags(obj._pickupFlag);
- for (int useNum = 0; useNum < 4; ++useNum) {
- if (scumm_stricmp(obj._use[useNum]._target.c_str(), "*PICKUP*") == 0) {
+ for (int useNum = 0; useNum < USE_COUNT; ++useNum) {
+ if (obj._use[useNum]._target.equalsIgnoreCase("*PICKUP*")) {
pickupFound = true;
- for (int namesNum = 0; namesNum < 4; ++namesNum) {
+ for (int namesNum = 0; namesNum < NAMES_COUNT; ++namesNum) {
for (uint bgNum = 0; bgNum < scene._bgShapes.size(); ++bgNum) {
Object &bgObj = scene._bgShapes[bgNum];
- if (scumm_stricmp(obj._use[useNum]._names[namesNum].c_str(), bgObj._name.c_str()) == 0) {
+ if (obj._use[useNum]._names[namesNum].equalsIgnoreCase(bgObj._name)) {
copyToInventory(bgObj);
if (bgObj._pickupFlag)
_vm->setFlags(bgObj._pickupFlag);
@@ -439,9 +418,6 @@ int Inventory::putItemInInventory(Object &obj) {
return matches;
}
-/**
- * Copy the passed object into the inventory
- */
void Inventory::copyToInventory(Object &obj) {
InventoryItem invItem;
invItem._name = obj._name;
@@ -454,14 +430,11 @@ void Inventory::copyToInventory(Object &obj) {
++_holdings;
}
-/**
- * Deletes a specified item from the player's inventory
- */
int Inventory::deleteItemFromInventory(const Common::String &name) {
int invNum = -1;
for (int idx = 0; idx < (int)size() && invNum == -1; ++idx) {
- if (scumm_stricmp(name.c_str(), (*this)[idx]._name.c_str()) == 0)
+ if (name.equalsIgnoreCase((*this)[idx]._name))
invNum = idx;
}
@@ -476,9 +449,6 @@ int Inventory::deleteItemFromInventory(const Common::String &name) {
return 1;
}
-/**
- * Synchronize the data for a savegame
- */
void Inventory::synchronize(Common::Serializer &s) {
s.syncAsSint16LE(_holdings);
diff --git a/engines/sherlock/inventory.h b/engines/sherlock/inventory.h
index 5b9374d7a7..02f570f5da 100644
--- a/engines/sherlock/inventory.h
+++ b/engines/sherlock/inventory.h
@@ -47,6 +47,14 @@ enum InvMode {
INVMODE_USE55 = 255
};
+enum InvNewMode {
+ PLAIN_INVENTORY = 0, LOOK_INVENTORY_MODE = 1, USE_INVENTORY_MODE = 2,
+ GIVE_INVENTORY_MODE = 3, INVENTORY_DONT_DISPLAY = 128
+};
+
+enum InvSlamMode { SLAM_DONT_DISPLAY, SLAM_DISPLAY = 1, SLAM_SECONDARY_BUFFER };
+
+
struct InventoryItem {
int _requiredFlag;
Common::String _name;
@@ -58,6 +66,9 @@ struct InventoryItem {
InventoryItem(int requiredFlag, const Common::String &name,
const Common::String &description, const Common::String &examine);
+ /**
+ * Synchronize the data for an inventory item
+ */
void synchronize(Common::Serializer &s);
};
@@ -66,6 +77,9 @@ private:
SherlockEngine *_vm;
Common::StringArray _names;
+ /**
+ * Copy the passed object into the inventory
+ */
void copyToInventory(Object &obj);
public:
ImageFile *_invShapes[MAX_VISIBLE_INVENTORY];
@@ -74,32 +88,81 @@ public:
int _invIndex;
int _holdings; // Used to hold number of visible items in active inventory.
// Since Inventory array also contains some special hidden items
+ /**
+ * Free any loaded inventory graphics
+ */
void freeGraphics();
public:
Inventory(SherlockEngine *vm);
~Inventory();
+ /**
+ * Free inventory data
+ */
void freeInv();
+ /**
+ * Load the list of names the inventory items correspond to, if not already loaded,
+ * and then calls loadGraphics to load the associated graphics
+ */
void loadInv();
+ /**
+ * Load the list of names of graphics for the inventory
+ */
void loadGraphics();
+ /**
+ * Searches through the list of names that correspond to the inventory items
+ * and returns the number that matches the passed name
+ */
int findInv(const Common::String &name);
- void putInv(int slamIt);
+ /**
+ * Display the character's inventory. The slamIt parameter specifies:
+ */
+ void putInv(InvSlamMode slamIt);
- void drawInventory(int flag);
+ /**
+ * Put the game into inventory mode and open the interface window.
+ */
+ void drawInventory(InvNewMode flag);
+ /**
+ * Prints the line of inventory commands at the top of an inventory window with
+ * the correct highlighting
+ */
void invCommands(bool slamIt);
+ /**
+ * Set the highlighting color of a given inventory item
+ */
void highlight(int index, byte color);
+ /**
+ * Support method for refreshing the display of the inventory
+ */
+ void refreshInv();
+
+ /**
+ * Adds a shape from the scene to the player's inventory
+ */
int putNameInInventory(const Common::String &name);
+
+ /**
+ * Moves a specified item into the player's inventory If the item has a *PICKUP* use action,
+ * then the item in the use action are added to the inventory.
+ */
int putItemInInventory(Object &obj);
+ /**
+ * Deletes a specified item from the player's inventory
+ */
int deleteItemFromInventory(const Common::String &name);
+ /**
+ * Synchronize the data for a savegame
+ */
void synchronize(Common::Serializer &s);
};
diff --git a/engines/sherlock/journal.cpp b/engines/sherlock/journal.cpp
index 2a7aeb4f2d..564db59042 100644
--- a/engines/sherlock/journal.cpp
+++ b/engines/sherlock/journal.cpp
@@ -27,9 +27,13 @@ namespace Sherlock {
#define JOURNAL_BUTTONS_Y 178
#define LINES_PER_PAGE 11
+#define JOURNAL_SEARCH_LEFT 15
+#define JOURNAL_SEARCH_TOP 186
+#define JOURNAL_SEARCH_RIGHT 296
+#define JOURNAL_SEACRH_MAX_CHARS 50
// Positioning of buttons in the journal view
-const int JOURNAL_POINTS[9][3] = {
+static const int JOURNAL_POINTS[9][3] = {
{ 6, 68, 37 },
{ 69, 131, 100 },
{ 132, 192, 162 },
@@ -41,7 +45,7 @@ const int JOURNAL_POINTS[9][3] = {
{ 237, 313, 275 }
};
-const int SEARCH_POINTS[3][3] = {
+static const int SEARCH_POINTS[3][3] = {
{ 51, 123, 86 },
{ 124, 196, 159 },
{ 197, 269, 232 }
@@ -49,7 +53,7 @@ const int SEARCH_POINTS[3][3] = {
/*----------------------------------------------------------------*/
-Journal::Journal(SherlockEngine *vm): _vm(vm) {
+Journal::Journal(SherlockEngine *vm) : _vm(vm) {
// Initialize fields
_maxPage = 0;
_index = 0;
@@ -57,14 +61,12 @@ Journal::Journal(SherlockEngine *vm): _vm(vm) {
_up = _down = false;
_page = 1;
- // Load the journal directory and location names
- loadJournalLocations();
+ if (_vm->_interactiveFl) {
+ // Load the journal directory and location names
+ loadJournalLocations();
+ }
}
-/**
- * Records statements that are said, in the order which they are said. The player
- * can then read the journal to review them
- */
void Journal::record(int converseNum, int statementNum, bool replyOnly) {
int saveIndex = _index;
int saveSub = _sub;
@@ -90,9 +92,6 @@ void Journal::record(int converseNum, int statementNum, bool replyOnly) {
}
}
-/**
- * Load the list of location names that the journal will make reference to
- */
void Journal::loadJournalLocations() {
Resources &res = *_vm->_res;
@@ -131,19 +130,16 @@ void Journal::loadJournalLocations() {
delete loc;
}
-/**
- * Loads the description for the current display index in the journal, and then
- * word wraps the result to prepare it for being displayed
- * @param alreadyLoaded Indicates whether the journal file is being loaded for the
- * first time, or being reloaded
- */
void Journal::loadJournalFile(bool alreadyLoaded) {
+ People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
JournalEntry &journalEntry = _journal[_index];
Common::String dirFilename = _directory[journalEntry._converseNum];
bool replyOnly = journalEntry._replyOnly;
+
+ // Get the location number from within the filename
Common::String locStr(dirFilename.c_str() + 4, dirFilename.c_str() + 6);
int newLocation = atoi(locStr.c_str());
@@ -156,8 +152,8 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
// Find the person being referred to
talk._talkTo = -1;
- for (int idx = 0; idx < MAX_PEOPLE; ++idx) {
- Common::String portrait = PORTRAITS[idx];
+ for (int idx = 0; idx < (int)people._characters.size(); ++idx) {
+ Common::String portrait = people[idx]._portrait;
Common::String numStr(portrait.c_str(), portrait.c_str() + 4);
if (locStr == numStr) {
@@ -193,11 +189,11 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
// See if title can fit into a single line, or requires splitting on 2 lines
int width = screen.stringWidth(journalString.c_str() + 1);
- if (width > 230) {
+ if (width > JOURNAL_MAX_WIDTH) {
// Scan backwards from end of title to find a space between a word
// where the width is less than the maximum allowed for the line
const char *lineP = journalString.c_str() + journalString.size() - 1;
- while (width > 230 || *lineP != ' ')
+ while (width > JOURNAL_MAX_WIDTH || *lineP != ' ')
width -= screen.charWidth(*lineP--);
// Split the header into two lines, and add a '@' prefix
@@ -227,7 +223,7 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
journalString += "the Inspector";
break;
default:
- journalString += NAMES[talk._talkTo];
+ journalString += people._characters[talk._talkTo]._name;
break;
}
journalString += ", \"";
@@ -247,8 +243,8 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
byte c = *replyP++;
// Is it a control character?
- if (c < 128) {
- // Nope. Set flag for allowing control coes to insert spaces
+ if (c < SWITCH_SPEAKER) {
+ // Nope. Set flag for allowing control codes to insert spaces
ctrlSpace = true;
assert(c >= ' ');
@@ -288,13 +284,13 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
else if (talk._talkTo == 2)
journalString += "The Inspector";
else
- journalString += NAMES[talk._talkTo];
+ journalString += people._characters[talk._talkTo]._name;
const byte *strP = replyP + 1;
byte v;
do {
v = *strP++;
- } while (v && (v < 128) && (v != '.') && (v != '!') && (v != '?'));
+ } while (v && (v < SWITCH_SPEAKER) && (v != '.') && (v != '!') && (v != '?'));
if (v == '?')
journalString += " asked, \"";
@@ -310,11 +306,11 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
journalString += c;
do {
journalString += *replyP++;
- } while (*replyP && *replyP < 128 && *replyP != '{' && *replyP != '}');
+ } while (*replyP && *replyP < SWITCH_SPEAKER && *replyP != '{' && *replyP != '}');
commentJustPrinted = false;
}
- } else if (c == 128) {
+ } else if (c == SWITCH_SPEAKER) {
if (!startOfReply) {
if (!commentFlag && !commentJustPrinted)
journalString += "\"\n";
@@ -335,13 +331,13 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
else if (c == 2)
journalString += "the Inspector";
else
- journalString += NAMES[c];
+ journalString += people._characters[c]._name;
const byte *strP = replyP;
byte v;
do {
v = *strP++;
- } while (v && v < 128 && v != '.' && v != '!' && v != '?');
+ } while (v && v < SWITCH_SPEAKER && v != '.' && v != '!' && v != '?');
if (v == '?')
journalString += " asked, \"";
@@ -401,7 +397,7 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
// Put a space in the output for a control character, unless it's
// immediately coming after another control character
- if (ctrlSpace && c != 130 && c != 161 && !commentJustPrinted) {
+ if (ctrlSpace && c != ASSIGN_PORTRAIT_LOCATION && c != CARRIAGE_RETURN && !commentJustPrinted) {
journalString += " ";
ctrlSpace = false;
}
@@ -427,11 +423,11 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
// Build up chacters until a full line is found
int width = 0;
const char *endP = startP;
- while (width < 230 && *endP && *endP != '\n' && (endP - startP) < 79)
+ while (width < JOURNAL_MAX_WIDTH && *endP && *endP != '\n' && (endP - startP) < (JOURNAL_MAX_CHARS - 1))
width += screen.charWidth(*endP++);
// If word wrapping, move back to end of prior word
- if (width >= 230 || (endP - startP) >= 79) {
+ if (width >= JOURNAL_MAX_WIDTH || (endP - startP) >= (JOURNAL_MAX_CHARS - 1)) {
while (*--endP != ' ')
;
}
@@ -451,9 +447,6 @@ void Journal::loadJournalFile(bool alreadyLoaded) {
}
}
-/**
- * Draw the journal background, frame, and interface buttons
- */
void Journal::drawJournalFrame() {
Resources &res = *_vm->_res;
Screen &screen = *_vm->_screen;
@@ -504,19 +497,16 @@ void Journal::drawJournalFrame() {
screen.makeButton(Common::Rect(JOURNAL_POINTS[8][0], JOURNAL_BUTTONS_Y + 11,
JOURNAL_POINTS[8][1], JOURNAL_BUTTONS_Y + 21),
JOURNAL_POINTS[8][2] - screen.stringWidth("Print Text") / 2, "Print Text");
- screen.buttonPrint(Common::Point(JOURNAL_POINTS[8][2], JOURNAL_BUTTONS_Y + 11),
+ screen.buttonPrint(Common::Point(JOURNAL_POINTS[8][2], JOURNAL_BUTTONS_Y + 11),
COMMAND_NULL, false, "Print Text");
}
-/**
- * Display the journal
- */
void Journal::drawInterface() {
Screen &screen = *_vm->_screen;
drawJournalFrame();
- if (_journal.size() == 0) {
+ if (_journal.empty()) {
_up = _down = 0;
} else {
drawJournal(0, 0);
@@ -528,9 +518,6 @@ void Journal::drawInterface() {
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
-/**
- * Display the arrows that can be used to scroll up and down pages
- */
void Journal::doArrows() {
Screen &screen = *_vm->_screen;
byte color;
@@ -552,9 +539,6 @@ void Journal::doArrows() {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[6][2], JOURNAL_BUTTONS_Y + 11), color, false, "First Page");
}
-/**
- * Displays a page of the journal at the current index
- */
bool Journal::drawJournal(int direction, int howFar) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -562,7 +546,7 @@ bool Journal::drawJournal(int direction, int howFar) {
int yp = 37;
int startPage = _page;
bool endJournal = false;
- bool firstOccurance = false;
+ bool firstOccurance = true;
bool searchSuccessful = false;
bool endFlag = false;
int lineNum = 0;
@@ -749,26 +733,26 @@ bool Journal::drawJournal(int direction, int howFar) {
screen.gPrint(Common::Point(53, yp), 15, "%s", lineStart.c_str() + 1);
} else {
width = screen.stringWidth(lineStart.c_str());
- screen.gPrint(Common::Point(53, yp), PEN_COLOR, lineStart.c_str());
- }
+ screen.gPrint(Common::Point(53, yp), PEN_COLOR, "%s", lineStart.c_str());
+ }
// Print out the found keyword
Common::String lineMatch(matchP, matchP + _find.size());
- screen.gPrint(Common::Point(53 + width, yp), INV_FOREGROUND, lineMatch.c_str());
+ screen.gPrint(Common::Point(53 + width, yp), INV_FOREGROUND, "%s", lineMatch.c_str());
width += screen.stringWidth(lineMatch.c_str());
// Print remainder of line
- screen.gPrint(Common::Point(53 + width, yp), PEN_COLOR, matchP + _find.size());
+ screen.gPrint(Common::Point(53 + width, yp), PEN_COLOR, "%s", matchP + _find.size());
} else if (_lines[temp].hasPrefix("@")) {
- screen.gPrint(Common::Point(53, yp), 15, _lines[temp].c_str() + 1);
+ screen.gPrint(Common::Point(53, yp), 15, "%s", _lines[temp].c_str() + 1);
} else {
- screen.gPrint(Common::Point(53, yp), PEN_COLOR, _lines[temp].c_str());
+ screen.gPrint(Common::Point(53, yp), PEN_COLOR, "%s", _lines[temp].c_str());
}
} else {
if (_lines[temp].hasPrefix("@")) {
- screen.gPrint(Common::Point(53, yp), 15, _lines[temp].c_str() + 1);
+ screen.gPrint(Common::Point(53, yp), 15, "%s", _lines[temp].c_str() + 1);
} else {
- screen.gPrint(Common::Point(53, yp), PEN_COLOR, _lines[temp].c_str());
+ screen.gPrint(Common::Point(53, yp), PEN_COLOR, "%s", _lines[temp].c_str());
}
}
@@ -800,72 +784,90 @@ bool Journal::drawJournal(int direction, int howFar) {
return direction >= 3 && searchSuccessful;
}
-/**
- * Handle events whilst the journal is being displayed
- */
+JournalButton Journal::getHighlightedButton(const Common::Point &pt) {
+ if (pt.x > JOURNAL_POINTS[0][0] && pt.x < JOURNAL_POINTS[0][1] && pt.y >= JOURNAL_BUTTONS_Y &&
+ pt.y < (JOURNAL_BUTTONS_Y + 10))
+ return BTN_EXIT;
+
+ if (pt.x > JOURNAL_POINTS[1][0] && pt.x < JOURNAL_POINTS[1][1] && pt.y >= JOURNAL_BUTTONS_Y &&
+ pt.y < (JOURNAL_BUTTONS_Y + 10) && _page > 1)
+ return BTN_BACK10;
+
+ if (pt.x > JOURNAL_POINTS[2][0] && pt.x < JOURNAL_POINTS[2][1] && pt.y >= JOURNAL_BUTTONS_Y &&
+ pt.y < (JOURNAL_BUTTONS_Y + 10) && _up)
+ return BTN_UP;
+
+ if (pt.x > JOURNAL_POINTS[3][0] && pt.x < JOURNAL_POINTS[3][1] && pt.y >= JOURNAL_BUTTONS_Y &&
+ pt.y < (JOURNAL_BUTTONS_Y + 10) && _down)
+ return BTN_DOWN;
+
+ if (pt.x > JOURNAL_POINTS[4][0] && pt.x < JOURNAL_POINTS[4][1] && pt.y >= JOURNAL_BUTTONS_Y &&
+ pt.y < (JOURNAL_BUTTONS_Y + 10) && _down)
+ return BTN_AHEAD110;
+
+ if (pt.x > JOURNAL_POINTS[5][0] && pt.x < JOURNAL_POINTS[5][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
+ pt.y < (JOURNAL_BUTTONS_Y + 20) && !_journal.empty())
+ return BTN_SEARCH;
+
+ if (pt.x > JOURNAL_POINTS[6][0] && pt.x < JOURNAL_POINTS[6][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
+ pt.y < (JOURNAL_BUTTONS_Y + 20) && _up)
+ return BTN_FIRST_PAGE;
+
+ if (pt.x > JOURNAL_POINTS[7][0] && pt.x < JOURNAL_POINTS[7][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
+ pt.y < (JOURNAL_BUTTONS_Y + 20) && _down)
+ return BTN_LAST_PAGE;
+
+ if (pt.x > JOURNAL_POINTS[8][0] && pt.x < JOURNAL_POINTS[8][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
+ pt.y < (JOURNAL_BUTTONS_Y + 20) && !_journal.empty())
+ return BTN_PRINT_TEXT;
+
+ return BTN_NONE;
+}
+
bool Journal::handleEvents(int key) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
bool doneFlag = false;
+
Common::Point pt = events.mousePos();
+ JournalButton btn = getHighlightedButton(pt);
byte color;
- enum Button {
- BTN_NONE, BTN_EXIT, BTN_BACK10, BTN_UP, BTN_DOWN, BTN_AHEAD110, BTN_SEARCH,
- BTN_FIRST_PAGE, BTN_LAST_PAGE, BTN_PRINT_TEXT
- };
- Button found = BTN_NONE;
if (events._pressed || events._released) {
// Exit button
- if (pt.x > JOURNAL_POINTS[0][0] && pt.x < JOURNAL_POINTS[0][1] && pt.y >= JOURNAL_BUTTONS_Y &&
- pt.y < (JOURNAL_BUTTONS_Y + 10)) {
- found = BTN_EXIT;
- color = COMMAND_HIGHLIGHTED;
- } else {
- color = COMMAND_FOREGROUND;
- }
+ color = (btn == BTN_EXIT) ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND;
screen.buttonPrint(Common::Point(JOURNAL_POINTS[0][2], JOURNAL_BUTTONS_Y), color, true, "Exit");
// Back 10 button
- if (pt.x > JOURNAL_POINTS[1][0] && pt.x < JOURNAL_POINTS[1][1] && pt.y >= JOURNAL_BUTTONS_Y &&
- pt.y < (JOURNAL_BUTTONS_Y + 10) && _page > 1) {
- found = BTN_BACK10;
+ if (btn == BTN_BACK10) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, "Back 10");
} else if (_page > 1) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[1][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, "Back 10");
}
// Up button
- if (pt.x > JOURNAL_POINTS[2][0] && pt.x < JOURNAL_POINTS[2][1] && pt.y >= JOURNAL_BUTTONS_Y &&
- pt.y < (JOURNAL_BUTTONS_Y + 10) && _up) {
- found = BTN_UP;
+ if (btn == BTN_UP) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[2][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, "Up");
} else if (_up) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[2][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, "Up");
}
// Down button
- if (pt.x > JOURNAL_POINTS[3][0] && pt.x < JOURNAL_POINTS[3][1] && pt.y >= JOURNAL_BUTTONS_Y &&
- pt.y < (JOURNAL_BUTTONS_Y + 10) && _down) {
- found = BTN_DOWN;
+ if (btn == BTN_DOWN) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[3][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, "Down");
} else if (_down) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[3][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, "Down");
}
// Ahead 10 button
- if (pt.x > JOURNAL_POINTS[4][0] && pt.x < JOURNAL_POINTS[4][1] && pt.y >= JOURNAL_BUTTONS_Y &&
- pt.y < (JOURNAL_BUTTONS_Y + 10) && _down) {
- found = BTN_AHEAD110;
+ if (btn == BTN_AHEAD110) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[4][2], JOURNAL_BUTTONS_Y), COMMAND_HIGHLIGHTED, true, "Ahead 10");
} else if (_down) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[4][2], JOURNAL_BUTTONS_Y), COMMAND_FOREGROUND, true, "Ahead 10");
}
// Search button
- if (pt.x > JOURNAL_POINTS[5][0] && pt.x < JOURNAL_POINTS[5][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
- pt.y < (JOURNAL_BUTTONS_Y + 20) && !_journal.empty()) {
- found = BTN_SEARCH;
+ if (btn == BTN_SEARCH) {
color = COMMAND_HIGHLIGHTED;
} else if (_journal.empty()) {
color = COMMAND_NULL;
@@ -875,9 +877,7 @@ bool Journal::handleEvents(int key) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[5][2], JOURNAL_BUTTONS_Y + 11), color, true, "Search");
// First Page button
- if (pt.x > JOURNAL_POINTS[6][0] && pt.x < JOURNAL_POINTS[6][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
- pt.y < (JOURNAL_BUTTONS_Y + 20) && _up) {
- found = BTN_FIRST_PAGE;
+ if (btn == BTN_FIRST_PAGE) {
color = COMMAND_HIGHLIGHTED;
} else if (_up) {
color = COMMAND_FOREGROUND;
@@ -887,9 +887,7 @@ bool Journal::handleEvents(int key) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[6][2], JOURNAL_BUTTONS_Y + 11), color, true, "First Page");
// Last Page button
- if (pt.x > JOURNAL_POINTS[7][0] && pt.x < JOURNAL_POINTS[7][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
- pt.y < (JOURNAL_BUTTONS_Y + 20) && _down) {
- found = BTN_LAST_PAGE;
+ if (btn == BTN_LAST_PAGE) {
color = COMMAND_HIGHLIGHTED;
} else if (_down) {
color = COMMAND_FOREGROUND;
@@ -898,20 +896,15 @@ bool Journal::handleEvents(int key) {
}
screen.buttonPrint(Common::Point(JOURNAL_POINTS[7][2], JOURNAL_BUTTONS_Y + 11), color, true, "Last Page");
-
// Print Text button
- if (pt.x > JOURNAL_POINTS[8][0] && pt.x < JOURNAL_POINTS[8][1] && pt.y >= (JOURNAL_BUTTONS_Y + 11) &&
- pt.y < (JOURNAL_BUTTONS_Y + 20) && !_journal.empty()) {
- found = BTN_PRINT_TEXT;
- }
screen.buttonPrint(Common::Point(JOURNAL_POINTS[8][2], JOURNAL_BUTTONS_Y + 11), COMMAND_NULL, true, "Print Text");
}
- if (found == BTN_EXIT && events._released)
+ if (btn == BTN_EXIT && events._released) {
// Exit button pressed
doneFlag = true;
- if (((found == BTN_BACK10 && events._released) || key == 'B') && (_page > 1)) {
+ } else if (((btn == BTN_BACK10 && events._released) || key == 'B') && (_page > 1)) {
// Scrolll up 10 pages
if (_page < 11)
drawJournal(1, (_page - 1) * LINES_PER_PAGE);
@@ -920,23 +913,20 @@ bool Journal::handleEvents(int key) {
doArrows();
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
- }
- if (((found == BTN_UP && events._released) || key =='U') && _up) {
+ } else if (((btn == BTN_UP && events._released) || key == 'U') && _up) {
// Scroll up
drawJournal(1, LINES_PER_PAGE);
doArrows();
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
- }
- if (((found == BTN_DOWN && events._released) || key =='D') && _down) {
+ } else if (((btn == BTN_DOWN && events._released) || key == 'D') && _down) {
// Scroll down
drawJournal(2, LINES_PER_PAGE);
doArrows();
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
- }
- if (((found == BTN_AHEAD110 && events._released) || key == 'A') && _down) {
+ } else if (((btn == BTN_AHEAD110 && events._released) || key == 'A') && _down) {
// Scroll down 10 pages
if ((_page + 10) > _maxPage)
drawJournal(2, (_maxPage - _page) * LINES_PER_PAGE);
@@ -945,16 +935,14 @@ bool Journal::handleEvents(int key) {
doArrows();
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
- }
- if (((found == BTN_SEARCH && events._released) || key == 'S') && !_journal.empty()) {
+ } else if (((btn == BTN_SEARCH && events._released) || key == 'S') && !_journal.empty()) {
screen.buttonPrint(Common::Point(JOURNAL_POINTS[5][2], JOURNAL_BUTTONS_Y + 11), COMMAND_FOREGROUND, true, "Search");
bool notFound = false;
-
do {
int dir;
- if ((dir = getFindName(notFound)) != 0) {
+ if ((dir = getSearchString(notFound)) != 0) {
int savedIndex = _index;
int savedSub = _sub;
int savedPage = _page;
@@ -978,9 +966,8 @@ bool Journal::handleEvents(int key) {
}
} while (!doneFlag);
doneFlag = false;
- }
- if (((found == BTN_FIRST_PAGE && events._released) || key == 'F') && _up) {
+ } else if (((btn == BTN_FIRST_PAGE && events._released) || key == 'F') && _up) {
// First page
_index = _sub = 0;
_up = _down = false;
@@ -990,9 +977,8 @@ bool Journal::handleEvents(int key) {
drawJournal(0, 0);
doArrows();
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
- }
- if (((found == BTN_LAST_PAGE && events._released) || key == 'L') && _down) {
+ } else if (((btn == BTN_LAST_PAGE && events._released) || key == 'L') && _down) {
// Last page
if ((_page + 10) > _maxPage)
drawJournal(2, (_maxPage - _page) * LINES_PER_PAGE);
@@ -1008,10 +994,7 @@ bool Journal::handleEvents(int key) {
return doneFlag;
}
-/**
- * Show the search submenu
- */
-int Journal::getFindName(bool printError) {
+int Journal::getSearchString(bool printError) {
enum Button { BTN_NONE, BTN_EXIT, BTN_BACKWARD, BTN_FORWARD };
Events &events = *_vm->_events;
@@ -1032,10 +1015,14 @@ int Journal::getFindName(bool printError) {
SEARCH_POINTS[1][2] - screen.stringWidth("Backward") / 2, "Backward");
screen.makeButton(Common::Rect(SEARCH_POINTS[2][0], yp, SEARCH_POINTS[2][1], yp + 10),
SEARCH_POINTS[2][2] - screen.stringWidth("Forward") / 2, "Forward");
+ screen.gPrint(Common::Point(SEARCH_POINTS[0][2] - screen.stringWidth("Exit") / 2, yp),
+ COMMAND_FOREGROUND, "E");
+ screen.gPrint(Common::Point(SEARCH_POINTS[1][2] - screen.stringWidth("Backward") / 2, yp),
+ COMMAND_FOREGROUND, "B");
+ screen.gPrint(Common::Point(SEARCH_POINTS[2][2] - screen.stringWidth("Forward") / 2, yp),
+ COMMAND_FOREGROUND, "F");
- screen.gPrint(Common::Point(SEARCH_POINTS[0][2] - screen.stringWidth("Exit") / 2, yp), COMMAND_FOREGROUND, "E");
- screen.gPrint(Common::Point(SEARCH_POINTS[1][2] - screen.stringWidth("Backward") / 2, yp), COMMAND_FOREGROUND, "B");
- screen.gPrint(Common::Point(SEARCH_POINTS[2][2] - screen.stringWidth("Forward") / 2, yp), COMMAND_FOREGROUND, "F");
+ screen.makeField(Common::Rect(12, 185, 307, 196));
screen.fillRect(Common::Rect(12, 185, 307, 186), BUTTON_BOTTOM);
screen.vLine(12, 185, 195, BUTTON_BOTTOM);
@@ -1047,7 +1034,7 @@ int Journal::getFindName(bool printError) {
INV_FOREGROUND, "Text Not Found !");
} else if (!_find.empty()) {
// There's already a search term, display it already
- screen.gPrint(Common::Point(15, 185), TALK_FOREGROUND, _find.c_str());
+ screen.gPrint(Common::Point(15, 185), TALK_FOREGROUND, "%s", _find.c_str());
name = _find;
}
@@ -1055,6 +1042,7 @@ int Journal::getFindName(bool printError) {
if (printError) {
// Give time for user to see the message
+ events.setButtonState();
for (int idx = 0; idx < 40 && !_vm->shouldQuit() && !events.kbHit() && !events._released; ++idx) {
events.pollEvents();
events.setButtonState();
@@ -1062,18 +1050,18 @@ int Journal::getFindName(bool printError) {
}
events.clearKeyboard();
- screen.fillRect(Common::Rect(13, 186, 306, 195), BUTTON_MIDDLE);
+ screen._backBuffer1.fillRect(Common::Rect(13, 186, 306, 195), BUTTON_MIDDLE);
if (!_find.empty()) {
- screen.gPrint(Common::Point(15, 185), TALK_FOREGROUND, _find.c_str());
+ screen.gPrint(Common::Point(15, 185), TALK_FOREGROUND, "%s", _find.c_str());
name = _find;
}
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
- xp = 15 + screen.stringWidth(name);
- yp = 186;
+ xp = JOURNAL_SEARCH_LEFT + screen.stringWidth(name);
+ yp = JOURNAL_SEARCH_TOP;
do {
events._released = false;
@@ -1128,23 +1116,21 @@ int Journal::getFindName(bool printError) {
xp -= screen.charWidth(name.lastChar());
screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), INV_FOREGROUND);
name.deleteLastChar();
- }
- if (keyState.keycode == Common::KEYCODE_RETURN)
+ } else if (keyState.keycode == Common::KEYCODE_RETURN) {
done = 1;
- if (keyState.keycode == Common::KEYCODE_ESCAPE) {
+ } else if (keyState.keycode == Common::KEYCODE_ESCAPE) {
screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), BUTTON_MIDDLE);
done = -1;
- }
- if (keyState.keycode >= Common::KEYCODE_SPACE && keyState.keycode <= Common::KEYCODE_z
- && keyState.keycode != Common::KEYCODE_AT && name.size() < 50
- && (xp + screen.charWidth(keyState.keycode)) < 296) {
+ } else if (keyState.ascii >= ' ' && keyState.ascii <= 'z' && keyState.keycode != Common::KEYCODE_AT &&
+ name.size() < JOURNAL_SEACRH_MAX_CHARS && (xp + screen.charWidth(keyState.ascii)) < JOURNAL_SEARCH_RIGHT) {
+ char ch = toupper(keyState.ascii);
screen.vgaBar(Common::Rect(xp, yp, xp + 8, yp + 9), BUTTON_MIDDLE);
- screen.print(Common::Point(xp, yp), TALK_FOREGROUND, "%c", (char)keyState.keycode);
- xp += screen.charWidth((char)keyState.keycode);
- name += (char)keyState.keycode;
+ screen.print(Common::Point(xp, yp), TALK_FOREGROUND, "%c", ch);
+ xp += screen.charWidth(ch);
+ name += ch;
}
}
@@ -1160,7 +1146,7 @@ int Journal::getFindName(bool printError) {
break;
}
}
- } while (!done);
+ } while (!done && !_vm->shouldQuit());
if (done != -1) {
_find = name;
@@ -1176,17 +1162,11 @@ int Journal::getFindName(bool printError) {
return done;
}
-/**
- * Reset viewing position to the start of the journal
- */
void Journal::resetPosition() {
_index = _sub = _up = _down = 0;
_page = 1;
}
-/**
- * Synchronize the data for a savegame
- */
void Journal::synchronize(Common::Serializer &s) {
s.syncAsSint16LE(_index);
s.syncAsSint16LE(_sub);
diff --git a/engines/sherlock/journal.h b/engines/sherlock/journal.h
index be5c4d77c3..d62b8338c0 100644
--- a/engines/sherlock/journal.h
+++ b/engines/sherlock/journal.h
@@ -25,12 +25,22 @@
#include "common/scummsys.h"
#include "common/array.h"
+#include "common/rect.h"
#include "common/serializer.h"
#include "common/str-array.h"
#include "common/stream.h"
namespace Sherlock {
+#define JOURNAL_MAX_WIDTH 230
+#define JOURNAL_MAX_CHARS 80
+
+enum JournalButton {
+ BTN_NONE, BTN_EXIT, BTN_BACK10, BTN_UP, BTN_DOWN, BTN_AHEAD110, BTN_SEARCH,
+ BTN_FIRST_PAGE, BTN_LAST_PAGE, BTN_PRINT_TEXT
+};
+
+
struct JournalEntry {
int _converseNum;
bool _replyOnly;
@@ -57,28 +67,70 @@ private:
int _page;
Common::String _find;
+ /**
+ * Load the list of location names that the journal will make reference to
+ */
void loadJournalLocations();
+ /**
+ * Loads the description for the current display index in the journal, and then
+ * word wraps the result to prepare it for being displayed
+ * @param alreadyLoaded Indicates whether the journal file is being loaded for the
+ * first time, or being reloaded
+ */
void loadJournalFile(bool alreadyLoaded);
+ /**
+ * Display the arrows that can be used to scroll up and down pages
+ */
void doArrows();
+ /**
+ * Displays a page of the journal at the current index
+ */
bool drawJournal(int direction, int howFar);
- int getFindName(bool printError);
+ /**
+ * Show the search submenu and allow the player to enter a search string
+ */
+ int getSearchString(bool printError);
+ /**
+ * Draw the journal background, frame, and interface buttons
+ */
void drawJournalFrame();
+
+ /**
+ * Returns the button, if any, that is under the specified position
+ */
+ JournalButton getHighlightedButton(const Common::Point &pt);
public:
Journal(SherlockEngine *vm);
+ /**
+ * Records statements that are said, in the order which they are said. The player
+ * can then read the journal to review them
+ */
void record(int converseNum, int statementNum, bool replyOnly = false);
+ /**
+ * Display the journal
+ */
void drawInterface();
+ /**
+ * Handle events whilst the journal is being displayed
+ */
bool handleEvents(int key);
+ /**
+ * Reset viewing position to the start of the journal
+ */
void resetPosition();
+ /**
+ * Synchronize the data for a savegame
+ */
void synchronize(Common::Serializer &s);
};
diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp
index 46e233bf7a..44ca7cd44c 100644
--- a/engines/sherlock/map.cpp
+++ b/engines/sherlock/map.cpp
@@ -26,9 +26,10 @@
namespace Sherlock {
-/**
- * Load the data for the paths between locations on the map
- */
+MapPaths::MapPaths() {
+ _numLocations = 0;
+}
+
void MapPaths::load(int numLocations, Common::SeekableReadStream &s) {
_numLocations = numLocations;
_paths.resize(_numLocations * _numLocations);
@@ -44,9 +45,6 @@ void MapPaths::load(int numLocations, Common::SeekableReadStream &s) {
}
}
-/**
- * Get the path between two locations on the map
- */
const byte *MapPaths::getPath(int srcLocation, int destLocation) {
return &_paths[srcLocation * _numLocations + destLocation][0];
}
@@ -64,36 +62,27 @@ Map::Map(SherlockEngine *vm): _vm(vm), _topLine(g_system->getWidth(), 12) {
_drawMap = false;
_overPos = Common::Point(13000, 12600);
_charPoint = 0;
- _oldCharPoint = 39;
+ _oldCharPoint = 0;
_frameChangeFlag = false;
for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx)
Common::fill(&_sequences[idx][0], &_sequences[idx][MAX_FRAME], 0);
- if (!_vm->getIsDemo())
+ if (!_vm->isDemo())
loadData();
}
-/**
- * Loads the list of points for locations on the map for each scene
- */
void Map::loadPoints(int count, const int *xList, const int *yList, const int *transList) {
for (int idx = 0; idx < count; ++idx, ++xList, ++yList, ++transList) {
_points.push_back(MapEntry(*xList, *yList, *transList));
}
}
-/**
- * Load the sequence data for player icon animations
- */
void Map::loadSequences(int count, const byte *seq) {
for (int idx = 0; idx < count; ++idx, seq += MAX_FRAME)
Common::copy(seq, seq + MAX_FRAME, &_sequences[idx][0]);
}
-/**
- * Load data needed for the map
- */
void Map::loadData() {
// TODO: Remove this
if (_vm->getGameID() == GType_RoseTattoo)
@@ -131,9 +120,6 @@ void Map::loadData() {
delete pathStream;
}
-/**
- * Show the map
- */
int Map::show() {
Events &events = *_vm->_events;
People &people = *_vm->_people;
@@ -252,7 +238,7 @@ int Map::show() {
// Show wait cursor
_cursorIndex = 1;
- events.setCursor((*_mapCursors)[_cursorIndex]);
+ events.setCursor((*_mapCursors)[_cursorIndex]._frame);
}
}
@@ -285,19 +271,15 @@ int Map::show() {
return _charPoint;
}
-/**
- * Load and initialize all the sprites that are needed for the map display
- */
void Map::setupSprites() {
Events &events = *_vm->_events;
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
- typedef byte Sequences[16][MAX_FRAME];
_savedPos.x = -1;
_mapCursors = new ImageFile("omouse.vgs");
_cursorIndex = 0;
- events.setCursor((*_mapCursors)[_cursorIndex]);
+ events.setCursor((*_mapCursors)[_cursorIndex]._frame);
_shapes = new ImageFile("mapicon.vgs");
_iconShapes = new ImageFile("overicon.vgs");
@@ -325,9 +307,6 @@ void Map::setupSprites() {
scene._bgShapes.clear();
}
-/**
- * Free the sprites and data used by the map
- */
void Map::freeSprites() {
delete _mapCursors;
delete _shapes;
@@ -335,9 +314,6 @@ void Map::freeSprites() {
_iconSave.free();
}
-/**
- * Draws an icon for every place that's currently known
- */
void Map::showPlaces() {
Screen &screen = *_vm->_screen;
@@ -356,25 +332,16 @@ void Map::showPlaces() {
}
}
-/**
- * Makes a copy of the top rows of the screen that are used to display location names
- */
void Map::saveTopLine() {
_topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12));
}
-/**
- * Erases anything shown in the top line by restoring the previously saved original map background
- */
void Map::eraseTopLine() {
Screen &screen = *_vm->_screen;
screen._backBuffer1.blitFrom(_topLine, Common::Point(0, 0));
- screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.h);
+ screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.h());
}
-/**
- * Prints the name of the specified icon
- */
void Map::showPlaceName(int idx, bool highlighted) {
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
@@ -387,22 +354,19 @@ void Map::showPlaceName(int idx, bool highlighted) {
bool flipped = people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
|| people[AL]._sequenceNumber == MAP_UPLEFT;
- screen._backBuffer1.transBlitFrom(people[AL]._imageFrame->_frame, _lDrawnPos, flipped);
+ screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, _lDrawnPos, flipped);
}
if (highlighted) {
int xp = (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(name)) / 2;
- screen.gPrint(Common::Point(xp + 2, 2), 0, name.c_str());
- screen.gPrint(Common::Point(xp + 1, 1), 0, name.c_str());
- screen.gPrint(Common::Point(xp, 0), 12, name.c_str());
+ screen.gPrint(Common::Point(xp + 2, 2), 0, "%s", name.c_str());
+ screen.gPrint(Common::Point(xp + 1, 1), 0, "%s", name.c_str());
+ screen.gPrint(Common::Point(xp, 0), 12, "%s", name.c_str());
screen.slamArea(xp, 0, width + 2, 15);
}
}
-/**
- * Update all on-screen sprites to account for any scrolling of the map
- */
void Map::updateMap(bool flushScreen) {
Events &events = *_vm->_events;
People &people = *_vm->_people;
@@ -415,7 +379,7 @@ void Map::updateMap(bool flushScreen) {
if (++_cursorIndex > (1 + 8))
_cursorIndex = 1;
- events.setCursor((*_mapCursors)[(_cursorIndex + 1) / 2]);
+ events.setCursor((*_mapCursors)[(_cursorIndex + 1) / 2]._frame);
}
if (!_drawMap && !flushScreen)
@@ -432,9 +396,9 @@ void Map::updateMap(bool flushScreen) {
saveIcon(people[AL]._imageFrame, hPos);
if (people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
|| people[AL]._sequenceNumber == MAP_UPLEFT)
- screen._backBuffer1.transBlitFrom(people[AL]._imageFrame->_frame, hPos, true);
+ screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, true);
else
- screen._backBuffer1.transBlitFrom(people[AL]._imageFrame->_frame, hPos, false);
+ screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, false);
if (flushScreen) {
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
@@ -449,9 +413,6 @@ void Map::updateMap(bool flushScreen) {
}
}
-/**
- * Handle moving icon for player from their previous location on the map to a destination location
- */
void Map::walkTheStreets() {
People &people = *_vm->_people;
Common::Array<Common::Point> tempPath;
@@ -510,9 +471,6 @@ void Map::walkTheStreets() {
people._walkTo.push(destPos);
}
-/**
- * Save the area under the player's icon
- */
void Map::saveIcon(ImageFrame *src, const Common::Point &pt) {
Screen &screen = *_vm->_screen;
Common::Point size(src->_width, src->_height);
@@ -540,16 +498,13 @@ void Map::saveIcon(ImageFrame *src, const Common::Point &pt) {
return;
}
- assert(size.x <= _iconSave.w && size.y <= _iconSave.h);
+ assert(size.x <= _iconSave.w() && size.y <= _iconSave.h());
_iconSave.blitFrom(screen._backBuffer1, Common::Point(0, 0),
Common::Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y));
_savedPos = pos;
_savedSize = size;
}
-/**
- * Restore the area under the player's icon
- */
void Map::restoreIcon() {
Screen &screen = *_vm->_screen;
@@ -558,9 +513,6 @@ void Map::restoreIcon() {
screen._backBuffer1.blitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y));
}
-/**
- * Handles highlighting map icons, showing their names
- */
void Map::highlightIcon(const Common::Point &pt) {
int oldPoint = _point;
@@ -599,9 +551,6 @@ void Map::highlightIcon(const Common::Point &pt) {
}
}
-/**
-* Synchronize the data for a savegame
-*/
void Map::synchronize(Common::Serializer &s) {
s.syncAsSint16LE(_bigPos.x);
s.syncAsSint16LE(_bigPos.y);
diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h
index 4a418138b2..ab70b0885f 100644
--- a/engines/sherlock/map.h
+++ b/engines/sherlock/map.h
@@ -48,9 +48,18 @@ class MapPaths {
private:
int _numLocations;
Common::Array< Common::Array<byte> > _paths;
+
public:
+ MapPaths();
+
+ /**
+ * Load the data for the paths between locations on the map
+ */
void load(int numLocations, Common::SeekableReadStream &s);
+ /**
+ * Get the path between two locations on the map
+ */
const byte *getPath(int srcLocation, int destLocation);
};
@@ -75,24 +84,64 @@ private:
bool _drawMap;
Surface _iconSave;
private:
+ /**
+ * Load data needed for the map
+ */
void loadData();
+ /**
+ * Load and initialize all the sprites that are needed for the map display
+ */
void setupSprites();
+
+ /**
+ * Free the sprites and data used by the map
+ */
void freeSprites();
+ /**
+ * Draws an icon for every place that's currently known
+ */
void showPlaces();
+ /**
+ * Makes a copy of the top rows of the screen that are used to display location names
+ */
void saveTopLine();
+
+ /**
+ * Erases anything shown in the top line by restoring the previously saved original map background
+ */
void eraseTopLine();
+
+ /**
+ * Prints the name of the specified icon
+ */
void showPlaceName(int idx, bool highlighted);
+ /**
+ * Update all on-screen sprites to account for any scrolling of the map
+ */
void updateMap(bool flushScreen);
+ /**
+ * Handle moving icon for player from their previous location on the map to a destination location
+ */
void walkTheStreets();
+ /**
+ * Save the area under the player's icon
+ */
void saveIcon(ImageFrame *src, const Common::Point &pt);
+
+ /**
+ * Restore the area under the player's icon
+ */
void restoreIcon();
+ /**
+ * Handles highlighting map icons, showing their names
+ */
void highlightIcon(const Common::Point &pt);
public:
bool _active;
@@ -105,11 +154,24 @@ public:
const MapEntry &operator[](int idx) { return _points[idx]; }
+ /**
+ * Loads the list of points for locations on the map for each scene
+ */
void loadPoints(int count, const int *xList, const int *yList, const int *transList);
+
+ /**
+ * Load the sequence data for player icon animations
+ */
void loadSequences(int count, const byte *seq);
+ /**
+ * Show the map
+ */
int show();
+ /**
+ * Synchronize the data for a savegame
+ */
void synchronize(Common::Serializer &s);
};
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 2576ff04d6..f3803518ee 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -41,9 +41,6 @@ namespace Sherlock {
SherlockEngine *Sprite::_vm;
-/**
- * Reset the data for the sprite
- */
void Sprite::clear() {
_name = "";
_description = "";
@@ -68,18 +65,12 @@ void Sprite::clear() {
_numFrames = 0;
}
-/**
- * Updates the image frame poiner for the sprite
- */
void Sprite::setImageFrame() {
int imageNumber = (*_sequences)[_sequenceNumber][_frameNumber] +
(*_sequences)[_sequenceNumber][0] - 2;
_imageFrame = &(*_images)[imageNumber];
}
-/**
- * This adjusts the sprites position, as well as it's animation sequence:
- */
void Sprite::adjustSprite() {
Map &map = *_vm->_map;
People &people = *_vm->_people;
@@ -175,9 +166,6 @@ void Sprite::adjustSprite() {
}
}
-/**
- * Checks the sprite's position to see if it's collided with any special objects
- */
void Sprite::checkSprite() {
Events &events = *_vm->_events;
People &people = *_vm->_people;
@@ -364,9 +352,6 @@ void Sprite::checkSprite() {
/*----------------------------------------------------------------*/
-/**
- * Load the data for the action
- */
void ActionType::load(Common::SeekableReadStream &s) {
char buffer[12];
@@ -375,7 +360,7 @@ void ActionType::load(Common::SeekableReadStream &s) {
if (_cAnimSpeed & 0x80)
_cAnimSpeed = -(_cAnimSpeed & 0x7f);
- for (int idx = 0; idx < 4; ++idx) {
+ for (int idx = 0; idx < NAMES_COUNT; ++idx) {
s.read(buffer, 12);
_names[idx] = Common::String(buffer);
}
@@ -386,13 +371,8 @@ void ActionType::load(Common::SeekableReadStream &s) {
UseType::UseType() {
_cAnimNum = _cAnimSpeed = 0;
_useFlag = 0;
- _dFlag[0] = 0;
- _lFlag[0] = _lFlag[1] = 0;
}
-/**
- * Load the data for the UseType
- */
void UseType::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
char buffer[12];
@@ -406,18 +386,15 @@ void UseType::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
if (_cAnimSpeed & 0x80)
_cAnimSpeed = -(_cAnimSpeed & 0x7f);
- for (int idx = 0; idx < 4; ++idx) {
+ for (int idx = 0; idx < NAMES_COUNT; ++idx) {
s.read(buffer, 12);
_names[idx] = Common::String(buffer);
}
_useFlag = s.readSint16LE();
- if (!isRoseTattoo) {
- _dFlag[0] = s.readSint16LE();
- _lFlag[0] = s.readSint16LE();
- _lFlag[1] = s.readSint16LE();
- }
+ if (!isRoseTattoo)
+ s.skip(6);
s.read(buffer, 12);
_target = Common::String(buffer);
@@ -473,9 +450,6 @@ Object::Object() {
_restoreSlot = 0;
}
-/**
- * Load the data for the object
- */
void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
char buffer[41];
s.read(buffer, 12);
@@ -560,9 +534,6 @@ void Object::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
}
}
-/**
- * Toggle the type of an object between hidden and active
- */
void Object::toggleHidden() {
if (_type != HIDDEN && _type != HIDE_SHAPE && _type != INVALID) {
if (_seqTo != 0)
@@ -598,13 +569,10 @@ void Object::toggleHidden() {
}
}
-/**
- * Check the state of the object
- */
void Object::checkObject() {
Scene &scene = *_vm->_scene;
Sound &sound = *_vm->_sound;
- int checkFrame = _allow ? MAX_FRAME : 32000;
+ int checkFrame = _allow ? MAX_FRAME : FRAMES_END;
bool codeFound;
if (_seqTo) {
@@ -640,7 +608,7 @@ void Object::checkObject() {
_seqCounter2 = _seqCounter;
_seqStack = _frameNumber + 1;
setObjSequence(v, false);
- } else if (v >= SOUND_CODE && (v <= (SOUND_CODE + 29))) {
+ } else if (v >= SOUND_CODE && (v < (SOUND_CODE + 30))) {
codeFound = true;
++_frameNumber;
v -= SOUND_CODE;
@@ -649,7 +617,7 @@ void Object::checkObject() {
if (!scene._sounds[v - 1]._name.empty() && sound._digitized)
sound.playLoadedSound(v - 1, WAIT_RETURN_IMMEDIATELY);
}
- } else if (v >= FLIP_CODE && v <= (FLIP_CODE + 2)) {
+ } else if (v >= FLIP_CODE && v < (FLIP_CODE + 3)) {
// Flip code
codeFound = true;
++_frameNumber;
@@ -659,15 +627,15 @@ void Object::checkObject() {
switch (v) {
case 0:
// Clear the flag
- _flags &= ~2;
+ _flags &= ~OBJ_FLIPPED;
break;
case 1:
// Set the flag
- _flags |= 2;
+ _flags |= OBJ_FLIPPED;
break;
case 2:
// Toggle the flag
- _flags ^= 2;
+ _flags ^= OBJ_FLIPPED;
break;
default:
break;
@@ -709,8 +677,8 @@ void Object::checkObject() {
_delta = pt;
_frameNumber += 2;
- } else if (v < 4) {
- for (int idx = 0; idx < 4; ++idx) {
+ } else if (v < USE_COUNT) {
+ for (int idx = 0; idx < NAMES_COUNT; ++idx) {
checkNameForCodes(_use[v]._names[idx], nullptr);
}
@@ -724,14 +692,9 @@ void Object::checkObject() {
} while (codeFound);
}
-/**
- * This will check to see if the object has reached the end of a sequence.
- * If it has, it switch to whichever next sequence should be started.
- * @returns true if the end of a sequence was reached
- */
bool Object::checkEndOfSequence() {
Screen &screen = *_vm->_screen;
- int checkFrame = _allow ? MAX_FRAME : 32000;
+ int checkFrame = _allow ? MAX_FRAME : FRAMES_END;
bool result = false;
if (_type == REMOVE || _type == INVALID)
@@ -781,13 +744,9 @@ bool Object::checkEndOfSequence() {
return result;
}
-/**
- * Scans through the sequences array and finds the designated sequence.
- * It then sets the frame number of the start of that sequence
- */
void Object::setObjSequence(int seq, bool wait) {
Scene &scene = *_vm->_scene;
- int checkFrame = _allow ? MAX_FRAME : 32000;
+ int checkFrame = _allow ? MAX_FRAME : FRAMES_END;
if (seq >= 128) {
// Loop the sequence until the count exceeded
@@ -858,12 +817,6 @@ void Object::setObjSequence(int seq, bool wait) {
}
}
-/**
- * Checks for codes
- * @param name The name to check for codes
- * @param messages Provides a lookup list of messages that can be printed
- * @returns 0 if no codes are found, 1 if codes were found
- */
int Object::checkNameForCodes(const Common::String &name, const char *const messages[]) {
Map &map = *_vm->_map;
People &people = *_vm->_people;
@@ -945,13 +898,13 @@ int Object::checkNameForCodes(const Common::String &name, const char *const mess
int messageNum = atoi(name.c_str() + 1);
ui._infoFlag = true;
ui.clearInfo();
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[messageNum]);
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[messageNum]);
ui._menuCounter = 25;
} else if (name.hasPrefix("@")) {
// Message attached to canimation
ui._infoFlag = true;
ui.clearInfo();
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, name.c_str() + 1);
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", name.c_str() + 1);
printed = true;
ui._menuCounter = 25;
}
@@ -959,14 +912,11 @@ int Object::checkNameForCodes(const Common::String &name, const char *const mess
return printed;
}
-/**
- * Handle setting any flags associated with the object
- */
void Object::setFlagsAndToggles() {
Scene &scene = *_vm->_scene;
Talk &talk = *_vm->_talk;
- for (int useIdx = 0; useIdx < 4; ++useIdx) {
+ for (int useIdx = 0; useIdx < USE_COUNT; ++useIdx) {
if (_use[useIdx]._useFlag) {
if (!_vm->readFlags(_use[useIdx]._useFlag))
_vm->setFlags(_use[useIdx]._useFlag);
@@ -981,16 +931,12 @@ void Object::setFlagsAndToggles() {
}
if (!talk._talkToAbort) {
- for (int idx = 0; idx < 4; ++idx)
+ for (int idx = 0; idx < NAMES_COUNT; ++idx)
scene.toggleObject(_use[useIdx]._names[idx]);
}
}
}
-/**
- * Adjusts the sprite's position and animation sequence, advancing by 1 frame.
- * If the end of the sequence is reached, the appropriate action is taken.
- */
void Object::adjustObject() {
if (_type == REMOVE)
return;
@@ -1013,10 +959,6 @@ void Object::adjustObject() {
}
}
-/**
- * Handles trying to pick up an object. If allowed, plays an y necessary animation for picking
- * up the item, and then adds it to the player's inventory
- */
int Object::pickUpObject(const char *const messages[]) {
Inventory &inv = *_vm->_inventory;
People &people = *_vm->_people;
@@ -1029,7 +971,7 @@ int Object::pickUpObject(const char *const messages[]) {
int numObjects = 0;
if (pickup == 99) {
- for (int idx = 0; idx < 4 && !talk._talkToAbort; ++idx) {
+ for (int idx = 0; idx < NAMES_COUNT && !talk._talkToAbort; ++idx) {
if (checkNameForCodes(_use[0]._names[idx], nullptr)) {
if (!talk._talkToAbort)
printed = true;
@@ -1046,7 +988,7 @@ int Object::pickUpObject(const char *const messages[]) {
ui._infoFlag = true;
ui.clearInfo();
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[message]);
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[message]);
ui._menuCounter = 30;
} else {
// Pick it up
@@ -1076,7 +1018,7 @@ int Object::pickUpObject(const char *const messages[]) {
ui._temp1 = 1;
}
- for (int idx = 0; idx < 4 && !talk._talkToAbort; ++idx) {
+ for (int idx = 0; idx < NAMES_COUNT && !talk._talkToAbort; ++idx) {
if (checkNameForCodes(_use[0]._names[idx], nullptr)) {
if (!talk._talkToAbort)
printed = true;
@@ -1103,9 +1045,6 @@ int Object::pickUpObject(const char *const messages[]) {
return numObjects;
}
-/**
- * Returns the current bounds for the sprite
- */
const Common::Rect Object::getNewBounds() const {
Common::Point pt = _position;
if (_imageFrame)
@@ -1114,17 +1053,11 @@ const Common::Rect Object::getNewBounds() const {
return Common::Rect(pt.x, pt.y, pt.x + frameWidth(), pt.y + frameHeight());
}
-/**
- * Returns the bounds for a sprite without a shape
- */
const Common::Rect Object::getNoShapeBounds() const {
return Common::Rect(_position.x, _position.y,
_position.x + _noShapeSize.x, _position.y + _noShapeSize.y);
}
-/**
- * Returns the old bounsd for the sprite from the previous frame
- */
const Common::Rect Object::getOldBounds() const {
return Common::Rect(_oldPosition.x, _oldPosition.y,
_oldPosition.x + _oldSize.x, _oldPosition.y + _oldSize.y);
@@ -1132,9 +1065,6 @@ const Common::Rect Object::getOldBounds() const {
/*----------------------------------------------------------------*/
-/**
- * Load the data for the animation
- */
void CAnim::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
char buffer[12];
s.read(buffer, 12);
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index fd4a103a8d..b61e7e24fe 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -102,8 +102,8 @@ class Sprite {
private:
static SherlockEngine *_vm;
public:
- Common::String _name; // Name
- Common::String _description; // Description
+ Common::String _name;
+ Common::String _description;
Common::StringArray _examine; // Examine in-depth description
Common::String _pickUp; // Message for if you can't pick up object
@@ -120,7 +120,6 @@ public:
Common::Point _oldSize; // Image's old size
Common::Point _goto; // Walk destination
SpriteType _type; // Type of object
- int _pickup;
Common::Point _noShapeSize; // Size of a NO_SHAPE
int _status; // Status: open/closed, moved/not moved
int8 _misc; // Miscellaneous use
@@ -129,48 +128,85 @@ public:
Sprite() { clear(); }
static void setVm(SherlockEngine *vm) { _vm = vm; }
+ /**
+ * Reset the data for the sprite
+ */
void clear();
+ /**
+ * Updates the image frame poiner for the sprite
+ */
void setImageFrame();
+ /**
+ * This adjusts the sprites position, as well as it's animation sequence:
+ */
void adjustSprite();
+ /**
+ * Checks the sprite's position to see if it's collided with any special objects
+ */
void checkSprite();
+ /**
+ * Return frame width
+ */
int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; }
+
+ /**
+ * Return frame height
+ */
int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; }
};
enum { REVERSE_DIRECTION = 0x80 };
+#define NAMES_COUNT 4
struct ActionType {
int _cAnimNum;
int _cAnimSpeed;
- Common::String _names[4];
+ Common::String _names[NAMES_COUNT];
+ /**
+ * Load the data for the action
+ */
void load(Common::SeekableReadStream &s);
};
struct UseType {
int _cAnimNum;
int _cAnimSpeed;
- Common::String _names[4];
+ Common::String _names[NAMES_COUNT];
int _useFlag; // Which flag USE will set (if any)
- int _dFlag[1];
- int _lFlag[2];
Common::String _target;
Common::String _verb;
UseType();
+
+ /**
+ * Load the data for the UseType
+ */
void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
+enum { OBJ_BEHIND = 1, OBJ_FLIPPED = 2, OBJ_FORWARD = 4, TURNON_OBJ = 0x20, TURNOFF_OBJ = 0x40 };
+#define USE_COUNT 4
+
class Object {
private:
static SherlockEngine *_vm;
+ /**
+ * This will check to see if the object has reached the end of a sequence.
+ * If it has, it switch to whichever next sequence should be started.
+ * @returns true if the end of a sequence was reached
+ */
bool checkEndOfSequence();
+ /**
+ * Scans through the sequences array and finds the designated sequence.
+ * It then sets the frame number of the start of that sequence
+ */
void setObjSequence(int seq, bool wait);
public:
static bool _countCAnimFrames;
@@ -233,24 +269,69 @@ public:
Object();
+ /**
+ * Load the data for the object
+ */
void load(Common::SeekableReadStream &s, bool isRoseTattoo);
+ /**
+ * Toggle the type of an object between hidden and active
+ */
void toggleHidden();
+ /**
+ * Check the state of the object
+ */
void checkObject();
+ /**
+ * Checks for codes
+ * @param name The name to check for codes
+ * @param messages Provides a lookup list of messages that can be printed
+ * @returns 0 if no codes are found, 1 if codes were found
+ */
int checkNameForCodes(const Common::String &name, const char *const messages[]);
+ /**
+ * Handle setting any flags associated with the object
+ */
void setFlagsAndToggles();
+ /**
+ * Adjusts the sprite's position and animation sequence, advancing by 1 frame.
+ * If the end of the sequence is reached, the appropriate action is taken.
+ */
void adjustObject();
+ /**
+ * Handles trying to pick up an object. If allowed, plays an y necessary animation for picking
+ * up the item, and then adds it to the player's inventory
+ */
int pickUpObject(const char *const messages[]);
+ /**
+ * Return the frame width
+ */
int frameWidth() const { return _imageFrame ? _imageFrame->_frame.w : 0; }
+
+ /**
+ * Return the frame height
+ */
int frameHeight() const { return _imageFrame ? _imageFrame->_frame.h : 0; }
+
+ /**
+ * Returns the current bounds for the sprite
+ */
const Common::Rect getNewBounds() const;
+
+ /**
+ * Returns the bounds for a sprite without a shape
+ */
const Common::Rect getNoShapeBounds() const;
+
+ /**
+ * Returns the old bounsd for the sprite from the previous frame
+ */
const Common::Rect getOldBounds() const;
};
@@ -271,6 +352,9 @@ struct CAnim {
// Rose Tattoo specific
int _scaleVal; // How much the canim is scaled
+ /**
+ * Load the data for the animation
+ */
void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 0eda40c03f..3a630fdd99 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -50,144 +50,6 @@ static const uint8 CHARACTER_SEQUENCES[MAX_HOLMES_SEQUENCE][MAX_FRAME] = {
{ 52, 1, 2, 3, 4, 0 } // Goto Stand Down Left
};
-const char PORTRAITS[MAX_PEOPLE][5] = {
- { "HOLM" }, // Sherlock Holmes
- { "WATS" }, // Dr. Watson
- { "LEST" }, // Inspector Lestrade
- { "CON1" }, // Constable O'Brien
- { "CON2" }, // Constable Lewis
- { "SHEI" }, // Sheila Parker
- { "HENR" }, // Henry Carruthers
- { "LESL" }, // Lesley (flower girl)
- { "USH1" }, // Usher #1
- { "USH2" }, // Usher #2
- { "FRED" }, // Fredrick Epstein
- { "WORT" }, // Mrs. Worthington
- { "COAC" }, // Coach
- { "PLAY" }, // Player
- { "WBOY" }, // Tim (Waterboy)
- { "JAME" }, // James Sanders
- { "BELL" }, // Belle (perfumerie)
- { "GIRL" }, // Cleaning Girl (perfumerie)
- { "EPST" }, // Epstien in the Opera Balcony
- { "WIGG" }, // Wiggins
- { "PAUL" }, // Paul (Brumwell / Carroway)
- { "BART" }, // Bartender
- { "DIRT" }, // Dirty Drunk
- { "SHOU" }, // Shouting Drunk
- { "STAG" }, // Staggering Drunk
- { "BOUN" }, // Bouncer
- { "SAND" }, // James Sanders - At Home
- { "CORO" }, // The Coroner
- { "EQUE" }, // The Equestrian Shop Keeper
- { "GEOR" }, // George Blackwood
- { "LARS" }, // Lars
- { "PARK" }, // Sheila Parker (happy)
- { "CHEM" }, // Chemist
- { "GREG" }, // Inspector Gregson
- { "LAWY" }, // Jacob Farthington Lawyer
- { "MYCR" }, // Mycroft
- { "SHER" }, // Old Sherman
- { "CHMB" }, // Richard Chemist Stock boy
- { "BARM" }, // Barman
- { "DAND" }, // Dandy Player
- { "ROUG" }, // Rough-looking Player
- { "SPEC" }, // Spectator
- { "HUNT" }, // Robert Hunt
- { "VIOL" }, // Violet Secretary
- { "PETT" }, // Pettigrew
- { "APPL" }, // Augie (apple seller)
- { "ANNA" }, // Anna Carroway
- { "GUAR" }, // Guard
- { "ANTO" }, // Antonio Caruso
- { "TOBY" }, // Toby the Dog
- { "KING" }, // Simon Kingsley
- { "ALFR" }, // Alfred Tobacco Clerk
- { "LADY" }, // Lady Brumwell
- { "ROSA" }, // Madame Rosa
- { "LADB" }, // Lady Brumwell
- { "MOOR" }, // Joseph Moorehead
- { "BEAL" }, // Mrs. Beale
- { "LION" }, // Felix the Lion
- { "HOLL" }, // Hollingston
- { "CALL" }, // Constable Callaghan
- { "JERE" }, // Sergeant Jeremy Duncan
- { "LORD" }, // Lord Brumwell
- { "NIGE" }, // Nigel Jameson
- { "JONA" }, // Jonas (newspaper seller)
- { "DUGA" }, // Constable Dugan
- { "INSP" } // Inspector Lestrade (Scotland Yard)
-};
-
-const char *const NAMES[MAX_PEOPLE] = {
- "Sherlock Holmes",
- "Dr. Watson",
- "Inspector Lestrade",
- "Constable O'Brien",
- "Constable Lewis",
- "Sheila Parker",
- "Henry Carruthers",
- "Lesley",
- "An Usher",
- "An Usher",
- "Fredrick Epstein",
- "Mrs. Worthington",
- "The Coach",
- "A Player",
- "Tim",
- "James Sanders",
- "Belle",
- "Cleaning Girl",
- "Fredrick Epstein",
- "Wiggins",
- "Paul",
- "The Bartender",
- "A Dirty Drunk",
- "A Shouting Drunk",
- "A Staggering Drunk",
- "The Bouncer",
- "James Sanders",
- "The Coroner",
- "Reginald Snipes",
- "George Blackwood",
- "Lars",
- "Sheila Parker",
- "The Chemist",
- "Inspector Gregson",
- "Jacob Farthington",
- "Mycroft",
- "Old Sherman",
- "Richard",
- "The Barman",
- "A Dandy Player",
- "A Rough-looking Player",
- "A Spectator",
- "Robert Hunt",
- "Violet",
- "Pettigrew",
- "Augie",
- "Anna Carroway",
- "A Guard",
- "Antonio Caruso",
- "Toby the Dog",
- "Simon Kingsley",
- "Alfred",
- "Lady Brumwell",
- "Madame Rosa",
- "Lady Brumwell",
- "Joseph Moorehead",
- "Mrs. Beale",
- "Felix",
- "Hollingston",
- "Constable Callaghan",
- "Sergeant Duncan",
- "Lord Brumwell",
- "Nigel Jaimeson",
- "Jonas",
- "Constable Dugan",
- "Inspector Lestrade"
-};
-
/*----------------------------------------------------------------*/
People::People(SherlockEngine *vm) : _vm(vm), _player(_data[0]) {
@@ -217,11 +79,8 @@ People::~People() {
delete[] _portrait._sequences;
}
-/**
- * Reset the player data
- */
void People::reset() {
- // Note: The engine has theoretical support for two player charactersm but only the first one is used.
+ // Note: The engine has theoretical support for two player characters but only the first one is used.
// Watson is, instead, handled by a different sprite in each scene, with a very simple initial movement, if any
Sprite &p = _data[PLAYER];
@@ -247,9 +106,6 @@ void People::reset() {
_walkTo.clear();
}
-/**
- * Load the walking images for Sherlock
- */
bool People::loadWalk() {
if (_walkLoaded) {
return false;
@@ -262,9 +118,6 @@ bool People::loadWalk() {
}
}
-/**
- * If the walk data has been loaded, then it will be freed
- */
bool People::freeWalk() {
if (_walkLoaded) {
delete _player._images;
@@ -277,11 +130,6 @@ bool People::freeWalk() {
}
}
-/**
- * Set the variables for moving a character from one poisition to another
- * in a straight line - goAllTheWay must have been previously called to
- * check for any obstacles in the path.
- */
void People::setWalking() {
Map &map = *_vm->_map;
Scene &scene = *_vm->_scene;
@@ -427,10 +275,6 @@ void People::setWalking() {
_player._frameNumber = oldFrame;
}
-/**
- * Bring a moving character to a standing position. If the Scalpel chessboard
- * is being displayed, then the chraracter will always face down.
- */
void People::gotoStand(Sprite &sprite) {
Map &map = *_vm->_map;
_walkTo.clear();
@@ -481,9 +325,6 @@ void People::gotoStand(Sprite &sprite) {
_allowWalkAbort = true;
}
-/**
- * Walk to the co-ordinates passed, and then face the given direction
- */
void People::walkToCoords(const Common::Point &destPos, int destDir) {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
@@ -516,11 +357,6 @@ void People::walkToCoords(const Common::Point &destPos, int destDir) {
}
}
-/**
- * Called to set the character walking to the current cursor location.
- * It uses the zones and the inter-zone points to determine a series
- * of steps to walk to get to that position.
- */
void People::goAllTheWay() {
Scene &scene = *_vm->_scene;
Common::Point srcPt(_player._position.x / 100 + _player.frameWidth() / 2,
@@ -608,9 +444,6 @@ void People::goAllTheWay() {
}
}
-/**
- * Finds the scene background object corresponding to a specified speaker
- */
int People::findSpeaker(int speaker) {
Scene &scene = *_vm->_scene;
@@ -620,7 +453,7 @@ int People::findSpeaker(int speaker) {
if (obj._type == ACTIVE_BG_SHAPE) {
Common::String name(obj._name.c_str(), obj._name.c_str() + 4);
- if (scumm_stricmp(PORTRAITS[speaker], name.c_str()) == 0
+ if (name.equalsIgnoreCase(_characters[speaker]._portrait)
&& obj._name[4] >= '0' && obj._name[4] <= '9')
return idx;
}
@@ -629,9 +462,6 @@ int People::findSpeaker(int speaker) {
return -1;
}
-/**
- * Turn off any currently active portraits, and removes them from being drawn
- */
void People::clearTalking() {
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
@@ -662,9 +492,6 @@ void People::clearTalking() {
}
}
-/**
- * Setup the data for an animating speaker portrait at the top of the screen
- */
void People::setTalking(int speaker) {
Resources &res = *_vm->_res;
@@ -674,7 +501,7 @@ void People::setTalking(int speaker) {
if (_portraitsOn) {
delete _talkPics;
- Common::String filename = Common::String::format("%s.vgs", PORTRAITS[speaker]);
+ Common::String filename = Common::String::format("%s.vgs", _characters[speaker]._portrait);
_talkPics = new ImageFile(filename);
// Load portrait sequences
@@ -724,9 +551,6 @@ void People::setTalking(int speaker) {
}
}
-/**
- * Synchronize the data for a savegame
- */
void People::synchronize(Common::Serializer &s) {
s.syncAsByte(_holmesOn);
s.syncAsSint16LE(_player._position.x);
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index f98c3db867..8244fd9b59 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -30,13 +30,13 @@
namespace Sherlock {
-// People definitions
+// Player definitions. The game has theoretical support for two player characters but only the first one is used.
+// Watson is, instead, handled by a different sprite in each scene, with a very simple initial movement, if any
enum PeopleId {
PLAYER = 0,
AL = 0,
PEG = 1,
- NUM_OF_PEOPLE = 2, // Holmes and Watson
- MAX_PEOPLE = 66 // Total of all NPCs
+ MAX_PLAYERS = 2
};
// Animation sequence identifiers for characters
@@ -53,12 +53,19 @@ enum {
MAP_DOWN = 5, MAP_DOWNLEFT = 6, MAP_LEFT = 2, MAP_UPLEFT = 8
};
-extern const char *const NAMES[MAX_PEOPLE];
-extern const char PORTRAITS[MAX_PEOPLE][5];
+struct PersonData {
+ const char *_name;
+ const char *_portrait;
+ const byte *_stillSequences;
+ const byte *_talkSequences;
+
+ PersonData(const char *name, const char *portrait, const byte *stillSequences, const byte *talkSequences) :
+ _name(name), _portrait(portrait), _stillSequences(stillSequences), _talkSequences(talkSequences) {}
+};
class SherlockEngine;
-class Person: public Sprite {
+class Person : public Sprite {
public:
Person() : Sprite() {}
@@ -68,11 +75,12 @@ public:
class People {
private:
SherlockEngine *_vm;
- Person _data[NUM_OF_PEOPLE];
+ Person _data[MAX_PLAYERS];
bool _walkLoaded;
int _oldWalkSequence;
int _srcZone, _destZone;
public:
+ Common::Array<PersonData> _characters;
ImageFile *_talkPics;
Common::Point _walkDest;
Common::Point _hSavedPos;
@@ -94,35 +102,77 @@ public:
~People();
Person &operator[](PeopleId id) {
- assert(id < NUM_OF_PEOPLE);
+ assert(id < MAX_PLAYERS);
return _data[id];
}
Person &operator[](int idx) {
- assert(idx < NUM_OF_PEOPLE);
+ assert(idx < MAX_PLAYERS);
return _data[idx];
}
+ /**
+ * Returns true if Sherlock is visible on the screen and enabled
+ */
bool isHolmesActive() const { return _walkLoaded && _holmesOn; }
+ /**
+ * Reset the player data
+ */
void reset();
+ /**
+ * Load the walking images for Sherlock
+ */
bool loadWalk();
+ /**
+ * If the walk data has been loaded, then it will be freed
+ */
bool freeWalk();
+ /**
+ * Set the variables for moving a character from one poisition to another
+ * in a straight line - goAllTheWay must have been previously called to
+ * check for any obstacles in the path.
+ */
void setWalking();
+ /**
+ * Bring a moving character to a standing position. If the Scalpel chessboard
+ * is being displayed, then the chraracter will always face down.
+ */
void gotoStand(Sprite &sprite);
+ /**
+ * Walk to the co-ordinates passed, and then face the given direction
+ */
void walkToCoords(const Common::Point &destPos, int destDir);
+ /**
+ * Called to set the character walking to the current cursor location.
+ * It uses the zones and the inter-zone points to determine a series
+ * of steps to walk to get to that position.
+ */
void goAllTheWay();
+ /**
+ * Finds the scene background object corresponding to a specified speaker
+ */
int findSpeaker(int speaker);
+ /**
+ * Turn off any currently active portraits, and removes them from being drawn
+ */
void clearTalking();
+
+ /**
+ * Setup the data for an animating speaker portrait at the top of the screen
+ */
void setTalking(int speaker);
+ /**
+ * Synchronize the data for a savegame
+ */
void synchronize(Common::Serializer &s);
};
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 24fef3f235..864622e74b 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -28,21 +28,13 @@
namespace Sherlock {
-Cache::Cache(SherlockEngine *vm): _vm(vm) {
+Cache::Cache(SherlockEngine *vm) : _vm(vm) {
}
-/**
- * Returns true if a given file is currently being cached
- */
bool Cache::isCached(const Common::String &filename) const {
return _resources.contains(filename);
}
-/**
- * Loads a file into the cache if it's not already present, and returns it.
- * If the file is LZW compressed, automatically decompresses it and loads
- * the uncompressed version into memory
- */
void Cache::load(const Common::String &name) {
// First check if the entry already exists
if (_resources.contains(name))
@@ -58,9 +50,6 @@ void Cache::load(const Common::String &name) {
f.close();
}
-/**
- * Load a cache entry based on a passed stream
- */
void Cache::load(const Common::String &name, Common::SeekableReadStream &stream) {
// First check if the entry already exists
if (_resources.contains(name))
@@ -88,9 +77,6 @@ void Cache::load(const Common::String &name, Common::SeekableReadStream &stream)
}
}
-/**
- * Get a file from the cache
- */
Common::SeekableReadStream *Cache::get(const Common::String &filename) const {
// Return a memory stream that encapsulates the data
const CacheEntry &cacheEntry = _resources[filename];
@@ -99,18 +85,18 @@ Common::SeekableReadStream *Cache::get(const Common::String &filename) const {
/*----------------------------------------------------------------*/
-Resources::Resources(SherlockEngine *vm): _vm(vm), _cache(vm) {
+Resources::Resources(SherlockEngine *vm) : _vm(vm), _cache(vm) {
_resourceIndex = -1;
- addToCache("vgs.lib");
- addToCache("talk.lib");
- addToCache("journal.txt");
+ if (_vm->_interactiveFl) {
+ addToCache("vgs.lib");
+ addToCache("talk.lib");
+ addToCache("sequence.txt");
+ addToCache("journal.txt");
+ addToCache("portrait.lib");
+ }
}
-/**
- * Adds the specified file to the cache. If it's a library file, takes care of
- * loading it's index for future use
- */
void Resources::addToCache(const Common::String &filename) {
_cache.load(filename);
@@ -126,9 +112,6 @@ void Resources::addToCache(const Common::String &filename) {
delete stream;
}
-/**
- * Adds a resource from a library file to the cache
- */
void Resources::addToCache(const Common::String &filename, const Common::String &libFilename) {
// Get the resource
Common::SeekableReadStream *stream = load(filename, libFilename);
@@ -138,16 +121,10 @@ void Resources::addToCache(const Common::String &filename, const Common::String
delete stream;
}
-/**
- * Adds a given stream to the cache under the given name
- */
void Resources::addToCache(const Common::String &filename, Common::SeekableReadStream &stream) {
_cache.load(filename, stream);
}
-/**
- * Returns a stream for a given file
- */
Common::SeekableReadStream *Resources::load(const Common::String &filename) {
// First check if the file is directly in the cache
if (_cache.isCached(filename))
@@ -155,30 +132,19 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename) {
// Secondly, iterate through any loaded library file looking for a resource
// that has the same name
- LibraryIndexes::iterator i;
- for (i = _indexes.begin(); i != _indexes.end(); ++i) {
- if ((*i)._value.contains(filename)) {
+ for (LibraryIndexes::iterator i = _indexes.begin(); i != _indexes.end(); ++i) {
+ if (i->_value.contains(filename)) {
// Get a stream reference to the given library file
- Common::SeekableReadStream *stream = load((*i)._key);
- LibraryEntry &entry = (*i)._value[filename];
+ Common::SeekableReadStream *stream = load(i->_key);
+ LibraryEntry &entry = i->_value[filename];
_resourceIndex = entry._index;
stream->seek(entry._offset);
Common::SeekableReadStream *resStream = stream->readStream(entry._size);
+ decompressIfNecessary(resStream);
- // Check whether the file is compressed
- if (resStream->readUint32BE() == MKTAG('L', 'Z', 'V', 26)) {
- resStream->seek(0);
- // It's compressed, so decompress the sub-file and return it
- Common::SeekableReadStream *decompressed = decompress(*resStream);
- delete stream;
- delete resStream;
- return decompressed;
- } else {
- resStream->seek(0);
- delete stream;
- return resStream;
- }
+ delete stream;
+ return resStream;
}
}
@@ -189,13 +155,24 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename) {
Common::SeekableReadStream *stream = f.readStream(f.size());
f.close();
+ decompressIfNecessary(stream);
return stream;
}
-/**
- * Loads a specific resource from a given library file
- */
+void Resources::decompressIfNecessary(Common::SeekableReadStream *&stream) {
+ bool isCompressed = stream->readUint32BE() == MKTAG('L', 'Z', 'V', 26);
+
+ if (isCompressed) {
+ int outSize = stream->readUint32LE();
+ Common::SeekableReadStream *newStream = decompressLZ(*stream, outSize);
+ delete stream;
+ stream = newStream;
+ } else {
+ stream->seek(-4, SEEK_CUR);
+ }
+}
+
Common::SeekableReadStream *Resources::load(const Common::String &filename, const Common::String &libraryFile) {
// Open up the library for access
Common::SeekableReadStream *libStream = load(libraryFile);
@@ -208,22 +185,17 @@ Common::SeekableReadStream *Resources::load(const Common::String &filename, cons
LibraryEntry &entry = _indexes[libraryFile][filename];
libStream->seek(entry._offset);
Common::SeekableReadStream *stream = libStream->readStream(entry._size);
+ decompressIfNecessary(stream);
delete libStream;
return stream;
}
-/**
- * Returns true if the given file exists on disk or in the cache
- */
bool Resources::exists(const Common::String &filename) const {
Common::File f;
return f.exists(filename) || _cache.isCached(filename);
}
-/**
- * Reads in the index from a library file, and caches it's index for later use
- */
void Resources::loadLibraryIndex(const Common::String &libFilename,
Common::SeekableReadStream *stream, bool isNewStyle) {
uint32 offset, nextOffset;
@@ -263,15 +235,84 @@ void Resources::loadLibraryIndex(const Common::String &libFilename,
}
}
-/**
- * Returns the index of the last loaded resource in it's given library file.
- * This will be used primarily when loading talk files, so the engine can
- * update the given conversation number in the journal
- */
int Resources::resourceIndex() const {
return _resourceIndex;
}
+Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &source) {
+ // This variation can't be used by Rose Tattoo, since compressed resources include the input size,
+ // not the output size. Which means their decompression has to be done via passed buffers
+ assert(_vm->getGameID() == GType_SerratedScalpel);
+
+ uint32 id = source.readUint32BE();
+ assert(id == MKTAG('L', 'Z', 'V', 0x1A));
+
+ uint32 outputSize = source.readUint32LE();
+ return decompressLZ(source, outputSize);
+}
+
+Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &source, uint32 outSize) {
+ int inSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readUint32LE() : -1;
+ byte *outBuffer = (byte *)malloc(outSize);
+ Common::MemoryReadStream *outStream = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
+
+ decompressLZ(source, outBuffer, outSize, inSize);
+
+ return outStream;
+}
+
+void Resources::decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize) {
+ int inputSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readUint32LE() : -1;
+
+ decompressLZ(source, buffer, outSize, inputSize);
+}
+
+Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source, uint32 outSize) {
+ byte *dataOut = (byte *)malloc(outSize);
+ decompressLZ(source, dataOut, outSize, -1);
+
+ return new Common::MemoryReadStream(dataOut, outSize, DisposeAfterUse::YES);
+}
+
+void Resources::decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize) {
+ byte lzWindow[4096];
+ uint16 lzWindowPos;
+ uint16 cmd;
+
+ byte *outBufferEnd = outBuffer + outSize;
+ int endPos = source.pos() + inSize;
+
+ memset(lzWindow, 0xFF, 0xFEE);
+ lzWindowPos = 0xFEE;
+ cmd = 0;
+
+ do {
+ cmd >>= 1;
+ if (!(cmd & 0x100))
+ cmd = source.readByte() | 0xFF00;
+
+ if (cmd & 1) {
+ byte literal = source.readByte();
+ *outBuffer++ = literal;
+ lzWindow[lzWindowPos] = literal;
+ lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
+ } else {
+ int copyPos, copyLen;
+ copyPos = source.readByte();
+ copyLen = source.readByte();
+ copyPos = copyPos | ((copyLen & 0xF0) << 4);
+ copyLen = (copyLen & 0x0F) + 3;
+ while (copyLen--) {
+ byte literal = lzWindow[copyPos];
+ copyPos = (copyPos + 1) & 0x0FFF;
+ *outBuffer++ = literal;
+ lzWindow[lzWindowPos] = literal;
+ lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
+ }
+ }
+ } while ((outSize == -1 || outBuffer < outBufferEnd) || (inSize == -1 || source.pos() < endPos));
+}
+
/*----------------------------------------------------------------*/
SherlockEngine *ImageFile::_vm;
@@ -299,9 +340,6 @@ ImageFile::~ImageFile() {
(*this)[idx]._frame.free();
}
-/**
- * Load the data of the sprite
- */
void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette, bool animImages) {
loadPalette(stream);
@@ -348,9 +386,6 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette, bool
}
}
-/**
- * Gets the palette at the start of the sprite file
- */
void ImageFile::loadPalette(Common::SeekableReadStream &stream) {
// Check for palette
int v1 = stream.readUint16LE() + 1;
@@ -370,9 +405,6 @@ void ImageFile::loadPalette(Common::SeekableReadStream &stream) {
}
}
-/**
- * Decompress a single frame for the sprite
- */
void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) {
frame._frame.create(frame._width, frame._height, Graphics::PixelFormat::createFormatCLUT8());
@@ -431,90 +463,4 @@ void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) {
}
}
-/**
- * Decompress an LZW compressed resource
- */
-Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &source) {
- // This variation can't be used by Rose Tattoo, since compressed resources include the input size,
- // not the output size. Which means their decompression has to be done via passed buffers
- assert(_vm->getGameID() == GType_SerratedScalpel);
-
- uint32 id = source.readUint32BE();
- assert(id == MKTAG('L', 'Z', 'V', 0x1A));
-
- uint32 outputSize = source.readUint32LE();
- return decompressLZ(source, outputSize);
-}
-
-/**
- * Decompress an LZW compressed resource
- */
-Common::SeekableReadStream *Resources::decompress(Common::SeekableReadStream &source, uint32 outSize) {
- int inSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readUint32LE() : -1;
- byte *outBuffer = (byte *)malloc(outSize);
- Common::MemoryReadStream *outStream = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
-
- decompressLZ(source, outBuffer, outSize, inSize);
-
- return outStream;
-}
-
-/**
- * Decompress an LZW compressed resource
- */
-void Resources::decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize) {
- int inputSize = (_vm->getGameID() == GType_RoseTattoo) ? source.readUint32LE() : -1;
-
- decompressLZ(source, buffer, outSize, inputSize);
-}
-
-/**
- * Decompresses an LZW block of data with a specified output size
- */
-Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source, uint32 outSize) {
- byte *outBuffer = (byte *)malloc(outSize);
- Common::MemoryReadStream *outStream = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
-
- decompressLZ(source, outBuffer, outSize, -1);
- return outStream;
-}
-
-void Resources::decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize) {
- byte lzWindow[4096];
- uint16 lzWindowPos;
- uint16 cmd;
- byte *outBufferEnd = outBuffer + outSize;
- int32 endPos = source.pos() + inSize;
-
- memset(lzWindow, 0xFF, 0xFEE);
- lzWindowPos = 0xFEE;
- cmd = 0;
-
- do {
- cmd >>= 1;
- if (!(cmd & 0x100))
- cmd = source.readByte() | 0xFF00;
-
- if (cmd & 1) {
- byte literal = source.readByte();
- *outBuffer++ = literal;
- lzWindow[lzWindowPos] = literal;
- lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
- } else {
- int copyPos, copyLen;
- copyPos = source.readByte();
- copyLen = source.readByte();
- copyPos = copyPos | ((copyLen & 0xF0) << 4);
- copyLen = (copyLen & 0x0F) + 3;
- while (copyLen--) {
- byte literal = lzWindow[copyPos];
- copyPos = (copyPos + 1) & 0x0FFF;
- *outBuffer++ = literal;
- lzWindow[lzWindowPos] = literal;
- lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
- }
- }
- } while ((!outSize || outBuffer < outBufferEnd) && (!inSize || source.pos() < endPos));
-}
-
} // End of namespace Sherlock
diff --git a/engines/sherlock/resources.h b/engines/sherlock/resources.h
index a3208520ea..659ecf0110 100644
--- a/engines/sherlock/resources.h
+++ b/engines/sherlock/resources.h
@@ -57,11 +57,26 @@ private:
public:
Cache(SherlockEngine *_vm);
+ /**
+ * Returns true if a given file is currently being cached
+ */
bool isCached(const Common::String &filename) const;
+ /**
+ * Loads a file into the cache if it's not already present, and returns it.
+ * If the file is LZW compressed, automatically decompresses it and loads
+ * the uncompressed version into memory
+ */
void load(const Common::String &name);
+
+ /**
+ * Load a cache entry based on a passed stream
+ */
void load(const Common::String &name, Common::SeekableReadStream &stream);
+ /**
+ * Get a file from the cache
+ */
Common::SeekableReadStream *get(const Common::String &filename) const;
};
@@ -72,29 +87,82 @@ private:
LibraryIndexes _indexes;
int _resourceIndex;
- void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream,
- bool isNewStyle);
+ /**
+ * Reads in the index from a library file, and caches it's index for later use
+ */
+ void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream, bool isNewStyle);
public:
Resources(SherlockEngine *vm);
+ /**
+ * Adds the specified file to the cache. If it's a library file, takes care of
+ * loading it's index for future use
+ */
void addToCache(const Common::String &filename);
+
+ /**
+ * Adds a resource from a library file to the cache
+ */
void addToCache(const Common::String &filename, const Common::String &libFilename);
+
+ /**
+ * Adds a given stream to the cache under the given name
+ */
void addToCache(const Common::String &filename, Common::SeekableReadStream &stream);
+
bool isInCache(const Common::String &filename) const { return _cache.isCached(filename); }
+ /**
+ * Checks the passed stream, and if is compressed, deletes it and replaces it with it's uncompressed data
+ */
+ void decompressIfNecessary(Common::SeekableReadStream *&stream);
+
+ /**
+ * Returns a stream for a given file
+ */
Common::SeekableReadStream *load(const Common::String &filename);
+ /**
+ * Loads a specific resource from a given library file
+ */
Common::SeekableReadStream *load(const Common::String &filename, const Common::String &libraryFile);
+ /**
+ * Returns true if the given file exists on disk or in the cache
+ */
bool exists(const Common::String &filename) const;
+ /**
+ * Returns the index of the last loaded resource in it's given library file.
+ * This will be used primarily when loading talk files, so the engine can
+ * update the given conversation number in the journal
+ */
int resourceIndex() const;
+ /**
+ * Decompresses LZW compressed data
+ */
Common::SeekableReadStream *decompress(Common::SeekableReadStream &source);
+
+ /**
+ * Decompresses LZW compressed data
+ */
Common::SeekableReadStream *decompress(Common::SeekableReadStream &source, uint32 outSize);
+
+ /**
+ * Decompresses LZW compressed data
+ */
void decompress(Common::SeekableReadStream &source, byte *buffer, uint32 outSize);
- static void decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize);
+
+ /**
+ * Decompresses LZW compressed data
+ */
static Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, uint32 outSize);
+
+ /**
+ * Decompresses LZW compressed data
+ */
+ static void decompressLZ(Common::SeekableReadStream &source, byte *outBuffer, int32 outSize, int32 inSize);
};
struct ImageFrame {
@@ -105,16 +173,25 @@ struct ImageFrame {
Common::Point _offset;
byte _rleMarker;
Graphics::Surface _frame;
-
- operator Graphics::Surface &() { return _frame; }
};
class ImageFile : public Common::Array<ImageFrame> {
private:
static SherlockEngine *_vm;
+ /**
+ * Load the data of the sprite
+ */
void load(Common::SeekableReadStream &stream, bool skipPalette, bool animImages);
+
+ /**
+ * Gets the palette at the start of the sprite file
+ */
void loadPalette(Common::SeekableReadStream &stream);
+
+ /**
+ * Decompress a single frame for the sprite
+ */
void decompressFrame(ImageFrame &frame, const byte *src);
public:
byte _palette[256 * 3];
diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp
index b9ac3e79d6..ddf4917a34 100644
--- a/engines/sherlock/saveload.cpp
+++ b/engines/sherlock/saveload.cpp
@@ -38,6 +38,10 @@ const int ENV_POINTS[6][3] = {
{ 241, 280, 261 } // Quit
};
+static const char *const EMPTY_SAVEGAME_SLOT = "-EMPTY-";
+static const char *const SAVEGAME_STR = "SHLK";
+#define SAVEGAME_STR_SIZE 4
+
/*----------------------------------------------------------------*/
SaveManager::SaveManager(SherlockEngine *vm, const Common::String &target) :
@@ -55,9 +59,6 @@ SaveManager::~SaveManager() {
}
}
-/**
- * Shows the in-game dialog interface for loading and saving games
- */
void SaveManager::drawInterface() {
Screen &screen = *_vm->_screen;
UserInterface &ui = *_vm->_ui;
@@ -87,18 +88,17 @@ void SaveManager::drawInterface() {
if (!_savegameIndex)
screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), COMMAND_NULL, 0, "Up");
- if (_savegameIndex == MAX_SAVEGAME_SLOTS - 5)
+ if (_savegameIndex == MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT)
screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), COMMAND_NULL, 0, "Down");
- for (int idx = _savegameIndex; idx < _savegameIndex + 5; ++idx)
- {
+ for (int idx = _savegameIndex; idx < _savegameIndex + ONSCREEN_FILES_COUNT; ++idx) {
screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10),
INV_FOREGROUND, "%d.", idx + 1);
screen.gPrint(Common::Point(24, CONTROLS_Y + 11 + (idx - _savegameIndex) * 10),
INV_FOREGROUND, "%s", _savegames[idx].c_str());
}
- if (!ui._windowStyle) {
+ if (!ui._slideWindows) {
screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
} else {
ui.summonWindow();
@@ -107,15 +107,12 @@ void SaveManager::drawInterface() {
_envMode = SAVEMODE_NONE;
}
-/**
- * Build up a savegame list, with empty slots given an explicit Empty message
- */
void SaveManager::createSavegameList() {
Screen &screen = *_vm->_screen;
_savegames.clear();
for (int idx = 0; idx < MAX_SAVEGAME_SLOTS; ++idx)
- _savegames.push_back("-EMPTY-");
+ _savegames.push_back(EMPTY_SAVEGAME_SLOT);
SaveStateList saveList = getSavegameList(_target);
for (uint idx = 0; idx < saveList.size(); ++idx) {
@@ -137,9 +134,6 @@ void SaveManager::createSavegameList() {
}
}
-/**
- * Load a list of savegames
- */
SaveStateList SaveManager::getSavegameList(const Common::String &target) {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray filenames;
@@ -172,12 +166,6 @@ SaveStateList SaveManager::getSavegameList(const Common::String &target) {
return saveList;
}
-const char *const SAVEGAME_STR = "SHLK";
-#define SAVEGAME_STR_SIZE 4
-
-/**
- * Read in the header information for a savegame
- */
bool SaveManager::readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header) {
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
header._thumbnail = nullptr;
@@ -212,9 +200,6 @@ bool SaveManager::readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHea
return true;
}
-/**
- * Write out the header information for a savegame
- */
void SaveManager::writeSavegameHeader(Common::OutSaveFile *out, SherlockSavegameHeader &header) {
// Write out a savegame header
out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1);
@@ -245,9 +230,6 @@ void SaveManager::writeSavegameHeader(Common::OutSaveFile *out, SherlockSavegame
out->writeUint32LE(_vm->_events->getFrameCounter());
}
-/**
- * Creates a thumbnail for the current on-screen contents
- */
void SaveManager::createThumbnail() {
if (_saveThumb) {
_saveThumb->free();
@@ -260,9 +242,6 @@ void SaveManager::createThumbnail() {
::createThumbnail(_saveThumb, (const byte *)_vm->_screen->getPixels(), SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT, thumbPalette);
}
-/**
- * Return the index of the button the mouse is over, if any
- */
int SaveManager::getHighlightedButton() const {
Common::Point pt = _vm->_events->mousePos();
@@ -275,21 +254,18 @@ int SaveManager::getHighlightedButton() const {
return -1;
}
-/**
- * Handle highlighting buttons
- */
void SaveManager::highlightButtons(int btnIndex) {
Screen &screen = *_vm->_screen;
byte color = (btnIndex == 0) ? COMMAND_HIGHLIGHTED : COMMAND_FOREGROUND;
screen.buttonPrint(Common::Point(ENV_POINTS[0][2], CONTROLS_Y), color, 1, "Exit");
- if ((btnIndex == 1) || ((_envMode == 1) && (btnIndex != 2)))
+ if ((btnIndex == 1) || ((_envMode == SAVEMODE_LOAD) && (btnIndex != 2)))
screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Load");
else
screen.buttonPrint(Common::Point(ENV_POINTS[1][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Load");
- if ((btnIndex == 2) || ((_envMode == 2) && (btnIndex != 1)))
+ if ((btnIndex == 2) || ((_envMode == SAVEMODE_SAVE) && (btnIndex != 1)))
screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_HIGHLIGHTED, true, "Save");
else
screen.buttonPrint(Common::Point(ENV_POINTS[2][2], CONTROLS_Y), COMMAND_FOREGROUND, true, "Save");
@@ -309,9 +285,6 @@ void SaveManager::highlightButtons(int btnIndex) {
screen.buttonPrint(Common::Point(ENV_POINTS[5][2], CONTROLS_Y), color, 1, "Quit");
}
-/**
- * Load the game in the specified slot
- */
void SaveManager::loadGame(int slot) {
Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(
generateSaveName(slot));
@@ -335,9 +308,6 @@ void SaveManager::loadGame(int slot) {
delete saveFile;
}
-/**
- * Save the game in the specified slot with the given name
- */
void SaveManager::saveGame(int slot, const Common::String &name) {
Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving(
generateSaveName(slot));
@@ -354,17 +324,10 @@ void SaveManager::saveGame(int slot, const Common::String &name) {
delete out;
}
-/**
- * Support method that generates a savegame name
- * @param slot Slot number
- */
Common::String SaveManager::generateSaveName(int slot) {
return Common::String::format("%s.%03d", _target.c_str(), slot);
}
-/**
- * Synchronize the data for a savegame
- */
void SaveManager::synchronize(Common::Serializer &s) {
Inventory &inv = *_vm->_inventory;
Journal &journal = *_vm->_journal;
@@ -391,14 +354,11 @@ void SaveManager::synchronize(Common::Serializer &s) {
_justLoaded = true;
}
-/**
- * Make sure that the selected savegame is on-screen
- */
bool SaveManager::checkGameOnScreen(int slot) {
Screen &screen = *_vm->_screen;
// Check if it's already on-screen
- if (slot != -1 && (slot < _savegameIndex || slot >= (_savegameIndex + 5))) {
+ if (slot != -1 && (slot < _savegameIndex || slot >= (_savegameIndex + ONSCREEN_FILES_COUNT))) {
_savegameIndex = slot;
screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
@@ -425,7 +385,7 @@ bool SaveManager::checkGameOnScreen(int slot) {
return false;
}
-bool SaveManager::getFilename(int slot) {
+bool SaveManager::promptForDescription(int slot) {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
@@ -441,7 +401,7 @@ bool SaveManager::getFilename(int slot) {
screen.buttonPrint(Common::Point(ENV_POINTS[5][2], CONTROLS_Y), COMMAND_NULL, true, "Quit");
Common::String saveName = _savegames[slot];
- if (scumm_stricmp(saveName.c_str(), "-EMPTY-") == 0) {
+ if (isSlotEmpty(slot)) {
// It's an empty slot, so start off with an empty save name
saveName = "";
@@ -485,18 +445,16 @@ bool SaveManager::getFilename(int slot) {
xp -= screen.charWidth(saveName.lastChar());
screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_FOREGROUND);
saveName.deleteLastChar();
- }
-
- if (keyState.keycode == Common::KEYCODE_RETURN)
+
+ } else if (keyState.keycode == Common::KEYCODE_RETURN && saveName.compareToIgnoreCase(EMPTY_SAVEGAME_SLOT)) {
done = 1;
- if (keyState.keycode == Common::KEYCODE_ESCAPE) {
+ } else if (keyState.keycode == Common::KEYCODE_ESCAPE) {
screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND);
done = -1;
- }
-
- if (keyState.keycode >= ' ' && keyState.keycode <= 'z' && saveName.size() < 50
- && (xp + screen.charWidth(keyState.keycode)) < 308) {
+
+ } else if (keyState.ascii >= ' ' && keyState.ascii <= 'z' && saveName.size() < 50
+ && (xp + screen.charWidth(keyState.ascii)) < 308) {
char c = (char)keyState.ascii;
screen.vgaBar(Common::Rect(xp, yp - 1, xp + 8, yp + 9), INV_BACKGROUND);
@@ -519,4 +477,8 @@ bool SaveManager::getFilename(int slot) {
return done == 1;
}
+bool SaveManager::isSlotEmpty(int slot) const {
+ return _savegames[slot].equalsIgnoreCase(EMPTY_SAVEGAME_SLOT);
+}
+
} // End of namespace Sherlock
diff --git a/engines/sherlock/saveload.h b/engines/sherlock/saveload.h
index c9a7286c6b..a7ed852a5f 100644
--- a/engines/sherlock/saveload.h
+++ b/engines/sherlock/saveload.h
@@ -33,6 +33,7 @@
namespace Sherlock {
#define MAX_SAVEGAME_SLOTS 99
+#define ONSCREEN_FILES_COUNT 5
#define SHERLOCK_SAVEGAME_VERSION 1
enum SaveMode { SAVEMODE_NONE = 0, SAVEMODE_LOAD = 1, SAVEMODE_SAVE = 2 };
@@ -56,8 +57,14 @@ private:
Common::String _target;
Graphics::Surface *_saveThumb;
+ /**
+ * Build up a savegame list, with empty slots given an explicit Empty message
+ */
void createSavegameList();
+ /**
+ * Synchronize the data for a savegame
+ */
void synchronize(Common::Serializer &s);
public:
Common::StringArray _savegames;
@@ -68,28 +75,71 @@ public:
SaveManager(SherlockEngine *vm, const Common::String &target);
~SaveManager();
+ /**
+ * Shows the in-game dialog interface for loading and saving games
+ */
void drawInterface();
+ /**
+ * Creates a thumbnail for the current on-screen contents
+ */
void createThumbnail();
+ /**
+ * Load a list of savegames
+ */
static SaveStateList getSavegameList(const Common::String &target);
+ /**
+ * Support method that generates a savegame name
+ * @param slot Slot number
+ */
Common::String generateSaveName(int slot);
+ /**
+ * Write out the header information for a savegame
+ */
void writeSavegameHeader(Common::OutSaveFile *out, SherlockSavegameHeader &header);
+ /**
+ * Read in the header information for a savegame
+ */
static bool readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header);
+ /**
+ * Return the index of the button the mouse is over, if any
+ */
int getHighlightedButton() const;
+ /**
+ * Handle highlighting buttons
+ */
void highlightButtons(int btnIndex);
+ /**
+ * Load the game in the specified slot
+ */
void loadGame(int slot);
+
+ /**
+ * Save the game in the specified slot with the given name
+ */
void saveGame(int slot, const Common::String &name);
+ /**
+ * Make sure that the selected savegame is on-screen
+ */
bool checkGameOnScreen(int slot);
- bool getFilename(int slot);
+ /**
+ * Prompts the user to enter a description in a given slot
+ */
+ bool promptForDescription(int slot);
+
+ /**
+ * Returns true if the given save slot is empty
+ */
+ bool isSlotEmpty(int slot) const;
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/darts.cpp b/engines/sherlock/scalpel/darts.cpp
index 6da8d6848e..b567d58ab4 100644
--- a/engines/sherlock/scalpel/darts.cpp
+++ b/engines/sherlock/scalpel/darts.cpp
@@ -44,9 +44,10 @@ enum {
DART_COL_FORE = 5,
PLAYER_COLOR = 11
};
+#define OPPONENTS_COUNT 4
-const char *const OPPONENT_NAMES[5] = {
- "Skipper", "Willy", "Micky", "Tom", "Bartender"
+const char *const OPPONENT_NAMES[OPPONENTS_COUNT] = {
+ "Skipper", "Willy", "Micky", "Tom"
};
/*----------------------------------------------------------------*/
@@ -63,9 +64,6 @@ Darts::Darts(ScalpelEngine *vm) : _vm(vm) {
_oldDartButtons = false;
}
-/**
- * Main method for playing darts game
- */
void Darts::playDarts() {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -118,7 +116,7 @@ void Darts::playDarts() {
if (playerNumber == 0) {
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), PLAYER_COLOR, "Holmes Wins!");
- if (_level < 4)
+ if (_level < OPPONENTS_COUNT)
setFlagsForDarts(318 + _level);
} else {
screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 30), PLAYER_COLOR, "%s Wins!", _opponent.c_str());
@@ -181,9 +179,6 @@ void Darts::playDarts() {
screen.setFont(oldFont);
}
-/**
- * Load the graphics needed for the dart game
- */
void Darts::loadDarts() {
Screen &screen = *_vm->_screen;
@@ -194,9 +189,6 @@ void Darts::loadDarts() {
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
-/**
- * Initializes the variables needed for the dart game
- */
void Darts::initDarts() {
_dartScore1 = _dartScore2 = 301;
_roundNumber = 1;
@@ -210,7 +202,7 @@ void Darts::initDarts() {
_computerPlayer = 2;
} else {
// Check flags for opponents
- for (int idx = 0; idx < 4; ++idx) {
+ for (int idx = 0; idx < OPPONENTS_COUNT; ++idx) {
if (_vm->readFlags(314 + idx))
_level = idx;
}
@@ -219,17 +211,11 @@ void Darts::initDarts() {
_opponent = OPPONENT_NAMES[_level];
}
-/**
- * Frees the images used by the dart game
- */
void Darts::closeDarts() {
delete _dartImages;
_dartImages = nullptr;
}
-/**
- * Show the names of the people playing, Holmes and his opponent
- */
void Darts::showNames(int playerNum) {
Screen &screen = *_vm->_screen;
byte color = playerNum == 0 ? PLAYER_COLOR : DART_COL_FORE;
@@ -249,10 +235,10 @@ void Darts::showNames(int playerNum) {
if (playerNum != 0)
screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y), PLAYER_COLOR + 3,
- _opponent.c_str());
+ "%s", _opponent.c_str());
else
screen.print(Common::Point(STATUS_INFO_X + 50, STATUS_INFO_Y), color,
- _opponent.c_str());
+ "%s", _opponent.c_str());
screen._backBuffer1.fillRect(Common::Rect(STATUS_INFO_X + 50, STATUS_INFO_Y + 10,
STATUS_INFO_X + 81, STATUS_INFO_Y + 12), color);
@@ -262,9 +248,6 @@ void Darts::showNames(int playerNum) {
screen._backBuffer2.blitFrom(screen._backBuffer1);
}
-/**
- * Show the player score and game status
- */
void Darts::showStatus(int playerNum) {
Screen &screen = *_vm->_screen;
byte color;
@@ -283,12 +266,6 @@ void Darts::showStatus(int playerNum) {
screen.slamRect(Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, SHERLOCK_SCREEN_WIDTH, STATUS_INFO_Y + 48));
}
-/**
- * Throws a single dart.
- * @param dartNum Dart number
- * @param computer 0 = Player, 1 = 1st player computer, 2 = 2nd player computer
- * @returns Score for what dart hit
- */
int Darts::throwDart(int dartNum, int computer) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -347,9 +324,6 @@ int Darts::throwDart(int dartNum, int computer) {
return dartScore(dartPos);
}
-/**
- * Draw a dart moving towards the board
- */
void Darts::drawDartThrow(const Common::Point &pt) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -358,7 +332,7 @@ void Darts::drawDartThrow(const Common::Point &pt) {
int delta = 9;
for (int idx = 4; idx < 23; ++idx) {
- Graphics::Surface &frame = (*_dartImages)[idx]._frame;
+ ImageFrame &frame = (*_dartImages)[idx];
// Adjust draw position for animating dart
if (idx < 13)
@@ -369,15 +343,15 @@ void Darts::drawDartThrow(const Common::Point &pt) {
pos.y += delta++;
// Draw the dart
- Common::Point drawPos(pos.x - frame.w / 2, pos.y - frame.h);
+ Common::Point drawPos(pos.x - frame._width / 2, pos.y - frame._height);
screen._backBuffer1.transBlitFrom(frame, drawPos);
- screen.slamArea(drawPos.x, drawPos.y, frame.w, frame.h);
+ screen.slamArea(drawPos.x, drawPos.y, frame._width, frame._height);
- // Handle erasing old dart strs
+ // Handle erasing old dart frame area
if (!oldDrawBounds.isEmpty())
screen.slamRect(oldDrawBounds);
- oldDrawBounds = Common::Rect(drawPos.x, drawPos.y, drawPos.x + frame.w, drawPos.y + frame.h);
+ oldDrawBounds = Common::Rect(drawPos.x, drawPos.y, drawPos.x + frame._width, drawPos.y + frame._height);
screen._backBuffer1.blitFrom(screen._backBuffer2, drawPos, oldDrawBounds);
events.wait(2);
@@ -389,9 +363,6 @@ void Darts::drawDartThrow(const Common::Point &pt) {
screen.slamRect(oldDrawBounds);
}
-/**
- * Erases the power bars
- */
void Darts::erasePowerBars() {
Screen &screen = *_vm->_screen;
@@ -403,11 +374,6 @@ void Darts::erasePowerBars() {
screen.slamArea(DARTBARVX - 1, DARTHEIGHTY - 1, 11, DARTBARSIZE + 3);
}
-/**
- * Show a gradually incrementing incrementing power that bar. If goToPower is provided, it will
- * increment to that power level ignoring all keyboard input (ie. for computer throws).
- * Otherwise, it will increment until either a key/mouse button is pressed, or it reaches the end
- */
int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, bool isVertical) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -447,20 +413,15 @@ int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, bool i
if (sound._musicOn) {
if (!(idx % 3))
sound.waitTimerRoland(1);
- } else {
- if (!(idx % 8))
- events.wait(1);
- }
-
+ } else if (!(idx % 8))
+ events.wait(1);
+
++idx;
} while (!done);
return MIN(idx * 100 / DARTBARSIZE, 100);
}
-/**
- * Returns true if a mouse button or key is pressed.
- */
bool Darts::dartHit() {
Events &events = *_vm->_events;
@@ -480,9 +441,6 @@ bool Darts::dartHit() {
return (events._pressed && !_oldDartButtons) ? 1 : 0;
}
-/**
- * Return the score of the given location on the dart-board
- */
int Darts::dartScore(const Common::Point &pt) {
Common::Point pos(pt.x - 37, pt.y - 33);
Graphics::Surface &scoreImg = (*_dartImages)[1]._frame;
@@ -496,10 +454,6 @@ int Darts::dartScore(const Common::Point &pt) {
return score;
}
-/**
- * Calculates where a computer player is trying to throw their dart, and choose the actual
- * point that was hit with some margin of error
- */
Common::Point Darts::getComputerDartDest(int playerNum) {
Common::Point target;
int score = playerNum == 0 ? _dartScore1 : _dartScore2;
@@ -555,9 +509,6 @@ Common::Point Darts::getComputerDartDest(int playerNum) {
return target;
}
-/**
- * Returns the center position for the area of the dartboard with a given number
- */
bool Darts::findNumberOnBoard(int aim, Common::Point &pt) {
ImageFrame &board = (*_dartImages)[1];
@@ -597,10 +548,6 @@ bool Darts::findNumberOnBoard(int aim, Common::Point &pt) {
return done;
}
-/**
- * Set a global flag to 0 or 1 depending on whether the passed flag is negative or positive.
- * @remarks We don't use the global setFlags method because we don't want to check scene flags
- */
void Darts::setFlagsForDarts(int flagNum) {
_vm->_flags[ABS(flagNum)] = flagNum >= 0;
}
diff --git a/engines/sherlock/scalpel/darts.h b/engines/sherlock/scalpel/darts.h
index a9624442e2..42990f8056 100644
--- a/engines/sherlock/scalpel/darts.h
+++ b/engines/sherlock/scalpel/darts.h
@@ -44,30 +44,88 @@ private:
int _roundScore;
bool _oldDartButtons;
+ /**
+ * Load the graphics needed for the dart game
+ */
void loadDarts();
+
+ /**
+ * Initializes the variables needed for the dart game
+ */
void initDarts();
+
+ /**
+ * Frees the images used by the dart game
+ */
void closeDarts();
+ /**
+ * Show the names of the people playing, Holmes and his opponent
+ */
void showNames(int playerNum);
+
+ /**
+ * Show the player score and game status
+ */
void showStatus(int playerNum);
+ /**
+ * Throws a single dart.
+ * @param dartNum Dart number
+ * @param computer 0 = Player, 1 = 1st player computer, 2 = 2nd player computer
+ * @returns Score for what dart hit
+ */
int throwDart(int dartNum, int computer);
+
+ /**
+ * Draw a dart moving towards the board
+ */
void drawDartThrow(const Common::Point &pt);
+ /**
+ * Erases the power bars
+ */
void erasePowerBars();
+
+ /**
+ * Show a gradually incrementing incrementing power that bar. If goToPower is provided, it will
+ * increment to that power level ignoring all keyboard input (ie. for computer throws).
+ * Otherwise, it will increment until either a key/mouse button is pressed, or it reaches the end
+ */
int doPowerBar(const Common::Point &pt, byte color, int goToPower, bool isVertical);
+ /**
+ * Returns true if a mouse button or key is pressed.
+ */
bool dartHit();
+
+ /**
+ * Return the score of the given location on the dart-board
+ */
int dartScore(const Common::Point &pt);
+ /**
+ * Calculates where a computer player is trying to throw their dart, and choose the actual
+ * point that was hit with some margin of error
+ */
Common::Point getComputerDartDest(int playerNum);
+ /**
+ * Returns the center position for the area of the dartboard with a given number
+ */
bool findNumberOnBoard(int aim, Common::Point &pt);
+ /**
+ * Set a global flag to 0 or 1 depending on whether the passed flag is negative or positive.
+ * @remarks We don't use the global setFlags method because we don't want to check scene flags
+ */
void setFlagsForDarts(int flagNum);
public:
Darts(ScalpelEngine *vm);
+ /**
+ * Main method for playing darts game
+ */
void playDarts();
};
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index eff589874d..ccc9c8abca 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -64,24 +64,25 @@ static const int TITLE_FRAMES[7][9] = {
};
#define NUM_PLACES 100
-const int MAP_X[NUM_PLACES] = {
+
+static const int MAP_X[NUM_PLACES] = {
0, 368, 0, 219, 0, 282, 0, 43, 0, 0, 396, 408, 0, 0, 0, 568, 37, 325,
28, 0, 263, 36, 148, 469, 342, 143, 443, 229, 298, 0, 157, 260, 432,
174, 0, 351, 0, 528, 0, 136, 0, 0, 0, 555, 165, 0, 506, 0, 0, 344, 0, 0
};
-const int MAP_Y[NUM_PLACES] = {
+static const int MAP_Y[NUM_PLACES] = {
0, 147, 0, 166, 0, 109, 0, 61, 0, 0, 264, 70, 0, 0, 0, 266, 341, 30, 275,
0, 294, 146, 311, 230, 184, 268, 133, 94, 207, 0, 142, 142, 330, 255, 0,
37, 0, 70, 0, 116, 0, 0, 0, 50, 21, 0, 303, 0, 0, 229, 0, 0
};
-const int MAP_TRANSLATE[NUM_PLACES] = {
+static const int MAP_TRANSLATE[NUM_PLACES] = {
0, 0, 0, 1, 0, 2, 0, 3, 4, 0, 4, 6, 0, 0, 0, 8, 9, 10, 11, 0, 12, 13, 14, 7,
15, 16, 17, 18, 19, 0, 20, 21, 22, 23, 0, 24, 0, 25, 0, 26, 0, 0, 0, 27,
28, 0, 29, 0, 0, 30, 0
};
-const byte MAP_SEQUENCES[3][MAX_FRAME] = {
+static const byte MAP_SEQUENCES[3][MAX_FRAME] = {
{ 1, 1, 2, 3, 4, 0 }, // Overview Still
{ 5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0 },
{ 5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0 }
@@ -89,7 +90,145 @@ const byte MAP_SEQUENCES[3][MAX_FRAME] = {
#define MAX_PEOPLE 66
-const byte STILL_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = {
+const char PEOPLE_PORTRAITS[MAX_PEOPLE][5] = {
+ { "HOLM" }, // Sherlock Holmes
+ { "WATS" }, // Dr. Watson
+ { "LEST" }, // Inspector Lestrade
+ { "CON1" }, // Constable O'Brien
+ { "CON2" }, // Constable Lewis
+ { "SHEI" }, // Sheila Parker
+ { "HENR" }, // Henry Carruthers
+ { "LESL" }, // Lesley (flower girl)
+ { "USH1" }, // Usher #1
+ { "USH2" }, // Usher #2
+ { "FRED" }, // Fredrick Epstein
+ { "WORT" }, // Mrs. Worthington
+ { "COAC" }, // Coach
+ { "PLAY" }, // Player
+ { "WBOY" }, // Tim (Waterboy)
+ { "JAME" }, // James Sanders
+ { "BELL" }, // Belle (perfumerie)
+ { "GIRL" }, // Cleaning Girl (perfumerie)
+ { "EPST" }, // Epstien in the Opera Balcony
+ { "WIGG" }, // Wiggins
+ { "PAUL" }, // Paul (Brumwell / Carroway)
+ { "BART" }, // Bartender
+ { "DIRT" }, // Dirty Drunk
+ { "SHOU" }, // Shouting Drunk
+ { "STAG" }, // Staggering Drunk
+ { "BOUN" }, // Bouncer
+ { "SAND" }, // James Sanders - At Home
+ { "CORO" }, // The Coroner
+ { "EQUE" }, // The Equestrian Shop Keeper
+ { "GEOR" }, // George Blackwood
+ { "LARS" }, // Lars
+ { "PARK" }, // Sheila Parker (happy)
+ { "CHEM" }, // Chemist
+ { "GREG" }, // Inspector Gregson
+ { "LAWY" }, // Jacob Farthington Lawyer
+ { "MYCR" }, // Mycroft
+ { "SHER" }, // Old Sherman
+ { "CHMB" }, // Richard Chemist Stock boy
+ { "BARM" }, // Barman
+ { "DAND" }, // Dandy Player
+ { "ROUG" }, // Rough-looking Player
+ { "SPEC" }, // Spectator
+ { "HUNT" }, // Robert Hunt
+ { "VIOL" }, // Violet Secretary
+ { "PETT" }, // Pettigrew
+ { "APPL" }, // Augie (apple seller)
+ { "ANNA" }, // Anna Carroway
+ { "GUAR" }, // Guard
+ { "ANTO" }, // Antonio Caruso
+ { "TOBY" }, // Toby the Dog
+ { "KING" }, // Simon Kingsley
+ { "ALFR" }, // Alfred Tobacco Clerk
+ { "LADY" }, // Lady Brumwell
+ { "ROSA" }, // Madame Rosa
+ { "LADB" }, // Lady Brumwell
+ { "MOOR" }, // Joseph Moorehead
+ { "BEAL" }, // Mrs. Beale
+ { "LION" }, // Felix the Lion
+ { "HOLL" }, // Hollingston
+ { "CALL" }, // Constable Callaghan
+ { "JERE" }, // Sergeant Jeremy Duncan
+ { "LORD" }, // Lord Brumwell
+ { "NIGE" }, // Nigel Jameson
+ { "JONA" }, // Jonas (newspaper seller)
+ { "DUGA" }, // Constable Dugan
+ { "INSP" } // Inspector Lestrade (Scotland Yard)
+};
+
+const char *const PEOPLE_NAMES[MAX_PEOPLE] = {
+ "Sherlock Holmes",
+ "Dr. Watson",
+ "Inspector Lestrade",
+ "Constable O'Brien",
+ "Constable Lewis",
+ "Sheila Parker",
+ "Henry Carruthers",
+ "Lesley",
+ "An Usher",
+ "An Usher",
+ "Fredrick Epstein",
+ "Mrs. Worthington",
+ "The Coach",
+ "A Player",
+ "Tim",
+ "James Sanders",
+ "Belle",
+ "Cleaning Girl",
+ "Fredrick Epstein",
+ "Wiggins",
+ "Paul",
+ "The Bartender",
+ "A Dirty Drunk",
+ "A Shouting Drunk",
+ "A Staggering Drunk",
+ "The Bouncer",
+ "James Sanders",
+ "The Coroner",
+ "Reginald Snipes",
+ "George Blackwood",
+ "Lars",
+ "Sheila Parker",
+ "The Chemist",
+ "Inspector Gregson",
+ "Jacob Farthington",
+ "Mycroft",
+ "Old Sherman",
+ "Richard",
+ "The Barman",
+ "A Dandy Player",
+ "A Rough-looking Player",
+ "A Spectator",
+ "Robert Hunt",
+ "Violet",
+ "Pettigrew",
+ "Augie",
+ "Anna Carroway",
+ "A Guard",
+ "Antonio Caruso",
+ "Toby the Dog",
+ "Simon Kingsley",
+ "Alfred",
+ "Lady Brumwell",
+ "Madame Rosa",
+ "Lady Brumwell",
+ "Joseph Moorehead",
+ "Mrs. Beale",
+ "Felix",
+ "Hollingston",
+ "Constable Callaghan",
+ "Sergeant Duncan",
+ "Lord Brumwell",
+ "Nigel Jaimeson",
+ "Jonas",
+ "Constable Dugan",
+ "Inspector Lestrade"
+};
+
+static const byte PEOPLE_STILL_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = {
{ 1, 0, 0 }, // Sherlock Holmes
{ 6, 0, 0 }, // Dr. Watson
{ 4, 0, 0 }, // Inspector Lestrade
@@ -158,7 +297,7 @@ const byte STILL_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = {
{ 4, 0, 0 } // Inspector Lestrade (Yard)
};
-byte TALK_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = {
+static const byte PEOPLE_TALK_SEQUENCES[MAX_PEOPLE][MAX_TALK_SEQUENCES] = {
{ 1, 0, 0 }, // Sherlock Holmes
{ 5, 5, 6, 7, 8, 7, 8, 6, 0, 0 }, // Dr. Watson
{ 2, 0, 0 }, // Inspector Lestrade
@@ -239,9 +378,6 @@ ScalpelEngine::~ScalpelEngine() {
delete _darts;
}
-/**
- * Game initialization
- */
void ScalpelEngine::initialize() {
initGraphics(320, 200, false);
@@ -261,15 +397,20 @@ void ScalpelEngine::initialize() {
_res->addToCache("snd.snd");
_res->addToCache("title.snd");
- // Load the map co-ordinates for each scene and sequence data
- _map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
- _map->loadSequences(3, &MAP_SEQUENCES[0][0]);
+ if (!isDemo()) {
+ // Load the map co-ordinates for each scene and sequence data
+ _map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
+ _map->loadSequences(3, &MAP_SEQUENCES[0][0]);
+ _map->_oldCharPoint = BAKER_ST_EXTERIOR;
+ }
// Load the inventory
loadInventory();
- // Set up constants used by the talk system
- _talk->setSequences(&TALK_SEQUENCES[0][0], &STILL_SEQUENCES[0][0], MAX_PEOPLE);
+ // Set up list of people
+ for (int idx = 0; idx < MAX_PEOPLE; ++idx)
+ _people->_characters.push_back(PersonData(PEOPLE_NAMES[idx], PEOPLE_PORTRAITS[idx],
+ PEOPLE_STILL_SEQUENCES[idx], PEOPLE_TALK_SEQUENCES[idx]));
_animation->setPrologueNames(&PROLOGUE_NAMES[0], PROLOGUE_NAMES_COUNT);
_animation->setPrologueFrames(&PROLOGUE_FRAMES[0][0], 6, 9);
@@ -278,17 +419,14 @@ void ScalpelEngine::initialize() {
_animation->setTitleFrames(&TITLE_FRAMES[0][0], 7, 9);
// Starting scene
- if (getIsDemo())
+ if (isDemo() && _interactiveFl)
_scene->_goToScene = 3;
else
_scene->_goToScene = 4;
}
-/**
- * Show the opening sequence
- */
void ScalpelEngine::showOpening() {
- if (getIsDemo())
+ if (isDemo() && _interactiveFl)
return;
if (!showCityCutscene())
@@ -304,21 +442,18 @@ void ScalpelEngine::showOpening() {
_sound->stopMusic();
}
-/**
- * Show the starting city cutscene which shows the game title
- */
bool ScalpelEngine::showCityCutscene() {
byte palette[PALETTE_SIZE];
_sound->playMusic("prolog1.mus");
- _titleOverride = "title.lib";
- _soundOverride = "title.snd";
+ _animation->_gfxLibraryFilename = "title.lib";
+ _animation->_soundLibraryFilename = "title.snd";
bool finished = _animation->play("26open1", 1, 255, true, 2);
if (finished) {
ImageFile titleImages("title2.vgs", true);
- _screen->_backBuffer1.copyFrom(*_screen);
- _screen->_backBuffer2.copyFrom(*_screen);
+ _screen->_backBuffer1.blitFrom(*_screen);
+ _screen->_backBuffer2.blitFrom(*_screen);
// London, England
_screen->_backBuffer1.transBlitFrom(titleImages[0], Common::Point(10, 11));
@@ -342,8 +477,8 @@ bool ScalpelEngine::showCityCutscene() {
if (finished) {
ImageFile titleImages("title.vgs", true);
- _screen->_backBuffer1.copyFrom(*_screen);
- _screen->_backBuffer2.copyFrom(*_screen);
+ _screen->_backBuffer1.blitFrom(*_screen);
+ _screen->_backBuffer2.blitFrom(*_screen);
// The Lost Files of
_screen->_backBuffer1.transBlitFrom(titleImages[0], Common::Point(75, 6));
@@ -374,20 +509,17 @@ bool ScalpelEngine::showCityCutscene() {
}
}
- _titleOverride = "";
- _soundOverride = "";
+ _animation->_gfxLibraryFilename = "";
+ _animation->_soundLibraryFilename = "";
return finished;
}
-/**
- * Show the back alley where the initial murder takes place
- */
bool ScalpelEngine::showAlleyCutscene() {
byte palette[PALETTE_SIZE];
_sound->playMusic("prolog2.mus");
- _titleOverride = "TITLE.LIB";
- _soundOverride = "TITLE.SND";
+ _animation->_gfxLibraryFilename = "TITLE.LIB";
+ _animation->_soundLibraryFilename = "TITLE.SND";
bool finished = _animation->play("27PRO1", 1, 3, true, 2);
if (finished)
@@ -401,12 +533,12 @@ bool ScalpelEngine::showAlleyCutscene() {
if (finished)
finished = _animation->play("27PRO3", 1, 0, true, 2);
- if(finished) {
+ if (finished) {
_screen->getPalette(palette);
_screen->fadeToBlack(2);
}
- if(finished) {
+ if (finished) {
ImageFile titleImages("title3.vgs", true);
// "Early the following morning on Baker Street..."
_screen->_backBuffer1.transBlitFrom(titleImages[0], Common::Point(35, 51), false, 0);
@@ -414,17 +546,14 @@ bool ScalpelEngine::showAlleyCutscene() {
finished = _events->delay(1000);
}
- _titleOverride = "";
- _soundOverride = "";
+ _animation->_gfxLibraryFilename = "";
+ _animation->_soundLibraryFilename = "";
return finished;
}
-/**
- * Show the Baker Street outside cutscene
- */
bool ScalpelEngine::showStreetCutscene() {
- _titleOverride = "TITLE.LIB";
- _soundOverride = "TITLE.SND";
+ _animation->_gfxLibraryFilename = "TITLE.LIB";
+ _animation->_soundLibraryFilename = "TITLE.SND";
_sound->playMusic("PROLOG3.MUS");
@@ -433,14 +562,12 @@ bool ScalpelEngine::showStreetCutscene() {
if (finished)
finished = _animation->play("14NOTE", 1, 0, false, 2);
- _titleOverride = "";
- _soundOverride = "";
+ _animation->_gfxLibraryFilename = "";
+ _animation->_soundLibraryFilename = "";
return finished;
}
-/**
- * Show the game credits
- */
+
bool ScalpelEngine::scrollCredits() {
// Load the images for displaying credit text
Common::SeekableReadStream *stream = _res->load("credits.vgs", "title.lib");
@@ -463,9 +590,9 @@ bool ScalpelEngine::scrollCredits() {
_screen->transBlitFrom(creditsImages[1], Common::Point(10, 400 - idx), false, 0);
// Don't show credit text on the top and bottom ten rows of the screen
- _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, _screen->w, 10));
- _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, _screen->h - 10),
- Common::Rect(0, _screen->h - 10, _screen->w, _screen->h));
+ _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, _screen->w(), 10));
+ _screen->blitFrom(_screen->_backBuffer1, Common::Point(0, _screen->h() - 10),
+ Common::Rect(0, _screen->h() - 10, _screen->w(), _screen->h()));
_events->delay(100);
}
@@ -473,13 +600,10 @@ bool ScalpelEngine::scrollCredits() {
return true;
}
-/**
- * Show Holmes and Watson at the breakfast table, lestrade's note, and then the scrolling credits
- */
bool ScalpelEngine::showOfficeCutscene() {
_sound->playMusic("PROLOG4.MUS");
- _titleOverride = "TITLE2.LIB";
- _soundOverride = "TITLE.SND";
+ _animation->_gfxLibraryFilename = "TITLE2.LIB";
+ _animation->_soundLibraryFilename = "TITLE.SND";
bool finished = _animation->play("COFF1", 1, 3, true, 3);
if (finished)
@@ -498,8 +622,10 @@ bool ScalpelEngine::showOfficeCutscene() {
} else
finished = _events->delay(19000);
- _events->clearEvents();
- finished = _events->delay(500);
+ if (finished) {
+ _events->clearEvents();
+ finished = _events->delay(500);
+ }
}
if (finished)
@@ -514,16 +640,11 @@ bool ScalpelEngine::showOfficeCutscene() {
if (finished)
_screen->fadeToBlack(3);
- _titleOverride = "";
- _soundOverride = "";
+ _animation->_gfxLibraryFilename = "";
+ _animation->_soundLibraryFilename = "";
return finished;
}
-/**
- * Load the default inventory for the game, which includes both the initial active inventory,
- * as well as special pending inventory items which can appear automatically in the player's
- * inventory once given required flags are set
- */
void ScalpelEngine::loadInventory() {
Inventory &inv = *_inventory;
@@ -545,24 +666,18 @@ void ScalpelEngine::loadInventory() {
inv.push_back(InventoryItem(586, "Pawn ticket", "A pawn ticket", "_ITEM16A"));
}
-/**
- * Transition to show an image
- */
void ScalpelEngine::showLBV(const Common::String &filename) {
Common::SeekableReadStream *stream = _res->load(filename, "title.lib");
ImageFile images(*stream);
delete stream;
_screen->setPalette(images._palette);
- _screen->_backBuffer1.blitFrom(images[0]._frame);
+ _screen->_backBuffer1.blitFrom(images[0]);
_screen->verticalTransition();
}
-/**
- * Starting a scene within the game
- */
void ScalpelEngine::startScene() {
- if (_scene->_goToScene == 100 || _scene->_goToScene == 98) {
+ if (_scene->_goToScene == OVERHEAD_MAP || _scene->_goToScene == OVERHEAD_MAP2) {
// Show the map
if (_sound->_musicOn) {
if (_sound->loadSong(100)) {
@@ -585,17 +700,17 @@ void ScalpelEngine::startScene() {
// 55: Fade out and exit
// 70: Brumwell suicide
switch (_scene->_goToScene) {
- case 2:
- case 52:
- case 53:
- case 70:
+ case BLACKWOOD_CAPTURE:
+ case RESCUE_ANNA:
+ case MOOREHEAD_DEATH:
+ case BRUMWELL_SUICIDE:
if (_sound->_musicOn && _sound->loadSong(_scene->_goToScene)) {
if (_sound->_music)
_sound->startSong();
}
switch (_scene->_goToScene) {
- case 2:
+ case BLACKWOOD_CAPTURE:
// Blackwood's capture
_res->addToCache("final2.vda", "epilogue.lib");
_res->addToCache("final2.vdx", "epilogue.lib");
@@ -603,7 +718,7 @@ void ScalpelEngine::startScene() {
_animation->play("final2", 1, 0, false, 4);
break;
- case 52:
+ case RESCUE_ANNA:
// Rescuing Anna
_res->addToCache("finalr2.vda", "epilogue.lib");
_res->addToCache("finalr2.vdx", "epilogue.lib");
@@ -638,7 +753,7 @@ void ScalpelEngine::startScene() {
_useEpilogue2 = false;
break;
- case 53:
+ case MOOREHEAD_DEATH:
// Moorehead's death / subway train
_res->addToCache("SUBWAY2.vda", "epilogue.lib");
_res->addToCache("SUBWAY2.vdx", "epilogue.lib");
@@ -654,7 +769,7 @@ void ScalpelEngine::startScene() {
_screen->_fadeStyle = false;
break;
- case 70:
+ case BRUMWELL_SUICIDE:
// Brumwell suicide
_animation->play("suicid", 1, 3, true, 4);
break;
@@ -663,31 +778,31 @@ void ScalpelEngine::startScene() {
}
// Except for the Moorehead Murder scene, fade to black first
- if (_scene->_goToScene != 53) {
+ if (_scene->_goToScene != MOOREHEAD_DEATH) {
_events->wait(40);
_screen->fadeToBlack(3);
}
switch (_scene->_goToScene) {
case 52:
- _scene->_goToScene = 27; // Go to the Lawyer's Office
+ _scene->_goToScene = LAWYER_OFFICE; // Go to the Lawyer's Office
_map->_bigPos = Common::Point(0, 0); // Overland scroll position
_map->_overPos = Common::Point(22900 - 600, 9400 + 900); // Overland position
- _map->_oldCharPoint = 27;
+ _map->_oldCharPoint = LAWYER_OFFICE;
break;
case 53:
- _scene->_goToScene = 17; // Go to St. Pancras Station
+ _scene->_goToScene = STATION; // Go to St. Pancras Station
_map->_bigPos = Common::Point(0, 0); // Overland scroll position
_map->_overPos = Common::Point(32500 - 600, 3000 + 900); // Overland position
- _map->_oldCharPoint = 17;
+ _map->_oldCharPoint = STATION;
break;
default:
- _scene->_goToScene = 4; // Back to Baker st.
+ _scene->_goToScene = BAKER_STREET; // Back to Baker st.
_map->_bigPos = Common::Point(0, 0); // Overland scroll position
_map->_overPos = Common::Point(14500 - 600, 8400 + 900); // Overland position
- _map->_oldCharPoint = 4;
+ _map->_oldCharPoint = BAKER_STREET;
break;
}
@@ -695,7 +810,7 @@ void ScalpelEngine::startScene() {
_sound->freeSong();
break;
- case 55:
+ case EXIT_GAME:
// Exit game
_screen->fadeToBlack(3);
quitGame();
@@ -711,15 +826,12 @@ void ScalpelEngine::startScene() {
if (_scene->_goToScene == 99) {
// Darts Board minigame
_darts->playDarts();
- _mapResult = _scene->_goToScene = 19; // Go back to the bar
+ _mapResult = _scene->_goToScene = PUB_INTERIOR;
}
_mapResult = _scene->_goToScene;
}
-/**
- * Takes care of clearing the mirror in scene 12, in case anything drew over it
- */
void ScalpelEngine::eraseMirror12() {
Common::Point pt((*_people)[AL]._position.x / 100, (*_people)[AL]._position.y / 100);
@@ -730,9 +842,6 @@ void ScalpelEngine::eraseMirror12() {
}
}
-/**
- * Takes care of drawing Holme's reflection onto the mirror in scene 12
- */
void ScalpelEngine::doMirror12() {
People &people = *_people;
Common::Point pt((*_people)[AL]._position.x / 100, (*_people)[AL]._position.y / 100);
@@ -806,9 +915,6 @@ void ScalpelEngine::doMirror12() {
}
}
-/**
- * This clears the mirror in scene 12 in case anything messed draw over it
- */
void ScalpelEngine::flushMirror12() {
Common::Point pt((*_people)[AL]._position.x / 100, (*_people)[AL]._position.y / 100);
diff --git a/engines/sherlock/scalpel/scalpel.h b/engines/sherlock/scalpel/scalpel.h
index 40e4937b5d..8743bfb7a9 100644
--- a/engines/sherlock/scalpel/scalpel.h
+++ b/engines/sherlock/scalpel/scalpel.h
@@ -30,32 +30,83 @@ namespace Sherlock {
namespace Scalpel {
+enum { BLACKWOOD_CAPTURE = 2, BAKER_STREET = 4, DRAWING_ROOM = 12, STATION = 17, PUB_INTERIOR = 19,
+ LAWYER_OFFICE = 27, BAKER_ST_EXTERIOR = 39, RESCUE_ANNA = 52, MOOREHEAD_DEATH = 53, EXIT_GAME = 55,
+ BRUMWELL_SUICIDE = 70, OVERHEAD_MAP2 = 98, DARTS_GAME = 99, OVERHEAD_MAP = 100 };
+
class ScalpelEngine : public SherlockEngine {
private:
Darts *_darts;
int _mapResult;
+ /**
+ * Show the starting city cutscene which shows the game title
+ */
bool showCityCutscene();
+
+ /**
+ * Show the back alley where the initial murder takes place
+ */
bool showAlleyCutscene();
+
+ /**
+ * Show the Baker Street outside cutscene
+ */
bool showStreetCutscene();
+
+ /**
+ * Show Holmes and Watson at the breakfast table, lestrade's note, and then the scrolling credits
+ */
bool showOfficeCutscene();
+
+ /**
+ * Show the game credits
+ */
bool scrollCredits();
+ /**
+ * Load the default inventory for the game, which includes both the initial active inventory,
+ * as well as special pending inventory items which can appear automatically in the player's
+ * inventory once given required flags are set
+ */
void loadInventory();
+ /**
+ * Transition to show an image
+ */
void showLBV(const Common::String &filename);
protected:
+ /**
+ * Game initialization
+ */
virtual void initialize();
+ /**
+ * Show the opening sequence
+ */
virtual void showOpening();
+ /**
+ * Starting a scene within the game
+ */
virtual void startScene();
public:
ScalpelEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
virtual ~ScalpelEngine();
+ /**
+ * Takes care of clearing the mirror in scene 12 (mansion drawing room), in case anything drew over it
+ */
void eraseMirror12();
+
+ /**
+ * Takes care of drawing Holme's reflection onto the mirror in scene 12 (mansion drawing room)
+ */
void doMirror12();
+
+ /**
+ * This clears the mirror in scene 12 (mansion drawing room) in case anything messed draw over it
+ */
void flushMirror12();
};
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 96cfac0683..2c80bfbd39 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -27,6 +27,13 @@
namespace Sherlock {
+static const int FS_TRANS[8] = {
+ STOP_UP, STOP_UPRIGHT, STOP_RIGHT, STOP_DOWNRIGHT, STOP_DOWN,
+ STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT
+};
+
+/*----------------------------------------------------------------*/
+
BgFileHeader::BgFileHeader() {
_numStructs = -1;
_numImages = -1;
@@ -44,7 +51,7 @@ BgFileHeader::BgFileHeader() {
Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0);
}
-void BgFileHeader::synchronize(Common::SeekableReadStream &s, bool isRoseTattoo) {
+void BgFileHeader::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
_numStructs = s.readUint16LE();
_numImages = s.readUint16LE();
_numcAnimations = s.readUint16LE();
@@ -63,10 +70,7 @@ void BgFileHeader::synchronize(Common::SeekableReadStream &s, bool isRoseTattoo)
/*----------------------------------------------------------------*/
-/**
- * Load the data for the object
- */
-void BgfileheaderInfo::load(Common::SeekableReadStream &s) {
+void BgFileHeaderInfo::load(Common::SeekableReadStream &s) {
_filesize = s.readUint32LE();
_maxFrames = s.readByte();
@@ -77,9 +81,6 @@ void BgfileheaderInfo::load(Common::SeekableReadStream &s) {
/*----------------------------------------------------------------*/
-/**
- * Load the data for the object
- */
void Exit::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
if (isRoseTattoo) {
char buffer[41];
@@ -108,9 +109,6 @@ void Exit::load(Common::SeekableReadStream &s, bool isRoseTattoo) {
/*----------------------------------------------------------------*/
-/**
- * Load the data for the object
- */
void SceneEntry::load(Common::SeekableReadStream &s) {
_startPosition.x = s.readSint16LE();
_startPosition.y = s.readSint16LE();
@@ -118,9 +116,6 @@ void SceneEntry::load(Common::SeekableReadStream &s) {
_allow = s.readByte();
}
-/**
- * Load the data for the object
- */
void SceneSound::load(Common::SeekableReadStream &s) {
char buffer[9];
s.read(buffer, 8);
@@ -132,9 +127,6 @@ void SceneSound::load(Common::SeekableReadStream &s) {
/*----------------------------------------------------------------*/
-/**
- * Retuurn the index of the passed object in the array
- */
int ObjectArray::indexOf(const Object &obj) const {
for (uint idx = 0; idx < size(); ++idx) {
if (&(*this)[idx] == &obj)
@@ -146,9 +138,6 @@ int ObjectArray::indexOf(const Object &obj) const {
/*----------------------------------------------------------------*/
-/**
- * Load the data for the object
- */
void ScaleZone::load(Common::SeekableReadStream &s) {
left = s.readSint16LE();
top = s.readSint16LE();
@@ -167,16 +156,12 @@ Scene::Scene(SherlockEngine *vm): _vm(vm) {
_currentScene = -1;
_goToScene = -1;
_loadingSavedGame = false;
- _changes = false;
- _keyboardInput = 0;
_walkedInScene = false;
_version = 0;
_lzwMode = false;
_invGraphicItems = 0;
_cAnimFramePause = 0;
_restoreFlag = false;
- _invLookFlag = false;
- _lookHelp = false;
_animating = 0;
_doBgAnimDone = true;
_tempFadeStyle = 0;
@@ -187,9 +172,6 @@ Scene::~Scene() {
freeScene();
}
-/**
- * Handles loading the scene specified by _goToScene
- */
void Scene::selectScene() {
Events &events = *_vm->_events;
People &people = *_vm->_people;
@@ -200,9 +182,6 @@ void Scene::selectScene() {
// Reset fields
ui._windowOpen = ui._infoFlag = false;
ui._menuMode = STD_MODE;
- _keyboardInput = 0;
- _oldKey = _help = _oldHelp = 0;
- _oldTemp = _temp = 0;
// Free any previous scene
freeScene();
@@ -215,7 +194,7 @@ void Scene::selectScene() {
loadScene(sceneFile);
- // If the fade style was changed from running amovie, then reset it
+ // If the fade style was changed from running a movie, then reset it
if (_tempFadeStyle) {
screen._fadeStyle = _tempFadeStyle;
_tempFadeStyle = 0;
@@ -227,15 +206,12 @@ void Scene::selectScene() {
_restoreFlag = true;
events.clearEvents();
- // If there were any scripst waiting to be run, but were interrupt by a running
+ // If there were any scripts waiting to be run, but were interrupt by a running
// canimation (probably the last scene's exit canim), clear the _scriptMoreFlag
if (talk._scriptMoreFlag == 3)
talk._scriptMoreFlag = 0;
}
-/**
- * Fres all the graphics and other dynamically allocated data for the scene
- */
void Scene::freeScene() {
if (_currentScene == -1)
return;
@@ -265,15 +241,6 @@ void Scene::freeScene() {
_currentScene = -1;
}
-/**
- * Loads the data associated for a given scene. The .BGD file's format is:
- * BGHEADER: Holds an index for the rest of the file
- * STRUCTS: The objects for the scene
- * IMAGES: The graphic information for the structures
- *
- * The _misc field of the structures contains the number of the graphic image
- * that it should point to after loading; _misc is then set to 0.
- */
bool Scene::loadScene(const Common::String &filename) {
Events &events = *_vm->_events;
Map &map = *_vm->_map;
@@ -284,7 +251,6 @@ bool Scene::loadScene(const Common::String &filename) {
Sound &sound = *_vm->_sound;
UserInterface &ui = *_vm->_ui;
bool flag;
- Common::Array<BgfileheaderInfo> bgInfo;
_walkedInScene = false;
@@ -319,7 +285,7 @@ bool Scene::loadScene(const Common::String &filename) {
rrmStream->seek(rrmStream->readUint32LE());
BgFileHeader bgHeader;
- bgHeader.synchronize(*rrmStream, IS_ROSE_TATTOO);
+ bgHeader.load(*rrmStream, IS_ROSE_TATTOO);
_invGraphicItems = bgHeader._numImages + 1;
if (IS_ROSE_TATTOO) {
@@ -338,6 +304,7 @@ bool Scene::loadScene(const Common::String &filename) {
}
// Read in the shapes header info
+ Common::Array<BgFileHeaderInfo> bgInfo;
bgInfo.resize(bgHeader._numStructs);
for (uint idx = 0; idx < bgInfo.size(); ++idx)
@@ -364,30 +331,51 @@ bool Scene::loadScene(const Common::String &filename) {
if (_lzwMode)
delete infoStream;
+ } else if (!_lzwMode) {
+ _bgShapes.resize(bgHeader._numStructs);
+ for (int idx = 0; idx < bgHeader._numStructs; ++idx)
+ _bgShapes[idx].load(*rrmStream, false);
+
+ if (bgHeader._descSize) {
+ _descText.resize(bgHeader._descSize);
+ rrmStream->read(&_descText[0], bgHeader._descSize);
+ }
+
+ if (bgHeader._seqSize) {
+ _sequenceBuffer.resize(bgHeader._seqSize);
+ rrmStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
+ }
} else {
- // Load shapes
- Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream : res.decompress(*rrmStream, bgHeader._numStructs * 625);
+ Common::SeekableReadStream *infoStream;
+
+ // Read shapes
+ infoStream = Resources::decompressLZ(*rrmStream, bgHeader._numStructs * 569);
_bgShapes.resize(bgHeader._numStructs);
for (int idx = 0; idx < bgHeader._numStructs; ++idx)
- _bgShapes[idx].load(*infoStream, true);
+ _bgShapes[idx].load(*infoStream, false);
+
+ delete infoStream;
+
+ // Read description texts
+ if (bgHeader._descSize) {
+ infoStream = Resources::decompressLZ(*rrmStream, bgHeader._descSize);
+
+ _descText.resize(bgHeader._descSize);
+ infoStream->read(&_descText[0], bgHeader._descSize);
- if (_lzwMode)
delete infoStream;
+ }
- // Load description text
- _descText.resize(bgHeader._descSize);
- if (_lzwMode)
- res.decompress(*rrmStream, (byte *)&_descText[0], bgHeader._descSize);
- else
- rrmStream->read(&_descText[0], bgHeader._descSize);
+ // Read sequences
+ if (bgHeader._seqSize) {
+ infoStream = Resources::decompressLZ(*rrmStream, bgHeader._seqSize);
- // Load sequences
- _sequenceBuffer.resize(bgHeader._seqSize);
- if (_lzwMode)
- res.decompress(*rrmStream, &_sequenceBuffer[0], bgHeader._seqSize);
- else
- rrmStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
+ _sequenceBuffer.resize(bgHeader._seqSize);
+ infoStream->read(&_sequenceBuffer[0], bgHeader._seqSize);
+
+ delete infoStream;
+ }
}
// Set up the list of images used by the scene
@@ -545,7 +533,6 @@ bool Scene::loadScene(const Common::String &filename) {
// Clear user interface area and draw controls
ui.drawInterface();
- _changes = false;
checkSceneStatus();
if (!saves._justLoaded) {
@@ -556,13 +543,13 @@ bool Scene::loadScene(const Common::String &filename) {
// Check for TURNON objects
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- if (_bgShapes[idx]._type == HIDDEN && (_bgShapes[idx]._flags & 0x20))
+ if (_bgShapes[idx]._type == HIDDEN && (_bgShapes[idx]._flags & TURNON_OBJ))
_bgShapes[idx].toggleHidden();
}
// Check for TURNOFF objects
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- if (_bgShapes[idx]._type != HIDDEN && (_bgShapes[idx]._flags & 0x40) &&
+ if (_bgShapes[idx]._type != HIDDEN && (_bgShapes[idx]._flags & TURNOFF_OBJ) &&
_bgShapes[idx]._type != INVALID)
_bgShapes[idx].toggleHidden();
if (_bgShapes[idx]._type == HIDE_SHAPE)
@@ -590,7 +577,7 @@ bool Scene::loadScene(const Common::String &filename) {
_walkedInScene = false;
saves._justLoaded = false;
- if (!_vm->getIsDemo()) {
+ if (!_vm->isDemo()) {
// Reset the previous map location and position on overhead map
map._oldCharPoint = _currentScene;
map._overPos.x = map[_currentScene].x * 100 - 600;
@@ -601,9 +588,6 @@ bool Scene::loadScene(const Common::String &filename) {
return flag;
}
-/**
- * Load all the sound effects specified for the current scene
- */
void Scene::loadSceneSounds() {
Sound &sound = *_vm->_sound;
@@ -611,10 +595,6 @@ void Scene::loadSceneSounds() {
sound.loadSound(_sounds[idx]._name, _sounds[idx]._priority);
}
-/**
- * Set objects to their current persistent state. This includes things such as
- * opening or moving them
- */
void Scene::checkSceneStatus() {
if (_sceneStats[_currentScene][64]) {
for (uint idx = 0; idx < 64; ++idx) {
@@ -640,10 +620,6 @@ void Scene::checkSceneStatus() {
}
}
-/**
- * Restores objects to the correct status. This ensures that things like being opened or moved
- * will remain the same on future visits to the scene
- */
void Scene::saveSceneStatus() {
// Flag any objects for the scene that have been altered
int count = MIN((int)_bgShapes.size(), 64);
@@ -657,11 +633,6 @@ void Scene::saveSceneStatus() {
_sceneStats[_currentScene][64] = true;
}
-/**
- * Check the scene's objects against the game flags. If false is passed,
- * it means the scene has just been loaded. A value of true means that the scene
- * is in use (ie. not just loaded)
- */
void Scene::checkSceneFlags(bool flag) {
SpriteType mode = flag ? HIDE_SHAPE : HIDDEN;
@@ -714,16 +685,10 @@ void Scene::checkSceneFlags(bool flag) {
}
}
-/**
- * Checks scene objects against the player's inventory items. If there are any
- * matching names, it means the given item has already been picked up, and should
- * be hidden in the scene.
- */
void Scene::checkInventory() {
for (uint shapeIdx = 0; shapeIdx < _bgShapes.size(); ++shapeIdx) {
for (int invIdx = 0; invIdx < _vm->_inventory->_holdings; ++invIdx) {
- if (scumm_stricmp(_bgShapes[shapeIdx]._name.c_str(),
- (*_vm->_inventory)[invIdx]._name.c_str()) == 0) {
+ if (_bgShapes[shapeIdx]._name.equalsIgnoreCase((*_vm->_inventory)[invIdx]._name)) {
_bgShapes[shapeIdx]._type = INVALID;
break;
}
@@ -731,10 +696,6 @@ void Scene::checkInventory() {
}
}
-/**
- * Set up any entrance co-ordinates or entrance canimations, and then transition
- * in the scene
- */
void Scene::transitionToScene() {
People &people = *_vm->_people;
SaveManager &saves = *_vm->_saves;
@@ -743,11 +704,6 @@ void Scene::transitionToScene() {
Common::Point &hSavedPos = people._hSavedPos;
int &hSavedFacing = people._hSavedFacing;
- const int FS_TRANS[8] = {
- STOP_UP, STOP_UPRIGHT, STOP_RIGHT, STOP_DOWNRIGHT, STOP_DOWN,
- STOP_DOWNLEFT, STOP_LEFT, STOP_UPLEFT
- };
-
if (hSavedPos.x < 1) {
// No exit information from last scene-check entrance info
if (_entrance._startPosition.x < 1) {
@@ -812,14 +768,14 @@ void Scene::transitionToScene() {
// player is clear of the box
switch (obj._aType) {
case FLAG_SET:
- for (int useNum = 0; useNum < 4; ++useNum) {
+ for (int useNum = 0; useNum < USE_COUNT; ++useNum) {
if (obj._use[useNum]._useFlag) {
if (!_vm->readFlags(obj._use[useNum]._useFlag))
_vm->setFlags(obj._use[useNum]._useFlag);
}
if (!talk._talkToAbort) {
- for (int nameIdx = 0; nameIdx < 4; ++nameIdx) {
+ for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
toggleObject(obj._use[useNum]._names[nameIdx]);
}
}
@@ -854,15 +810,11 @@ void Scene::transitionToScene() {
}
}
-/**
- * Scans through the object list to find one with a matching name, and will
- * call toggleHidden with all matches found. Returns the numer of matches found
- */
int Scene::toggleObject(const Common::String &name) {
int count = 0;
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
- if (scumm_stricmp(name.c_str(), _bgShapes[idx]._name.c_str()) == 0) {
+ if (name.equalsIgnoreCase(_bgShapes[idx]._name)) {
++count;
_bgShapes[idx].toggleHidden();
}
@@ -871,10 +823,6 @@ int Scene::toggleObject(const Common::String &name) {
return count;
}
-/**
- * Update the screen back buffer with all of the scene objects which need
- * to be drawn
- */
void Scene::updateBackground() {
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
@@ -894,27 +842,27 @@ void Scene::updateBackground() {
// Draw all active shapes which are behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == BEHIND)
- screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
+ screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all canimations which are behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == BEHIND)
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame,
- _canimShapes[idx]._position, _canimShapes[idx]._flags & 2);
+ _canimShapes[idx]._position, _canimShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all active shapes which are normal and behind the person
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == NORMAL_BEHIND)
- screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
+ screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all canimations which are normal and behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
if (_canimShapes[idx]._type == ACTIVE_BG_SHAPE && _canimShapes[idx]._misc == NORMAL_BEHIND)
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
- _canimShapes[idx]._flags & 2);
+ _canimShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw the player if he's active
@@ -931,7 +879,8 @@ void Scene::updateBackground() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
_bgShapes[idx]._misc == NORMAL_FORWARD)
- screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
+ screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
+ _bgShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all static and active canimations that are NORMAL and are in front of the player
@@ -939,7 +888,7 @@ void Scene::updateBackground() {
if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) &&
_canimShapes[idx]._misc == NORMAL_FORWARD)
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
- _canimShapes[idx]._flags & 2);
+ _canimShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all static and active shapes that are FORWARD
@@ -950,7 +899,8 @@ void Scene::updateBackground() {
if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
_bgShapes[idx]._misc == FORWARD)
- screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & 2);
+ screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
+ _bgShapes[idx]._flags & OBJ_FLIPPED);
}
// Draw all static and active canimations that are forward
@@ -958,15 +908,12 @@ void Scene::updateBackground() {
if ((_canimShapes[idx]._type == ACTIVE_BG_SHAPE || _canimShapes[idx]._type == STATIC_BG_SHAPE) &&
_canimShapes[idx]._misc == FORWARD)
screen._backBuffer->transBlitFrom(*_canimShapes[idx]._imageFrame, _canimShapes[idx]._position,
- _canimShapes[idx]._flags & 2);
+ _canimShapes[idx]._flags & OBJ_FLIPPED);
}
screen.resetDisplayBounds();
}
-/**
- * Check whether the passed area intersects with one of the scene's exits
- */
Exit *Scene::checkForExit(const Common::Rect &r) {
for (uint idx = 0; idx < _exits.size(); ++idx) {
if (_exits[idx].intersects(r))
@@ -976,11 +923,6 @@ Exit *Scene::checkForExit(const Common::Rect &r) {
return nullptr;
}
-/**
- * Checks all the background shapes. If a background shape is animating,
- * it will flag it as needing to be drawn. If a non-animating shape is
- * colliding with another shape, it will also flag it as needing drawing
- */
void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) {
// Iterate through the shapes
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
@@ -989,9 +931,9 @@ void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) {
if ((obj._flags & 5) == 1) {
obj._misc = (pt.y < (obj._position.y + obj.frameHeight() - 1)) ?
NORMAL_FORWARD : NORMAL_BEHIND;
- } else if (!(obj._flags & 1)) {
+ } else if (!(obj._flags & OBJ_BEHIND)) {
obj._misc = BEHIND;
- } else if (obj._flags & 4) {
+ } else if (obj._flags & OBJ_FORWARD) {
obj._misc = FORWARD;
}
}
@@ -1015,14 +957,6 @@ void Scene::checkBgShapes(ImageFrame *frame, const Common::Point &pt) {
}
}
-/**
- * Attempt to start a canimation sequence. It will load the requisite graphics, and
- * then copy the canim object into the _canimShapes array to start the animation.
- *
- * @param cAnimNum The canim object within the current scene
- * @param playRate Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
- * A negative playRate can also be specified to play the animation in reverse
- */
int Scene::startCAnim(int cAnimNum, int playRate) {
Events &events = *_vm->_events;
Map &map = *_vm->_map;
@@ -1070,7 +1004,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
if (talk._talkToAbort)
return 1;
- // Add new anim shape entry for displaying the animationo
+ // Add new anim shape entry for displaying the animation
_canimShapes.push_back(Object());
Object &cObj = _canimShapes[_canimShapes.size() - 1];
@@ -1235,9 +1169,6 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
return 1;
}
-/**
- * Animate all objects and people.
- */
void Scene::doBgAnim() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -1333,7 +1264,7 @@ void Scene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
- if (o._type == NO_SHAPE && ((o._flags & 1) == 0)) {
+ if (o._type == NO_SHAPE && ((o._flags & OBJ_BEHIND) == 0)) {
// Restore screen area
screen._backBuffer->blitFrom(screen._backBuffer2, o._position,
Common::Rect(o._position.x, o._position.y,
@@ -1384,14 +1315,14 @@ void Scene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Draw all canimations which are behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
}
@@ -1399,14 +1330,14 @@ void Scene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Draw all canimations which are NORMAL and behind the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
}
@@ -1427,14 +1358,14 @@ void Scene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Draw all static and active canimations that are NORMAL and are in front of the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
}
@@ -1442,27 +1373,27 @@ void Scene::doBgAnim() {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Draw any active portrait
if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
screen._backBuffer->transBlitFrom(*people._portrait._imageFrame,
- people._portrait._position, people._portrait._flags & 2);
+ people._portrait._position, people._portrait._flags & OBJ_FLIPPED);
// Draw all static and active canimations that are in front of the person
for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
Object &o = _canimShapes[idx];
if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) {
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
}
// Draw all NO_SHAPE shapes which have flag bit 0 clear
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
- if (o._type == NO_SHAPE && (o._flags & 1) == 0)
- screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & 2);
+ if (o._type == NO_SHAPE && (o._flags & OBJ_BEHIND) == 0)
+ screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
}
// Bring the newly built picture to the screen
@@ -1470,7 +1401,7 @@ void Scene::doBgAnim() {
_animating = 0;
screen.slamRect(Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCENE_HEIGHT));
} else {
- if (people[AL]._type != INVALID && ((_goToScene == -1 || _canimShapes.size() == 0))) {
+ if (people[AL]._type != INVALID && ((_goToScene == -1 || _canimShapes.empty()))) {
if (people[AL]._type == REMOVE) {
screen.slamRect(Common::Rect(
people[AL]._oldPosition.x, people[AL]._oldPosition.y,
@@ -1517,7 +1448,7 @@ void Scene::doBgAnim() {
if (_goToScene == -1) {
for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
Object &o = _bgShapes[idx];
- if (o._type == NO_SHAPE && (o._flags & 1) == 0) {
+ if (o._type == NO_SHAPE && (o._flags & OBJ_BEHIND) == 0) {
screen.slamArea(o._position.x, o._position.y, o._oldSize.x, o._oldSize.y);
screen.slamArea(o._oldPosition.x, o._oldPosition.y, o._oldSize.x, o._oldSize.y);
} else if (o._type == HIDE_SHAPE) {
@@ -1565,10 +1496,6 @@ void Scene::doBgAnim() {
}
}
-/**
- * Attempts to find a background shape within the passed bounds. If found,
- * it will return the shape number, or -1 on failure.
- */
int Scene::findBgShape(const Common::Rect &r) {
if (!_doBgAnimDone)
// New frame hasn't been drawn yet
@@ -1589,10 +1516,6 @@ int Scene::findBgShape(const Common::Rect &r) {
return -1;
}
-/**
- * Checks to see if the given position in the scene belongs to a given zone type.
- * If it is, the zone is activated and used just like a TAKL zone or aFLAG_SET zone.
- */
int Scene::checkForZones(const Common::Point &pt, int zoneType) {
int matches = 0;
@@ -1612,9 +1535,6 @@ int Scene::checkForZones(const Common::Point &pt, int zoneType) {
return matches;
}
-/**
- * Check which zone the the given position is located in.
- */
int Scene::whichZone(const Common::Point &pt) {
for (uint idx = 0; idx < _zones.size(); ++idx) {
if (_zones[idx].contains(pt))
@@ -1624,9 +1544,6 @@ int Scene::whichZone(const Common::Point &pt) {
return -1;
}
-/**
- * Returns the index of the closest zone to a given point.
- */
int Scene::closestZone(const Common::Point &pt) {
int dist = 1000;
int zone = -1;
@@ -1646,9 +1563,6 @@ int Scene::closestZone(const Common::Point &pt) {
return zone;
}
-/**
- * Synchronize the data for a savegame
- */
void Scene::synchronize(Common::Serializer &s) {
if (s.isSaving())
saveSceneStatus();
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 9454a4e20b..0cbd775c56 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -57,14 +57,21 @@ struct BgFileHeader {
BgFileHeader();
- void synchronize(Common::SeekableReadStream &s, bool isRoseTattoo);
+
+ /**
+ * Load the data for the object
+ */
+ void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
-struct BgfileheaderInfo {
+struct BgFileHeaderInfo {
int _filesize; // How long images are
int _maxFrames; // How many unique frames in object
Common::String _filename; // Filename of object
+ /**
+ * Load the data for the object
+ */
void load(Common::SeekableReadStream &s);
};
@@ -78,6 +85,9 @@ public:
Common::String _dest;
int _image; // Arrow image to use
+ /**
+ * Load the data for the object
+ */
void load(Common::SeekableReadStream &s, bool isRoseTattoo);
};
@@ -86,6 +96,9 @@ struct SceneEntry {
int _startDir;
int _allow;
+ /**
+ * Load the data for the object
+ */
void load(Common::SeekableReadStream &s);
};
@@ -93,11 +106,17 @@ struct SceneSound {
Common::String _name;
int _priority;
+ /**
+ * Load the data for the object
+ */
void load(Common::SeekableReadStream &s);
};
-class ObjectArray: public Common::Array<Object> {
+class ObjectArray : public Common::Array<Object> {
public:
+ /**
+ * Retuurn the index of the passed object in the array
+ */
int indexOf(const Object &obj) const;
};
@@ -113,33 +132,61 @@ class Scene {
private:
SherlockEngine *_vm;
Common::String _rrmName;
- int _selector;
- bool _lookHelp;
bool _loadingSavedGame;
+ /**
+ * Loads the data associated for a given scene. The .BGD file's format is:
+ * BGHEADER: Holds an index for the rest of the file
+ * STRUCTS: The objects for the scene
+ * IMAGES: The graphic information for the structures
+ *
+ * The _misc field of the structures contains the number of the graphic image
+ * that it should point to after loading; _misc is then set to 0.
+ */
bool loadScene(const Common::String &filename);
+ /**
+ * Loads sounds for the scene
+ */
void loadSceneSounds();
+ /**
+ * Set objects to their current persistent state. This includes things such as
+ * opening or moving them
+ */
void checkSceneStatus();
+ /**
+ * Checks scene objects against the player's inventory items. If there are any
+ * matching names, it means the given item has already been picked up, and should
+ * be hidden in the scene.
+ */
void checkInventory();
+ /**
+ * Set up any entrance co-ordinates or entrance canimations, and then transition
+ * in the scene
+ */
void transitionToScene();
+ /**
+ * Checks all the background shapes. If a background shape is animating,
+ * it will flag it as needing to be drawn. If a non-animating shape is
+ * colliding with another shape, it will also flag it as needing drawing
+ */
void checkBgShapes(ImageFrame *frame, const Common::Point &pt);
+ /**
+ * Restores objects to the correct status. This ensures that things like being opened or moved
+ * will remain the same on future visits to the scene
+ */
void saveSceneStatus();
public:
int _currentScene;
int _goToScene;
- bool _changes;
bool _sceneStats[SCENES_COUNT][65];
bool _savedStats[SCENES_COUNT][9];
- int _keyboardInput;
- int _oldKey, _help, _oldHelp;
- int _oldTemp, _temp;
bool _walkedInScene;
int _version;
bool _lzwMode;
@@ -165,37 +212,84 @@ public:
bool _doBgAnimDone;
int _tempFadeStyle;
int _cAnimFramePause;
- bool _invLookFlag;
public:
Scene(SherlockEngine *vm);
~Scene();
+ /**
+ * Handles loading the scene specified by _goToScene
+ */
void selectScene();
+ /**
+ * Fres all the graphics and other dynamically allocated data for the scene
+ */
void freeScene();
+ /**
+ * Check the scene's objects against the game flags. If false is passed,
+ * it means the scene has just been loaded. A value of true means that the scene
+ * is in use (ie. not just loaded)
+ */
void checkSceneFlags(bool mode);
+ /**
+ * Check whether the passed area intersects with one of the scene's exits
+ */
Exit *checkForExit(const Common::Rect &r);
+ /**
+ * Attempt to start a canimation sequence. It will load the requisite graphics, and
+ * then copy the canim object into the _canimShapes array to start the animation.
+ *
+ * @param cAnimNum The canim object within the current scene
+ * @param playRate Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
+ * A negative playRate can also be specified to play the animation in reverse
+ */
int startCAnim(int cAnimNum, int playRate);
+ /**
+ * Scans through the object list to find one with a matching name, and will
+ * call toggleHidden with all matches found. Returns the numer of matches found
+ */
int toggleObject(const Common::String &name);
+ /**
+ * Animate all objects and people.
+ */
void doBgAnim();
- void clearInfo();
-
+ /**
+ * Attempts to find a background shape within the passed bounds. If found,
+ * it will return the shape number, or -1 on failure.
+ */
int findBgShape(const Common::Rect &r);
+ /**
+ * Checks to see if the given position in the scene belongs to a given zone type.
+ * If it is, the zone is activated and used just like a TAKL zone or aFLAG_SET zone.
+ */
int checkForZones(const Common::Point &pt, int zoneType);
+ /**
+ * Check which zone the the given position is located in.
+ */
int whichZone(const Common::Point &pt);
+ /**
+ * Returns the index of the closest zone to a given point.
+ */
int closestZone(const Common::Point &pt);
+ /**
+ * Update the screen back buffer with all of the scene objects which need
+ * to be drawn
+ */
void updateBackground();
+ /**
+ * Synchronize the data for a savegame
+ */
void synchronize(Common::Serializer &s);
};
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index 349bf4d024..24f7660743 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -41,10 +41,6 @@ Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->get
Common::fill(&_tMap[0], &_tMap[PALETTE_SIZE], 0);
setFont(1);
- // Set dummy surface used for restricted scene drawing
- _sceneSurface.format = Graphics::PixelFormat::createFormatCLUT8();
- _sceneSurface.pitch = pitch;
-
// Rose Tattoo specific fields
_fadeBytesRead = _fadeBytesToRead = 0;
_oldFadePercent = 0;
@@ -57,10 +53,11 @@ Screen::~Screen() {
delete _font;
}
-/**
- * Set the font to use for writing text on the screen
- */
void Screen::setFont(int fontNumb) {
+ // Interactive demo doesn't use fonts
+ if (!_vm->_interactiveFl)
+ return;
+
_fontNumber = fontNumb;
Common::String fname = Common::String::format("FONT%d.VGS", fontNumb + 1);
@@ -74,9 +71,6 @@ void Screen::setFont(int fontNumb) {
_fontHeight = MAX((uint16)_fontHeight, (*_font)[idx]._frame.h);
}
-/**
- * Handles updating any dirty areas of the screen Surface object to the physical screen
- */
void Screen::update() {
// Merge the dirty rects
mergeDirtyRects();
@@ -86,7 +80,7 @@ void Screen::update() {
for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
const Common::Rect &r = *i;
const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
- g_system->copyRectToScreen(srcP, this->pitch, r.left, r.top,
+ g_system->copyRectToScreen(srcP, _surface.pitch, r.left, r.top,
r.width(), r.height());
}
@@ -95,23 +89,14 @@ void Screen::update() {
_dirtyRects.clear();
}
-/**
- * Return the currently active palette
- */
void Screen::getPalette(byte palette[PALETTE_SIZE]) {
g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT);
}
-/**
- * Set the palette
- */
void Screen::setPalette(const byte palette[PALETTE_SIZE]) {
g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT);
}
-/**
- * Fades from the currently active palette to the passed palette
- */
int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) {
int total = 0;
byte tempPalette[PALETTE_SIZE];
@@ -120,8 +105,7 @@ int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) {
// For any palette component that doesn't already match the given destination
// palette, change by 1 towards the reference palette component
for (int idx = 0; idx < PALETTE_SIZE; ++idx) {
- if (tempPalette[idx] > palette[idx])
- {
+ if (tempPalette[idx] > palette[idx]) {
tempPalette[idx] = MAX((int)palette[idx], (int)tempPalette[idx] - 4);
++total;
} else if (tempPalette[idx] < palette[idx]) {
@@ -137,9 +121,6 @@ int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) {
return total;
}
-/**
- * Fade out the palette to black
- */
void Screen::fadeToBlack(int speed) {
byte tempPalette[PALETTE_SIZE];
Common::fill(&tempPalette[0], &tempPalette[PALETTE_SIZE], 0);
@@ -149,12 +130,9 @@ void Screen::fadeToBlack(int speed) {
}
setPalette(tempPalette);
- fillRect(Common::Rect(0, 0, this->w, this->h), 0);
+ fillRect(Common::Rect(0, 0, _surface.w, _surface.h), 0);
}
-/**
- * Fade in a given palette
- */
void Screen::fadeIn(const byte palette[PALETTE_SIZE], int speed) {
int count = 50;
while (equalizePalette(palette) && --count) {
@@ -164,18 +142,11 @@ void Screen::fadeIn(const byte palette[PALETTE_SIZE], int speed) {
setPalette(palette);
}
-/**
- * Adds a rectangle to the list of modified areas of the screen during the
- * current frame
- */
void Screen::addDirtyRect(const Common::Rect &r) {
_dirtyRects.push_back(r);
assert(r.width() > 0 && r.height() > 0);
}
-/**
- * Merges together overlapping dirty areas of the screen
- */
void Screen::mergeDirtyRects() {
Common::List<Common::Rect>::iterator rOuter, rInner;
@@ -200,9 +171,6 @@ void Screen::mergeDirtyRects() {
}
}
-/**
- * Returns the union of two dirty area rectangles
- */
bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
destRect = src1;
destRect.extend(src2);
@@ -210,9 +178,6 @@ bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, co
return !destRect.isEmpty();
}
-/**
- * Do a random pixel transition in from _backBuffer surface to the screen
- */
void Screen::randomTransition() {
Events &events = *_vm->_events;
const int TRANSITION_MULTIPLIER = 0x15a4e35;
@@ -220,15 +185,15 @@ void Screen::randomTransition() {
for (int idx = 0; idx <= 65535 && !_vm->shouldQuit(); ++idx) {
_transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1;
- int offset = _transitionSeed & 65535;
+ int offset = _transitionSeed & 0xFFFF;
- if (offset < (this->w * this->h))
+ if (offset < (this->w() * this->h()))
*((byte *)getPixels() + offset) = *((const byte *)_backBuffer->getPixels() + offset);
if (idx != 0 && (idx % 300) == 0) {
// Ensure there's a full screen dirty rect for the next frame update
if (_dirtyRects.empty())
- addDirtyRect(Common::Rect(0, 0, this->w, this->h));
+ addDirtyRect(Common::Rect(0, 0, _surface.w, _surface.h));
events.pollEvents();
events.delay(1);
@@ -239,18 +204,15 @@ void Screen::randomTransition() {
blitFrom(*_backBuffer);
}
-/**
- * Transition to the surface from _backBuffer using a vertical transition
- */
void Screen::verticalTransition() {
Events &events = *_vm->_events;
byte table[640];
Common::fill(&table[0], &table[640], 0);
- for (int yp = 0; yp < this->h; ++yp) {
- for (int xp = 0; xp < this->w; ++xp) {
- int temp = (table[xp] >= (this->h - 3)) ? this->h - table[xp] :
+ for (int yp = 0; yp < this->h(); ++yp) {
+ for (int xp = 0; xp < this->w(); ++xp) {
+ int temp = (table[xp] >= (this->h() - 3)) ? this->h() - table[xp] :
_vm->getRandomNumber(3) + 1;
if (temp) {
@@ -264,43 +226,30 @@ void Screen::verticalTransition() {
}
}
-/**
- * Copies a section of the second back buffer into the main back buffer
- */
void Screen::restoreBackground(const Common::Rect &r) {
if (r.width() > 0 && r.height() > 0) {
Common::Rect tempRect = r;
- tempRect.clip(Common::Rect(0, 0, this->w, SHERLOCK_SCENE_HEIGHT));
+ tempRect.clip(Common::Rect(0, 0, this->w(), SHERLOCK_SCENE_HEIGHT));
if (tempRect.isValidRect())
_backBuffer1.blitFrom(_backBuffer2, Common::Point(tempRect.left, tempRect.top), tempRect);
}
}
-/**
- * Copies a given area to the screen
- */
void Screen::slamArea(int16 xp, int16 yp, int16 width, int16 height) {
slamRect(Common::Rect(xp, yp, xp + width, yp + height));
}
-/**
- * Copies a given area to the screen
- */
void Screen::slamRect(const Common::Rect &r) {
if (r.width() && r.height() > 0) {
Common::Rect tempRect = r;
- tempRect.clip(Common::Rect(0, 0, this->w, this->h));
+ tempRect.clip(Common::Rect(0, 0, this->w(), this->h()));
if (tempRect.isValidRect())
blitFrom(*_backBuffer, Common::Point(tempRect.left, tempRect.top), tempRect);
}
}
-/**
- * Copy an image from the back buffer to the screen, taking care of both the
- * new area covered by the shape as well as the old area, which must be restored
- */
void Screen::flushImage(ImageFrame *frame, const Common::Point &pt,
int16 *xp, int16 *yp, int16 *width, int16 *height) {
Common::Point imgPos = pt + frame->_offset;
@@ -327,19 +276,12 @@ void Screen::flushImage(ImageFrame *frame, const Common::Point &pt,
*height = newBounds.height();
}
-/**
- * Prints the text passed onto the back buffer at the given position and color.
- * The string is then blitted to the screen
- */
void Screen::print(const Common::Point &pt, byte color, const char *formatStr, ...) {
// Create the string to display
- char buffer[100];
va_list args;
-
va_start(args, formatStr);
- vsprintf(buffer, formatStr, args);
+ Common::String str = Common::String::vformat(formatStr, args);
va_end(args);
- Common::String str(buffer);
// Figure out area to draw text in
Common::Point pos = pt;
@@ -347,13 +289,13 @@ void Screen::print(const Common::Point &pt, byte color, const char *formatStr, .
pos.y--; // Font is always drawing one line higher
if (!pos.x)
// Center text horizontally
- pos.x = (this->w - width) / 2;
+ pos.x = (this->w() - width) / 2;
Common::Rect textBounds(pos.x, pos.y, pos.x + width, pos.y + _fontHeight);
- if (textBounds.right > this->w)
- textBounds.moveTo(this->w - width, textBounds.top);
- if (textBounds.bottom > this->h)
- textBounds.moveTo(textBounds.left, this->h - _fontHeight);
+ if (textBounds.right > this->w())
+ textBounds.moveTo(this->w() - width, textBounds.top);
+ if (textBounds.bottom > this->h())
+ textBounds.moveTo(textBounds.left, this->h() - _fontHeight);
// Write out the string at the given position
writeString(str, Common::Point(textBounds.left, textBounds.top), color);
@@ -362,27 +304,17 @@ void Screen::print(const Common::Point &pt, byte color, const char *formatStr, .
slamRect(textBounds);
}
-/**
- * Print a strings onto the back buffer without blitting it to the screen
- */
void Screen::gPrint(const Common::Point &pt, byte color, const char *formatStr, ...) {
// Create the string to display
- char buffer[100];
va_list args;
-
va_start(args, formatStr);
- vsprintf(buffer, formatStr, args);
+ Common::String str = Common::String::vformat(formatStr, args);
va_end(args);
- Common::String str(buffer);
// Print the text
writeString(str, pt, color);
}
-
-/**
- * Returns the width of a string in pixels
- */
int Screen::stringWidth(const Common::String &str) {
int width = 0;
@@ -392,21 +324,15 @@ int Screen::stringWidth(const Common::String &str) {
return width;
}
-/**
- * Returns the width of a character in pixels
- */
int Screen::charWidth(char c) {
if (c == ' ')
return 5;
- else if (c > ' ' && c <= '~')
+ else if (Common::isPrint(c))
return (*_font)[c - 33]._frame.w + 1;
else
return 0;
}
-/**
- * Draws the given string into the back buffer using the images stored in _font
- */
void Screen::writeString(const Common::String &str, const Common::Point &pt, byte color) {
Common::Point charPos = pt;
@@ -414,7 +340,7 @@ void Screen::writeString(const Common::String &str, const Common::Point &pt, byt
if (*c == ' ')
charPos.x += 5;
else {
- assert(*c > ' ' && *c <= '~');
+ assert(Common::isPrint(*c));
ImageFrame &frame = (*_font)[*c - 33];
_backBuffer->transBlitFrom(frame, charPos, false, color);
charPos.x += frame._frame.w + 1;
@@ -422,17 +348,11 @@ void Screen::writeString(const Common::String &str, const Common::Point &pt, byt
}
}
-/**
- * Fills an area on the back buffer, and then copies it to the screen
- */
void Screen::vgaBar(const Common::Rect &r, int color) {
_backBuffer->fillRect(r, color);
slamRect(r);
}
-/**
- * Draws a button for use in the inventory, talk, and examine dialogs.
- */
void Screen::makeButton(const Common::Rect &bounds, int textX,
const Common::String &str) {
@@ -448,10 +368,6 @@ void Screen::makeButton(const Common::Rect &bounds, int textX,
COMMAND_FOREGROUND, "%s", str.c_str() + 1);
}
-/**
- * Prints an interface command with the first letter highlighted to indicate
- * what keyboard shortcut is associated with it
- */
void Screen::buttonPrint(const Common::Point &pt, byte color, bool slamIt,
const Common::String &str) {
int xStart = pt.x - stringWidth(str) / 2;
@@ -461,22 +377,19 @@ void Screen::buttonPrint(const Common::Point &pt, byte color, bool slamIt,
if (slamIt) {
print(Common::Point(xStart, pt.y + 1), COMMAND_HIGHLIGHTED, "%c", str[0]);
print(Common::Point(xStart + charWidth(str[0]), pt.y + 1),
- COMMAND_FOREGROUND, str.c_str() + 1);
+ COMMAND_FOREGROUND, "%s", str.c_str() + 1);
} else {
gPrint(Common::Point(xStart, pt.y), COMMAND_HIGHLIGHTED, "%c", str[0]);
gPrint(Common::Point(xStart + charWidth(str[0]), pt.y),
- COMMAND_FOREGROUND, str.c_str() + 1);
+ COMMAND_FOREGROUND, "%s", str.c_str() + 1);
}
} else if (slamIt) {
- print(Common::Point(xStart, pt.y + 1), color, str.c_str());
+ print(Common::Point(xStart, pt.y + 1), color, "%s", str.c_str());
} else {
- gPrint(Common::Point(xStart, pt.y), color, str.c_str());
+ gPrint(Common::Point(xStart, pt.y), color, "%s", str.c_str());
}
}
-/**
- * Draw a panel in th eback buffer with a raised area effect around the edges
- */
void Screen::makePanel(const Common::Rect &r) {
_backBuffer->fillRect(r, BUTTON_MIDDLE);
_backBuffer->hLine(r.left, r.top, r.right - 2, BUTTON_TOP);
@@ -490,36 +403,30 @@ void Screen::makePanel(const Common::Rect &r) {
_backBuffer->hLine(r.left + 1, r.bottom - 2, r.right - 1, BUTTON_BOTTOM);
}
-/**
- * Sets the active back buffer pointer to a restricted sub-area of the first back buffer
- */
+void Screen::makeField(const Common::Rect &r) {
+ _backBuffer->fillRect(r, BUTTON_MIDDLE);
+ _backBuffer->hLine(r.left, r.top, r.right - 1, BUTTON_BOTTOM);
+ _backBuffer->hLine(r.left + 1, r.bottom - 1, r.right - 1, BUTTON_TOP);
+ _backBuffer->vLine(r.left, r.top + 1, r.bottom - 1, BUTTON_BOTTOM);
+ _backBuffer->vLine(r.right - 1, r.top + 1, r.bottom - 2, BUTTON_TOP);
+}
+
void Screen::setDisplayBounds(const Common::Rect &r) {
assert(r.left == 0 && r.top == 0);
- _sceneSurface.setPixels(_backBuffer1.getPixels());
- _sceneSurface.w = r.width();
- _sceneSurface.h = r.height();
+ _sceneSurface.setPixels(_backBuffer1.getPixels(), r.width(), r.height());
_backBuffer = &_sceneSurface;
}
-/**
- * Resets the active buffer pointer to point back to the full first back buffer
- */
void Screen::resetDisplayBounds() {
_backBuffer = &_backBuffer1;
}
-/**
- * Return the size of the current display window
- */
Common::Rect Screen::getDisplayBounds() {
- return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.w, _sceneSurface.h) :
- Common::Rect(0, 0, this->w, this->h);
+ return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.w(), _sceneSurface.h()) :
+ Common::Rect(0, 0, this->w(), this->h());
}
-/**
- * Synchronize the data for a savegame
- */
void Screen::synchronize(Common::Serializer &s) {
int fontNumb = _fontNumber;
s.syncAsByte(fontNumb);
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index 8a8eca13fc..f4cd6fd955 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -36,22 +36,22 @@ namespace Sherlock {
#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
enum {
- INFO_BLACK = 1,
- INFO_FOREGROUND = 11,
- INFO_BACKGROUND = 1,
- BORDER_COLOR = 237,
- INV_FOREGROUND = 14,
- INV_BACKGROUND = 1,
- COMMAND_HIGHLIGHTED = 10,
- COMMAND_FOREGROUND = 15,
- COMMAND_BACKGROUND = 4,
- COMMAND_NULL = 248,
- BUTTON_TOP = 233,
- BUTTON_MIDDLE = 244,
- BUTTON_BOTTOM = 248,
- TALK_FOREGROUND = 12,
- TALK_NULL = 16,
- PEN_COLOR = 250
+ INFO_BLACK = 1,
+ INFO_FOREGROUND = 11,
+ INFO_BACKGROUND = 1,
+ BORDER_COLOR = 237,
+ INV_FOREGROUND = 14,
+ INV_BACKGROUND = 1,
+ COMMAND_HIGHLIGHTED = 10,
+ COMMAND_FOREGROUND = 15,
+ COMMAND_BACKGROUND = 4,
+ COMMAND_NULL = 248,
+ BUTTON_TOP = 233,
+ BUTTON_MIDDLE = 244,
+ BUTTON_BOTTOM = 248,
+ TALK_FOREGROUND = 12,
+ TALK_NULL = 16,
+ PEN_COLOR = 250
};
class SherlockEngine;
@@ -75,12 +75,25 @@ private:
int _currentScroll;
int _targetScroll;
private:
+ /**
+ * Merges together overlapping dirty areas of the screen
+ */
void mergeDirtyRects();
+ /**
+ * Returns the union of two dirty area rectangles
+ */
bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
+ /**
+ * Draws the given string into the back buffer using the images stored in _font
+ */
void writeString(const Common::String &str, const Common::Point &pt, byte color);
protected:
+ /**
+ * Adds a rectangle to the list of modified areas of the screen during the
+ * current frame
+ */
virtual void addDirtyRect(const Common::Rect &r);
public:
Surface _backBuffer1, _backBuffer2;
@@ -93,53 +106,141 @@ public:
Screen(SherlockEngine *vm);
virtual ~Screen();
+ /**
+ * Set the font to use for writing text on the screen
+ */
void setFont(int fontNumber);
+ /**
+ * Handles updating any dirty areas of the screen Surface object to the physical screen
+ */
void update();
+ /**
+ * Return the currently active palette
+ */
void getPalette(byte palette[PALETTE_SIZE]);
+ /**
+ * Set the palette
+ */
void setPalette(const byte palette[PALETTE_SIZE]);
+ /**
+ * Fades from the currently active palette to the passed palette
+ */
int equalizePalette(const byte palette[PALETTE_SIZE]);
+ /**
+ * Fade out the palette to black
+ */
void fadeToBlack(int speed = 2);
+ /**
+ * Fade in a given palette
+ */
void fadeIn(const byte palette[PALETTE_SIZE], int speed = 2);
+ /**
+ * Do a random pixel transition in from _backBuffer surface to the screen
+ */
void randomTransition();
+ /**
+ * Transition to the surface from _backBuffer using a vertical transition
+ */
void verticalTransition();
- void print(const Common::Point &pt, byte color, const char *formatStr, ...);
- void gPrint(const Common::Point &pt, byte color, const char *formatStr, ...);
+ /**
+ * Prints the text passed onto the back buffer at the given position and color.
+ * The string is then blitted to the screen
+ */
+ void print(const Common::Point &pt, byte color, const char *formatStr, ...) GCC_PRINTF(4, 5);
+ /**
+ * Print a strings onto the back buffer without blitting it to the screen
+ */
+ void gPrint(const Common::Point &pt, byte color, const char *formatStr, ...) GCC_PRINTF(4, 5);
+
+ /**
+ * Copies a section of the second back buffer into the main back buffer
+ */
void restoreBackground(const Common::Rect &r);
+ /**
+ * Copies a given area to the screen
+ */
void slamArea(int16 xp, int16 yp, int16 width, int16 height);
+
+ /**
+ * Copies a given area to the screen
+ */
void slamRect(const Common::Rect &r);
+ /**
+ * Copy an image from the back buffer to the screen, taking care of both the
+ * new area covered by the shape as well as the old area, which must be restored
+ */
void flushImage(ImageFrame *frame, const Common::Point &pt,
int16 *xp, int16 *yp, int16 *width, int16 *height);
+ /**
+ * Returns the width of a string in pixels
+ */
int stringWidth(const Common::String &str);
+ /**
+ * Returns the width of a character in pixels
+ */
int charWidth(char c);
+ /**
+ * Fills an area on the back buffer, and then copies it to the screen
+ */
void vgaBar(const Common::Rect &r, int color);
+ /**
+ * Draws a button for use in the inventory, talk, and examine dialogs.
+ */
void makeButton(const Common::Rect &bounds, int textX, const Common::String &str);
+ /**
+ * Prints an interface command with the first letter highlighted to indicate
+ * what keyboard shortcut is associated with it
+ */
void buttonPrint(const Common::Point &pt, byte color, bool slamIt, const Common::String &str);
+ /**
+ * Draw a panel in the back buffer with a raised area effect around the edges
+ */
void makePanel(const Common::Rect &r);
+ /**
+ * Draw a field in the back buffer with a raised area effect around the edges,
+ * suitable for text input.
+ */
+ void makeField(const Common::Rect &r);
+
+ /**
+ * Sets the active back buffer pointer to a restricted sub-area of the first back buffer
+ */
void setDisplayBounds(const Common::Rect &r);
+
+ /**
+ * Resets the active buffer pointer to point back to the full first back buffer
+ */
void resetDisplayBounds();
+
+ /**
+ * Return the size of the current display window
+ */
Common::Rect getDisplayBounds();
int fontNumber() const { return _fontNumber; }
+ /**
+ * Synchronize the data for a savegame
+ */
void synchronize(Common::Serializer &s);
// Rose Tattoo specific methods
diff --git a/engines/sherlock/settings.cpp b/engines/sherlock/settings.cpp
index 73c99bfa82..cae5c6c67a 100644
--- a/engines/sherlock/settings.cpp
+++ b/engines/sherlock/settings.cpp
@@ -25,7 +25,7 @@
namespace Sherlock {
-const int SETUP_POINTS[12][4] = {
+static const int SETUP_POINTS[12][4] = {
{ 4, 154, 101, 53 }, // Exit
{ 4, 165, 101, 53 }, // Music Toggle
{ 219, 165, 316, 268 }, // Voice Toggle
@@ -40,21 +40,17 @@ const int SETUP_POINTS[12][4] = {
{ 219, 187, 316, 268 } // _key Pad Accel. Toggle
};
-const char *const SETUP_STRS0[2] = { "off", "on" };
-const char *const SETUP_STRS1[2] = { "Directly", "by Pixel" };
-const char *const SETUP_STRS2[2] = { "Left", "Right" };
-const char *const SETUP_STRS3[2] = { "Appear", "Slide" };
-const char *const SETUP_STRS4[2] = { "Slow", "Fast" };
-const char *const SETUP_STRS5[2] = { "Left", "Right" };
-const char *const SETUP_NAMES[12] = {
+static const char *const SETUP_STRS0[2] = { "off", "on" };
+static const char *const SETUP_STRS1[2] = { "Directly", "by Pixel" };
+static const char *const SETUP_STRS2[2] = { "Left", "Right" };
+static const char *const SETUP_STRS3[2] = { "Appear", "Slide" };
+static const char *const SETUP_STRS5[2] = { "Left", "Right" };
+static const char *const SETUP_NAMES[12] = {
"Exit", "M", "V", "S", "B", "New Font Style", "J", "Calibrate Joystick", "F", "W", "P", "K"
};
/*----------------------------------------------------------------*/
-/**
- * Draws the interface for the settings window
- */
void Settings::drawInteface(bool flag) {
People &people = *_vm->_people;
Screen &screen = *_vm->_screen;
@@ -108,7 +104,7 @@ void Settings::drawInteface(bool flag) {
screen.makeButton(Common::Rect(SETUP_POINTS[8][0], SETUP_POINTS[8][1], SETUP_POINTS[8][2], SETUP_POINTS[8][1] + 10),
SETUP_POINTS[8][3] - screen.stringWidth(tempStr) / 2, tempStr);
- tempStr = Common::String::format("Windows %s", ui._windowStyle ? "Slide" : "Appear");
+ tempStr = Common::String::format("Windows %s", ui._slideWindows ? "Slide" : "Appear");
screen.makeButton(Common::Rect(SETUP_POINTS[9][0], SETUP_POINTS[9][1], SETUP_POINTS[9][2], SETUP_POINTS[9][1] + 10),
SETUP_POINTS[9][3] - screen.stringWidth(tempStr) / 2, tempStr);
@@ -123,7 +119,7 @@ void Settings::drawInteface(bool flag) {
// Show the window immediately, or slide it on-screen
if (!flag) {
- if (!ui._windowStyle) {
+ if (!ui._slideWindows) {
screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
} else {
ui.summonWindow(true, CONTROLS_Y1);
@@ -135,9 +131,6 @@ void Settings::drawInteface(bool flag) {
}
}
-/**
- * Draws the buttons for the settings dialog
- */
int Settings::drawButtons(const Common::Point &pt, int _key) {
Events &events = *_vm->_events;
People &people = *_vm->_people;
@@ -150,7 +143,7 @@ int Settings::drawButtons(const Common::Point &pt, int _key) {
for (int idx = 0; idx < 12; ++idx) {
if ((pt.x > SETUP_POINTS[idx][0] && pt.x < SETUP_POINTS[idx][2] && pt.y > SETUP_POINTS[idx][1]
- && pt.y < (SETUP_POINTS[idx][1] + 10) && (events._released || events._released))
+ && pt.y < (SETUP_POINTS[idx][1] + 10) && (events._pressed || events._released))
|| (_key == SETUP_NAMES[idx][0])) {
found = idx;
color = COMMAND_HIGHLIGHTED;
@@ -189,7 +182,7 @@ int Settings::drawButtons(const Common::Point &pt, int _key) {
screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
break;
case 9:
- tempStr = Common::String::format("Windows %s", SETUP_STRS3[ui._windowStyle]);
+ tempStr = Common::String::format("Windows %s", SETUP_STRS3[ui._slideWindows]);
screen.buttonPrint(Common::Point(SETUP_POINTS[idx][3], SETUP_POINTS[idx][1]), color, true, tempStr);
break;
case 10:
@@ -209,13 +202,6 @@ int Settings::drawButtons(const Common::Point &pt, int _key) {
return found;
}
-
-/**
-* Handles input when the settings window is being shown
-* @remarks Whilst this would in theory be better in the Journal class, since it displays in
-* the user interface, it uses so many internal UI fields, that it sort of made some sense
-* to put it in the UserInterface class.
-*/
void Settings::show(SherlockEngine *vm) {
Events &events = *vm->_events;
People &people = *vm->_people;
@@ -255,7 +241,7 @@ void Settings::show(SherlockEngine *vm) {
if (ui._key == Common::KEYCODE_RETURN || ui._key == Common::KEYCODE_SPACE) {
events._pressed = false;
events._oldButtons = 0;
- ui._keycode = Common::KEYCODE_INVALID;
+ ui._keyPress = '\0';
events._released = true;
}
}
@@ -323,7 +309,7 @@ void Settings::show(SherlockEngine *vm) {
if ((found == 9 && events._released) || ui._key == 'W') {
// Window style
- ui._windowStyle ^= 1;
+ ui._slideWindows = !ui._slideWindows;
updateConfig = true;
settings.drawInteface(true);
}
@@ -341,7 +327,7 @@ void Settings::show(SherlockEngine *vm) {
if (updateConfig)
vm->saveConfig();
- ui._keycode = Common::KEYCODE_INVALID;
+ ui._keyPress = '\0';
ui._keyboardInput = false;
ui._windowBounds.top = CONTROLS_Y1;
ui._key = -1;
diff --git a/engines/sherlock/settings.h b/engines/sherlock/settings.h
index 25d27d48df..fc5fb2959f 100644
--- a/engines/sherlock/settings.h
+++ b/engines/sherlock/settings.h
@@ -36,10 +36,22 @@ private:
Settings(SherlockEngine *vm) : _vm(vm) {}
+ /**
+ * Draws the interface for the settings window
+ */
void drawInteface(bool flag);
+ /**
+ * Draws the buttons for the settings dialog
+ */
int drawButtons(const Common::Point &pt, int key);
public:
+ /**
+ * Handles input when the settings window is being shown
+ * @remarks Whilst this would in theory be better in the Journal class, since it displays in
+ * the user interface, it uses so many internal UI fields, that it sort of made some sense
+ * to put it in the UserInterface class.
+ */
static void show(SherlockEngine *vm);
};
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index 80a4383bdf..5973823f96 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -48,6 +48,7 @@ SherlockEngine::SherlockEngine(OSystem *syst, const SherlockGameDescription *gam
_loadGameSlot = -1;
_canLoadSave = false;
_showOriginalSavesDialog = false;
+ _interactiveFl = true;
}
SherlockEngine::~SherlockEngine() {
@@ -67,15 +68,21 @@ SherlockEngine::~SherlockEngine() {
delete _res;
}
-/**
- * Does basic initialization of the game engine
- */
void SherlockEngine::initialize() {
DebugMan.addDebugChannel(kDebugScript, "scripts", "Script debug level");
ImageFile::setVm(this);
Object::setVm(this);
Sprite::setVm(this);
+
+ if (isDemo()) {
+ Common::File f;
+ // The interactive demo doesn't have an intro thus doesn't include TITLE.SND
+ // At the opposite, the non-interactive demo is only the intro.
+ if (f.exists("TITLE.SND"))
+ _interactiveFl = false;
+ }
+
_res = new Resources(this);
_animation = new Animation(this);
_debugger = new Debugger(this);
@@ -95,9 +102,6 @@ void SherlockEngine::initialize() {
loadConfig();
}
-/**
- * Main method for running the game
- */
Common::Error SherlockEngine::run() {
// Initialize the engine
initialize();
@@ -116,7 +120,9 @@ Common::Error SherlockEngine::run() {
_saves->loadGame(_loadGameSlot);
_loadGameSlot = -1;
} else {
- showOpening();
+ do
+ showOpening();
+ while (!shouldQuit() && !_interactiveFl);
}
while (!shouldQuit()) {
@@ -145,9 +151,6 @@ Common::Error SherlockEngine::run() {
return Common::kNoError;
}
-/**
- * Main loop for displaying a scene and handling all that occurs within it
- */
void SherlockEngine::sceneLoop() {
while (!shouldQuit() && _scene->_goToScene == -1) {
// See if a script needs to be completed from either a goto room code,
@@ -172,9 +175,6 @@ void SherlockEngine::sceneLoop() {
}
-/**
- * Handle all player input
- */
void SherlockEngine::handleInput() {
_canLoadSave = true;
_events->pollEventsAndWait();
@@ -186,9 +186,6 @@ void SherlockEngine::handleInput() {
_ui->handleInput();
}
-/**
- * Read the state of a global flag
- */
bool SherlockEngine::readFlags(int flagNum) {
bool value = _flags[ABS(flagNum)];
if (flagNum < 0)
@@ -197,40 +194,25 @@ bool SherlockEngine::readFlags(int flagNum) {
return value;
}
-/**
- * Sets a global flag to either true or false depending on whether the specified
- * flag is positive or negative
- */
void SherlockEngine::setFlags(int flagNum) {
_flags[ABS(flagNum)] = flagNum >= 0;
_scene->checkSceneFlags(true);
}
-/**
- * Load game configuration esttings
- */
void SherlockEngine::loadConfig() {
// Load sound settings
syncSoundSettings();
ConfMan.registerDefault("font", 1);
- ConfMan.registerDefault("fade_style", true);
- ConfMan.registerDefault("help_style", false);
- ConfMan.registerDefault("window_style", 1);
- ConfMan.registerDefault("portraits_on", true);
- ConfMan.registerDefault("originalsaveload", false);
_screen->setFont(ConfMan.getInt("font"));
_screen->_fadeStyle = ConfMan.getBool("fade_style");
_ui->_helpStyle = ConfMan.getBool("help_style");
- _ui->_windowStyle = ConfMan.getInt("window_style");
+ _ui->_slideWindows = ConfMan.getBool("window_style");
_people->_portraitsOn = ConfMan.getBool("portraits_on");
}
-/**
- * Saves game configuration information
- */
void SherlockEngine::saveConfig() {
ConfMan.setBool("mute", !_sound->_digitized);
ConfMan.setBool("music_mute", !_sound->_music);
@@ -239,15 +221,12 @@ void SherlockEngine::saveConfig() {
ConfMan.setInt("font", _screen->fontNumber());
ConfMan.setBool("fade_style", _screen->_fadeStyle);
ConfMan.setBool("help_style", _ui->_helpStyle);
- ConfMan.setInt("window_style", _ui->_windowStyle);
+ ConfMan.setBool("window_style", _ui->_slideWindows);
ConfMan.setBool("portraits_on", _people->_portraitsOn);
ConfMan.flushToDisk();
}
-/**
- * Called by the engine when sound settings are updated
- */
void SherlockEngine::syncSoundSettings() {
Engine::syncSoundSettings();
@@ -255,39 +234,24 @@ void SherlockEngine::syncSoundSettings() {
_sound->syncSoundSettings();
}
-/**
- * Synchronize the data for a savegame
- */
void SherlockEngine::synchronize(Common::Serializer &s) {
for (uint idx = 0; idx < _flags.size(); ++idx)
s.syncAsByte(_flags[idx]);
}
-/**
- * Returns true if a savegame can be loaded
- */
bool SherlockEngine::canLoadGameStateCurrently() {
return _canLoadSave;
}
-/**
- * Returns true if the game can be saved
- */
bool SherlockEngine::canSaveGameStateCurrently() {
return _canLoadSave;
}
-/**
- * Called by the GMM to load a savegame
- */
Common::Error SherlockEngine::loadGameState(int slot) {
_saves->loadGame(slot);
return Common::kNoError;
}
-/**
- * Called by the GMM to save the game
- */
Common::Error SherlockEngine::saveGameState(int slot, const Common::String &desc) {
_saves->saveGame(slot, desc);
return Common::kNoError;
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index 2688b51d4c..bf8c0d6aaf 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -50,10 +50,6 @@
namespace Sherlock {
enum {
- kFileTypeHash
-};
-
-enum {
kDebugScript = 1 << 0
};
@@ -62,8 +58,8 @@ enum GameType {
GType_RoseTattoo = 1
};
-#define SHERLOCK_SCREEN_WIDTH _vm->_screen->w
-#define SHERLOCK_SCREEN_HEIGHT _vm->_screen->h
+#define SHERLOCK_SCREEN_WIDTH _vm->_screen->w()
+#define SHERLOCK_SCREEN_HEIGHT _vm->_screen->h()
#define SHERLOCK_SCENE_HEIGHT 138
struct SherlockGameDescription;
@@ -72,18 +68,33 @@ class Resource;
class SherlockEngine : public Engine {
private:
+ /**
+ * Main loop for displaying a scene and handling all that occurs within it
+ */
void sceneLoop();
+ /**
+ * Handle all player input
+ */
void handleInput();
+ /**
+ * Load game configuration esttings
+ */
void loadConfig();
protected:
+ /**
+ * Does basic initialization of the game engine
+ */
virtual void initialize();
virtual void showOpening() = 0;
virtual void startScene() {}
+ /**
+ * Returns a list of features the game itself supports
+ */
virtual bool hasFeature(EngineFeature f) const;
public:
const SherlockGameDescription *_gameDescription;
@@ -103,39 +114,86 @@ public:
UserInterface *_ui;
Common::RandomSource _randomSource;
Common::Array<bool> _flags;
- Common::String _soundOverride;
- Common::String _titleOverride;
bool _useEpilogue2;
int _loadGameSlot;
bool _canLoadSave;
bool _showOriginalSavesDialog;
+ bool _interactiveFl;
public:
SherlockEngine(OSystem *syst, const SherlockGameDescription *gameDesc);
virtual ~SherlockEngine();
+ /**
+ * Main method for running the game
+ */
virtual Common::Error run();
+ /**
+ * Returns true if a savegame can be loaded
+ */
virtual bool canLoadGameStateCurrently();
+
+ /**
+ * Returns true if the game can be saved
+ */
virtual bool canSaveGameStateCurrently();
+
+ /**
+ * Called by the GMM to load a savegame
+ */
virtual Common::Error loadGameState(int slot);
+
+ /**
+ * Called by the GMM to save the game
+ */
virtual Common::Error saveGameState(int slot, const Common::String &desc);
+
+ /**
+ * Called by the engine when sound settings are updated
+ */
virtual void syncSoundSettings();
- virtual bool getIsDemo() const;
+ /**
+ * Returns whether the version is a demo
+ */
+ virtual bool isDemo() const;
+
+ /**
+ * Returns the Id of the game
+ */
GameType getGameID() const;
- Common::Language getLanguage() const;
- Common::Platform getPlatform() const;
- Common::String getGameFile(int fileType);
+ /**
+ * Returns the platform the game's datafiles are for
+ */
+ Common::Platform getPlatform() const;
+ /**
+ * Return a random number
+ */
int getRandomNumber(int limit) { return _randomSource.getRandomNumber(limit - 1); }
+ /**
+ * Read the state of a global flag
+ * @remarks If a negative value is specified, it will return the inverse value
+ * of the positive flag number
+ */
bool readFlags(int flagNum);
+ /**
+ * Sets a global flag to either true or false depending on whether the specified
+ * flag is positive or negative
+ */
void setFlags(int flagNum);
+ /**
+ * Saves game configuration information
+ */
void saveConfig();
+ /**
+ * Synchronize the data for a savegame
+ */
void synchronize(Common::Serializer &s);
};
diff --git a/engines/sherlock/sound.cpp b/engines/sherlock/sound.cpp
index 3a308644a8..06f6a0f264 100644
--- a/engines/sherlock/sound.cpp
+++ b/engines/sherlock/sound.cpp
@@ -30,11 +30,30 @@
namespace Sherlock {
-Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer): _vm(vm), _mixer(mixer) {
+static const int8 creativeADPCM_ScaleMap[64] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7,
+ 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15,
+ 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30,
+ 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60
+};
+
+static const uint8 creativeADPCM_AdjustMap[64] = {
+ 0, 0, 0, 0, 0, 16, 16, 16,
+ 0, 0, 0, 0, 0, 16, 16, 16,
+ 240, 0, 0, 0, 0, 16, 16, 16,
+ 240, 0, 0, 0, 0, 16, 16, 16,
+ 240, 0, 0, 0, 0, 16, 16, 16,
+ 240, 0, 0, 0, 0, 16, 16, 16,
+ 240, 0, 0, 0, 0, 0, 0, 0,
+ 240, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*----------------------------------------------------------------*/
+
+Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
_digitized = false;
_music = false;
_voices = 0;
- _playingEpilogue = false;
_diskSoundPlaying = false;
_soundPlaying = false;
_soundIsOn = &_soundPlaying;
@@ -45,11 +64,19 @@ Sound::Sound(SherlockEngine *vm, Audio::Mixer *mixer): _vm(vm), _mixer(mixer) {
_speechOn = true;
_vm->_res->addToCache("MUSIC.LIB");
+ if (!_vm->_interactiveFl)
+ _vm->_res->addToCache("TITLE.SND");
+ else {
+ _vm->_res->addToCache("MUSIC.LIB");
+ _vm->_res->addToCache("SND.SND");
+
+ if (!_vm->isDemo()) {
+ _vm->_res->addToCache("TITLE.SND");
+ _vm->_res->addToCache("EPILOGUE.SND");
+ }
+ }
}
-/**
- * Saves sound-related settings
- */
void Sound::syncSoundSettings() {
_digitized = !ConfMan.getBool("mute");
_music = !ConfMan.getBool("mute") && !ConfMan.getBool("music_mute");
@@ -58,41 +85,41 @@ void Sound::syncSoundSettings() {
void Sound::loadSound(const Common::String &name, int priority) {
// No implementation required in ScummVM
+ warning("loadSound");
}
-char Sound::decodeSample(char sample, byte& prediction, int& step) {
- char diff = ((sample & 0x07) << step);
-
- if (sample & 0x08) {
- if (prediction > diff)
- prediction = prediction - ((sample & 0x07) << step);
- else
- prediction = 0;
- } else {
- if (prediction < 0xff - diff)
- prediction = prediction + ((sample&0x07) << step);
- else
- prediction = 0xff;
- }
+byte Sound::decodeSample(byte sample, byte &reference, int16 &scale) {
+ int16 samp = sample + scale;
+ int16 ref = 0;
+ // clip bad ADPCM-4 sample
+ samp = CLIP<int16>(samp, 0, 63);
- if ((sample & 0x07) >= 5 && step < 3) {
- step ++;
- } else if ((sample & 0x07) == 0 && step > 0) {
- step --;
+ ref = reference + creativeADPCM_ScaleMap[samp];
+ if (ref > 0xff) {
+ reference = 0xff;
+ } else {
+ if (ref < 0x00) {
+ reference = 0;
+ } else {
+ reference = (uint8)(ref & 0xff);
+ }
}
- return prediction;
+ scale = (scale + creativeADPCM_AdjustMap[samp]) & 0xff;
+ return reference;
}
-bool Sound::playSound(const Common::String &name, WaitType waitType, int priority) {
+bool Sound::playSound(const Common::String &name, WaitType waitType, int priority, const char *libraryFilename) {
+ Resources &res = *_vm->_res;
stopSound();
Common::String filename = name;
if (!filename.contains('.'))
filename += ".SND";
-
- Common::SeekableReadStream *stream = _vm->_res->load(filename);
+
+ Common::String libFilename(libraryFilename);
+ Common::SeekableReadStream *stream = libFilename.empty() ? res.load(filename) : res.load(filename, libFilename);
if (!stream)
error("Unable to find sound file '%s'", filename.c_str());
@@ -104,16 +131,18 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit
byte *ptr = data;
stream->read(ptr, size);
+ assert(size > 2);
+
byte *decoded = (byte *)malloc((size - 1) * 2);
- // +127 to eliminate the pop when the sound starts (signed vs unsigned PCM). Still does not help with the pop at the end
- byte prediction = (ptr[0] & 0x0f) + 127;
- int step = 0;
+ // Holmes uses Creative ADPCM 4-bit data
int counter = 0;
+ byte reference = ptr[0];
+ int16 scale = 0;
for(int i = 1; i < size; i++) {
- decoded[counter++] = decodeSample((ptr[i]>>4)&0x0f, prediction, step);
- decoded[counter++] = decodeSample((ptr[i]>>0)&0x0f, prediction, step);
+ decoded[counter++] = decodeSample((ptr[i]>>4)&0x0f, reference, scale);
+ decoded[counter++] = decodeSample((ptr[i]>>0)&0x0f, reference, scale);
}
free(data);
@@ -146,7 +175,7 @@ bool Sound::playSound(const Common::String &name, WaitType waitType, int priorit
break;
}
} while (!_vm->shouldQuit() && _mixer->isSoundHandleActive(_effectsHandle));
-
+
_soundPlaying = false;
_mixer->stopHandle(_effectsHandle);
@@ -231,3 +260,4 @@ void Sound::freeDigiSound() {
}
} // End of namespace Sherlock
+
diff --git a/engines/sherlock/sound.h b/engines/sherlock/sound.h
index 659df57bc3..689e615a36 100644
--- a/engines/sherlock/sound.h
+++ b/engines/sherlock/sound.h
@@ -46,7 +46,7 @@ private:
Audio::SoundHandle _effectsHandle;
int _curPriority;
- char decodeSample(char sample, byte& prediction, int& step);
+ byte decodeSample(byte sample, byte& reference, int16& scale);
public:
bool _digitized;
bool _music;
@@ -54,7 +54,6 @@ public:
bool _soundOn;
bool _musicOn;
bool _speechOn;
- bool _playingEpilogue;
bool _diskSoundPlaying;
bool _soundPlaying;
bool *_soundIsOn;
@@ -62,19 +61,61 @@ public:
public:
Sound(SherlockEngine *vm, Audio::Mixer *mixer);
+ /**
+ * Saves sound-related settings
+ */
void syncSoundSettings();
+
+ /**
+ * Load a sound
+ */
void loadSound(const Common::String &name, int priority);
- bool playSound(const Common::String &name, WaitType waitType, int priority = 100);
+
+ /**
+ * Play the sound in the specified resource
+ */
+ bool playSound(const Common::String &name, WaitType waitType, int priority = 100, const char *libraryFilename = nullptr);
+
+ /**
+ * Play a previously loaded sound
+ */
void playLoadedSound(int bufNum, WaitType waitType);
+
+ /**
+ * Free any previously loaded sounds
+ */
void freeLoadedSounds();
+
+ /**
+ * Stop playing any active sound
+ */
void stopSound();
+ /**
+ * Load a specified song
+ */
int loadSong(int songNumber);
+
+ /**
+ * Start playing a song
+ */
void startSong();
+
+ /**
+ * Free any currently loaded song
+ */
void freeSong();
+ /**
+ * Play the specified music resource
+ */
void playMusic(const Common::String &name);
+
+ /**
+ * Stop playing the music
+ */
void stopMusic();
+
void stopSndFuncPtr(int v1, int v2);
void waitTimerRoland(uint time);
void freeDigiSound();
@@ -83,3 +124,4 @@ public:
} // End of namespace Sherlock
#endif
+
diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp
index 36e625794c..80495a398c 100644
--- a/engines/sherlock/surface.cpp
+++ b/engines/sherlock/surface.cpp
@@ -22,12 +22,13 @@
#include "sherlock/surface.h"
#include "sherlock/sherlock.h"
+#include "sherlock/resources.h"
#include "common/system.h"
#include "graphics/palette.h"
namespace Sherlock {
-Surface::Surface(uint16 width, uint16 height): _freePixels(true) {
+Surface::Surface(uint16 width, uint16 height) : _freePixels(true) {
create(width, height);
}
@@ -36,61 +37,65 @@ Surface::Surface() : _freePixels(false) {
Surface::~Surface() {
if (_freePixels)
- free();
+ _surface.free();
}
-/**
- * Sets up an internal surface with the specified dimensions that will be automatically freed
- * when the surface object is destroyed
- */
void Surface::create(uint16 width, uint16 height) {
if (_freePixels)
- free();
+ _surface.free();
- Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+ _surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
_freePixels = true;
}
-/**
- * Copy a surface into this one
- */
+void Surface::blitFrom(const Surface &src) {
+ blitFrom(src, Common::Point(0, 0));
+}
+
+void Surface::blitFrom(const ImageFrame &src) {
+ blitFrom(src._frame, Common::Point(0, 0));
+}
+
void Surface::blitFrom(const Graphics::Surface &src) {
blitFrom(src, Common::Point(0, 0));
}
-/**
- * Draws a surface at a given position within this surface
- */
+void Surface::blitFrom(const Surface &src, const Common::Point &pt) {
+ blitFrom(src, pt, Common::Rect(0, 0, src._surface.w, src._surface.h));
+}
+
+void Surface::blitFrom(const ImageFrame &src, const Common::Point &pt) {
+ blitFrom(src._frame, pt, Common::Rect(0, 0, src._frame.w, src._frame.h));
+}
+
void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt) {
blitFrom(src, pt, Common::Rect(0, 0, src.w, src.h));
}
-/**
- * Draws a sub-section of a surface at a given position within this surface
- */
-void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt,
- const Common::Rect &srcBounds) {
+void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
Common::Rect srcRect = srcBounds;
Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());
if (srcRect.isValidRect() && clip(srcRect, destRect)) {
// Surface is at least partially or completely on-screen
addDirtyRect(destRect);
- copyRectToSurface(src, destRect.left, destRect.top, srcRect);
+ _surface.copyRectToSurface(src, destRect.left, destRect.top, srcRect);
}
}
-/**
-* Draws an image frame at a given position within this surface with transparency
-*/
+void Surface::blitFrom(const ImageFrame &src, const Common::Point &pt, const Common::Rect &srcBounds) {
+ blitFrom(src._frame, pt, srcBounds);
+}
+
+void Surface::blitFrom(const Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
+ blitFrom(src._surface, pt, srcBounds);
+}
+
void Surface::transBlitFrom(const ImageFrame &src, const Common::Point &pt,
bool flipped, int overrideColor) {
transBlitFrom(src._frame, pt + src._offset, flipped, overrideColor);
}
-/**
-* Draws a surface at a given position within this surface with transparency
-*/
void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
bool flipped, int overrideColor) {
Common::Rect drawRect(0, 0, src.w, src.h);
@@ -125,38 +130,29 @@ void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &p
}
}
-/**
- * Fill a given area of the surface with a given color
- */
void Surface::fillRect(int x1, int y1, int x2, int y2, byte color) {
fillRect(Common::Rect(x1, y1, x2, y2), color);
}
-/**
- * Fill a given area of the surface with a given color
- */
void Surface::fillRect(const Common::Rect &r, byte color) {
- Graphics::Surface::fillRect(r, color);
+ _surface.fillRect(r, color);
addDirtyRect(r);
}
-/**
- * Clips the given source bounds so the passed destBounds will be entirely on-screen
- */
bool Surface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) {
- if (destBounds.left >= this->w || destBounds.top >= this->h ||
- destBounds.right <= 0 || destBounds.bottom <= 0)
+ if (destBounds.left >= _surface.w || destBounds.top >= _surface.h ||
+ destBounds.right <= 0 || destBounds.bottom <= 0)
return false;
// Clip the bounds if necessary to fit on-screen
- if (destBounds.right > this->w) {
- srcBounds.right -= destBounds.right - this->w;
- destBounds.right = this->w;
+ if (destBounds.right > _surface.w) {
+ srcBounds.right -= destBounds.right - _surface.w;
+ destBounds.right = _surface.w;
}
- if (destBounds.bottom > this->h) {
- srcBounds.bottom -= destBounds.bottom - this->h;
- destBounds.bottom = this->h;
+ if (destBounds.bottom > _surface.h) {
+ srcBounds.bottom -= destBounds.bottom - _surface.h;
+ destBounds.bottom = _surface.h;
}
if (destBounds.top < 0) {
@@ -172,11 +168,22 @@ bool Surface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) {
return true;
}
-/**
- * Clear the screen
- */
void Surface::clear() {
- fillRect(Common::Rect(0, 0, this->w, this->h), 0);
+ fillRect(Common::Rect(0, 0, _surface.w, _surface.h), 0);
+}
+
+void Surface::free() {
+ if (_freePixels) {
+ _surface.free();
+ _freePixels = false;
+ }
+}
+
+void Surface::setPixels(byte *pixels, int width, int height) {
+ _surface.format = Graphics::PixelFormat::createFormatCLUT8();
+ _surface.w = _surface.pitch = width;
+ _surface.h = height;
+ _surface.setPixels(pixels);
}
} // End of namespace Sherlock
diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h
index b2a759aa8d..ccabf02a23 100644
--- a/engines/sherlock/surface.h
+++ b/engines/sherlock/surface.h
@@ -25,36 +25,130 @@
#include "common/rect.h"
#include "graphics/surface.h"
-#include "sherlock/resources.h"
namespace Sherlock {
-class Surface : public Graphics::Surface {
+struct ImageFrame;
+
+class Surface {
private:
bool _freePixels;
+ /**
+ * Clips the given source bounds so the passed destBounds will be entirely on-screen
+ */
bool clip(Common::Rect &srcBounds, Common::Rect &destBounds);
+
+ /**
+ * Copy a surface into this one
+ */
+ void blitFrom(const Graphics::Surface &src);
+
+ /**
+ * Draws a surface at a given position within this surface
+ */
+ void blitFrom(const Graphics::Surface &src, const Common::Point &pt);
+
+ /**
+ * Draws a sub-section of a surface at a given position within this surface
+ */
+ void blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
protected:
+ Graphics::Surface _surface;
+
virtual void addDirtyRect(const Common::Rect &r) {}
public:
Surface(uint16 width, uint16 height);
Surface();
virtual ~Surface();
+ /**
+ * Sets up an internal surface with the specified dimensions that will be automatically freed
+ * when the surface object is destroyed
+ */
void create(uint16 width, uint16 height);
- void blitFrom(const Graphics::Surface &src);
- void blitFrom(const Graphics::Surface &src, const Common::Point &pt);
- void blitFrom(const Graphics::Surface &src, const Common::Point &pt,
- const Common::Rect &srcBounds);
+
+ /**
+ * Copy a surface into this one
+ */
+ void blitFrom(const Surface &src);
+
+ /**
+ * Copy an image frame into this surface
+ */
+ void blitFrom(const ImageFrame &src);
+
+ /**
+ * Draws a surface at a given position within this surface
+ */
+ void blitFrom(const Surface &src, const Common::Point &pt);
+
+ /**
+ * Copy an image frame onto this surface at a given position
+ */
+ void blitFrom(const ImageFrame &src, const Common::Point &pt);
+
+ /**
+ * Draws a sub-section of a surface at a given position within this surface
+ */
+ void blitFrom(const Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
+
+ /**
+ * Copy a sub-area of a source image frame into this surface at a given position
+ */
+ void blitFrom(const ImageFrame &src, const Common::Point &pt, const Common::Rect &srcBounds);
+
+ /**
+ * Draws an image frame at a given position within this surface with transparency
+ */
void transBlitFrom(const ImageFrame &src, const Common::Point &pt,
bool flipped = false, int overrideColor = 0);
+
+ /**
+ * Draws a surface at a given position within this surface with transparency
+ */
+ void transBlitFrom(const Surface &src, const Common::Point &pt,
+ bool flipped = false, int overrideColor = 0);
+
+ /**
+ * Draws a surface at a given position within this surface with transparency
+ */
void transBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
bool flipped = false, int overrideColor = 0);
+ /**
+ * Fill a given area of the surface with a given color
+ */
void fillRect(int x1, int y1, int x2, int y2, byte color);
+
+ /**
+ * Fill a given area of the surface with a given color
+ */
void fillRect(const Common::Rect &r, byte color);
+ /**
+ * Clear the screen
+ */
void clear();
+
+ /**
+ * Free the underlying surface
+ */
+ void free();
+
+ /**
+ * Set the pixels for the surface to an existing data block
+ */
+ void setPixels(byte *pixels, int width, int height);
+
+ inline uint16 w() const { return _surface.w; }
+ inline uint16 h() const { return _surface.h; }
+ inline const byte *getPixels() const { return (const byte *)_surface.getPixels(); }
+ inline byte *getPixels() { return (byte *)_surface.getPixels(); }
+ inline byte *getBasePtr(int x, int y) { return (byte *)_surface.getBasePtr(x, y); }
+ inline const byte *getBasePtr(int x, int y) const { return (const byte *)_surface.getBasePtr(x, y); }
+ inline void hLine(int x, int y, int x2, uint32 color) { _surface.hLine(x, y, x2, color); }
+ inline void vLine(int x, int y, int y2, uint32 color) { _surface.vLine(x, y, y2, color); }
};
} // End of namespace Sherlock
diff --git a/engines/sherlock/talk.cpp b/engines/sherlock/talk.cpp
index c67b98b35e..1a926a543d 100644
--- a/engines/sherlock/talk.cpp
+++ b/engines/sherlock/talk.cpp
@@ -26,6 +26,8 @@
namespace Sherlock {
+#define SPEAKER_REMOVE 0x80
+
SequenceEntry::SequenceEntry() {
_objNum = 0;
_frameNumber = 0;
@@ -34,9 +36,6 @@ SequenceEntry::SequenceEntry() {
/*----------------------------------------------------------------*/
-/**
- * Load the data for a single statement within a talk file
- */
void Statement::synchronize(Common::SeekableReadStream &s) {
int length;
@@ -91,7 +90,7 @@ void TalkSequences::clear() {
/*----------------------------------------------------------------*/
-Talk::Talk(SherlockEngine *vm): _vm(vm) {
+Talk::Talk(SherlockEngine *vm) : _vm(vm) {
_talkCounter = 0;
_talkToAbort = false;
_speaker = 0;
@@ -106,26 +105,6 @@ Talk::Talk(SherlockEngine *vm): _vm(vm) {
_scriptSaveIndex = -1;
}
-/**
- * Sets talk sequences
- */
-void Talk::setSequences(const byte *talkSequences, const byte *stillSequences, int maxPeople) {
- for (int idx = 0; idx < maxPeople; ++idx) {
- STILL_SEQUENCES.push_back(TalkSequences(stillSequences));
- TALK_SEQUENCES.push_back(TalkSequences(talkSequences));
- stillSequences += MAX_TALK_SEQUENCES;
- talkSequences += MAX_TALK_SEQUENCES;
- }
-}
-
-/**
- * Called whenever a conversation or item script needs to be run. For standard conversations,
- * it opens up a description window similar to how 'talk' does, but shows a 'reply' directly
- * instead of waiting for a statement option.
- * @remarks It seems that at some point, all item scripts were set up to use this as well.
- * In their case, the conversation display is simply suppressed, and control is passed on to
- * doScript to implement whatever action is required.
- */
void Talk::talkTo(const Common::String &filename) {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -158,7 +137,7 @@ void Talk::talkTo(const Common::String &filename) {
}
// Save the ui mode temporarily and switch to talk mode
- int savedMode = ui._menuMode;
+ MenuMode savedMode = ui._menuMode;
ui._menuMode = TALK_MODE;
// Turn on the Exit option
@@ -196,7 +175,7 @@ void Talk::talkTo(const Common::String &filename) {
if (IS_SERRATED_SCALPEL) {
// Restore any pressed button
if (!ui._windowOpen && savedMode != STD_MODE)
- ((ScalpelUserInterface *)_vm->_ui)->restoreButton(savedMode - 1);
+ ((ScalpelUserInterface *)_vm->_ui)->restoreButton((int)(savedMode - 1));
}
// Clear the ui counter so that anything displayed on the info line
@@ -223,7 +202,7 @@ void Talk::talkTo(const Common::String &filename) {
break;
case TALK_MODE:
- if (_speaker < 128)
+ if (_speaker < SPEAKER_REMOVE)
people.clearTalking();
if (_talkCounter)
return;
@@ -272,6 +251,9 @@ void Talk::talkTo(const Common::String &filename) {
events._pressed = events._released = events._oldButtons = 0;
abortFlag = true;
break;
+
+ default:
+ break;
}
}
@@ -387,7 +369,7 @@ void Talk::talkTo(const Common::String &filename) {
} else {
screen.buttonPrint(Common::Point(119, CONTROLS_Y), color, false, "Exit");
- if (!ui._windowStyle) {
+ if (!ui._slideWindows) {
screen.slamRect(Common::Rect(0, CONTROLS_Y,
SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
} else {
@@ -450,12 +432,6 @@ void Talk::talkTo(const Common::String &filename) {
events.setCursor(ARROW);
}
-/**
- * Main method for handling conversations when a character to talk to has been
- * selected. It will make Holmes walk to the person to talk to, draws the
- * interface window for the conversation and passes on control to give the
- * player a list of options to make a selection from
- */
void Talk::talk(int objNum) {
Events &events = *_vm->_events;
People &people = *_vm->_people;
@@ -466,7 +442,7 @@ void Talk::talk(int objNum) {
ui._windowBounds.top = CONTROLS_Y;
ui._infoFlag = true;
- _speaker = 128;
+ _speaker = SPEAKER_REMOVE;
loadTalkFile(scene._bgShapes[objNum]._name);
// Find the first statement with the correct flags
@@ -534,7 +510,7 @@ void Talk::talk(int objNum) {
displayTalk(false);
ui._selector = ui._oldSelector = -1;
- if (!ui._windowStyle) {
+ if (!ui._slideWindows) {
screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH,
SHERLOCK_SCREEN_HEIGHT));
} else {
@@ -549,18 +525,12 @@ void Talk::talk(int objNum) {
}
}
-/**
- * Clear loaded talk data
- */
void Talk::freeTalkVars() {
_statements.clear();
}
-/**
- * Opens the talk file 'talk.tlk' and searches the index for the specified
- * conversation. If found, the data for that conversation is loaded
- */
void Talk::loadTalkFile(const Common::String &filename) {
+ People &people = *_vm->_people;
Resources &res = *_vm->_res;
Sound &sound = *_vm->_sound;
@@ -569,8 +539,8 @@ void Talk::loadTalkFile(const Common::String &filename) {
// Check for an existing person being talked to
_talkTo = -1;
- for (int idx = 0; idx < MAX_PEOPLE; ++idx) {
- if (!scumm_strnicmp(filename.c_str(), PORTRAITS[idx], 4)) {
+ for (int idx = 0; idx < (int)people._characters.size(); ++idx) {
+ if (!scumm_strnicmp(filename.c_str(), people._characters[idx]._portrait, 4)) {
_talkTo = idx;
break;
}
@@ -596,9 +566,6 @@ void Talk::loadTalkFile(const Common::String &filename) {
setTalkMap();
}
-/**
- * Remove any voice commands from a loaded statement list
- */
void Talk::stripVoiceCommands() {
for (uint sIdx = 0; sIdx < _statements.size(); ++sIdx) {
Statement &statement = _statements[sIdx];
@@ -622,9 +589,6 @@ void Talk::stripVoiceCommands() {
}
}
-/**
- * Form a table of the display indexes for statements
- */
void Talk::setTalkMap() {
int statementNum = 0;
@@ -642,9 +606,6 @@ void Talk::setTalkMap() {
}
}
-/**
- * Draws the interface for conversation display
- */
void Talk::drawInterface() {
Screen &screen = *_vm->_screen;
Surface &bb = *screen._backBuffer;
@@ -673,10 +634,6 @@ void Talk::drawInterface() {
}
}
-/**
- * Display a list of statements in a window at the bottom of the scren that the
- * player can select from.
- */
bool Talk::displayTalk(bool slamIt) {
Screen &screen = *_vm->_screen;
int yp = CONTROLS_Y + 14;
@@ -761,9 +718,6 @@ bool Talk::displayTalk(bool slamIt) {
return done;
}
-/**
- * Prints a single conversation option in the interface window
- */
int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt) {
Screen &screen = *_vm->_screen;
int idx = lineNum;
@@ -771,11 +725,11 @@ int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt
bool numberFlag = false;
// Get the statement to display as well as optional number prefix
- if (idx < 128) {
+ if (idx < SPEAKER_REMOVE) {
number = Common::String::format("%d.", stateNum + 1);
numberFlag = true;
} else {
- idx -= 128;
+ idx -= SPEAKER_REMOVE;
}
msg = _statements[idx]._statement;
@@ -812,23 +766,23 @@ int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt
// Are we drawing the first line?
if (lineStartP == msg.c_str()) {
// We are, so print the number and then the text
- screen.print(Common::Point(16, lineY), color, number.c_str());
+ screen.print(Common::Point(16, lineY), color, "%s", number.c_str());
}
// Draw the line with an indent
- screen.print(Common::Point(30, lineY), color, sLine.c_str());
+ screen.print(Common::Point(30, lineY), color, "%s", sLine.c_str());
} else {
- screen.print(Common::Point(16, lineY), color, sLine.c_str());
+ screen.print(Common::Point(16, lineY), color, "%s", sLine.c_str());
}
} else {
if (numberFlag) {
if (lineStartP == msg.c_str()) {
- screen.gPrint(Common::Point(16, lineY - 1), color, number.c_str());
+ screen.gPrint(Common::Point(16, lineY - 1), color, "%s", number.c_str());
}
- screen.gPrint(Common::Point(30, lineY - 1), color, sLine.c_str());
+ screen.gPrint(Common::Point(30, lineY - 1), color, "%s", sLine.c_str());
} else {
- screen.gPrint(Common::Point(16, lineY - 1), color, sLine.c_str());
+ screen.gPrint(Common::Point(16, lineY - 1), color, "%s", sLine.c_str());
}
}
@@ -852,17 +806,10 @@ int Talk::talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt
return lineY;
}
-/**
- * Clears the stack of pending object sequences associated with speakers in the scene
- */
void Talk::clearSequences() {
_sequenceStack.clear();
}
-/**
- * Pulls a background object sequence from the sequence stack and restore's the
- * object's sequence
- */
void Talk::pullSequence() {
Scene &scene = *_vm->_scene;
@@ -885,10 +832,6 @@ void Talk::pullSequence() {
}
}
-/**
- * Push the sequence of a background object that's an NPC that needs to be
- * saved onto the sequence stack.
- */
void Talk::pushSequence(int speaker) {
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
@@ -918,9 +861,6 @@ void Talk::pushSequence(int speaker) {
error("script stack overflow");
}
-/**
- * Change the sequence of the scene background object associated with the current speaker.
- */
void Talk::setSequence(int speaker) {
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
@@ -938,8 +878,8 @@ void Talk::setSequence(int speaker) {
warning("Tried to copy too many talk frames");
} else {
for (int idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) {
- obj._sequences[idx] = TALK_SEQUENCES[speaker][idx];
- if (idx > 0 && !TALK_SEQUENCES[speaker][idx] && !TALK_SEQUENCES[speaker][idx - 1])
+ obj._sequences[idx] = people._characters[speaker]._talkSequences[idx];
+ if (idx > 0 && !obj._sequences[idx] && !obj._sequences[idx - 1])
return;
obj._frameNumber = 0;
@@ -950,10 +890,6 @@ void Talk::setSequence(int speaker) {
}
}
-/**
- * Change the sequence of a background object corresponding to a given speaker.
- * The new sequence will display the character as "listening"
- */
void Talk::setStillSeq(int speaker) {
People &people = *_vm->_people;
Scene &scene = *_vm->_scene;
@@ -971,8 +907,9 @@ void Talk::setStillSeq(int speaker) {
warning("Tried to copy too few still frames");
} else {
for (uint idx = 0; idx < MAX_TALK_SEQUENCES; ++idx) {
- obj._sequences[idx] = STILL_SEQUENCES[speaker][idx];
- if (idx > 0 && !TALK_SEQUENCES[speaker][idx] && !TALK_SEQUENCES[speaker][idx - 1])
+ obj._sequences[idx] = people._characters[speaker]._stillSequences[idx];
+ if (idx > 0 && !people._characters[speaker]._talkSequences[idx] &&
+ !people._characters[speaker]._talkSequences[idx - 1])
break;
}
@@ -983,10 +920,6 @@ void Talk::setStillSeq(int speaker) {
}
}
-/**
- * Parses a reply for control codes and display text. The found text is printed within
- * the text window, handles delays, animations, and animating portraits.
- */
void Talk::doScript(const Common::String &script) {
Animation &anim = *_vm->_animation;
Events &events = *_vm->_events;
@@ -1021,7 +954,7 @@ void Talk::doScript(const Common::String &script) {
// Check if the script begins with a Stealh Mode Active command
if (str[0] == STEALTH_MODE_ACTIVE || _talkStealth) {
_talkStealth = 2;
- _speaker |= 128;
+ _speaker |= SPEAKER_REMOVE;
} else {
pushSequence(_speaker);
ui.clearWindow();
@@ -1079,11 +1012,11 @@ void Talk::doScript(const Common::String &script) {
// Start of comment, so skip over it
while (*str++ != '}')
;
- } else if (c >= 128) {
+ } else if (c >= SWITCH_SPEAKER) {
// Handle control code
switch (c) {
case SWITCH_SPEAKER:
- if (!(_speaker & 128))
+ if (!(_speaker & SPEAKER_REMOVE))
people.clearTalking();
if (_talkToAbort)
return;
@@ -1101,7 +1034,7 @@ void Talk::doScript(const Common::String &script) {
case RUN_CANIMATION:
++str;
- scene.startCAnim((str[0] - 1) & 127, (str[0] & 128) ? -1 : 1);
+ scene.startCAnim((str[0] - 1) & 127, (str[0] & 0x80) ? -1 : 1);
if (_talkToAbort)
return;
@@ -1137,13 +1070,13 @@ void Talk::doScript(const Common::String &script) {
break;
case REMOVE_PORTRAIT:
- if (_speaker >= 0 && _speaker < 128)
+ if (_speaker >= 0 && _speaker < SPEAKER_REMOVE)
people.clearTalking();
pullSequence();
if (_talkToAbort)
return;
- _speaker |= 128;
+ _speaker |= SPEAKER_REMOVE;
break;
case CLEAR_WINDOW:
@@ -1162,14 +1095,14 @@ void Talk::doScript(const Common::String &script) {
// Scan for object
int objId = -1;
for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
- if (scumm_stricmp(tempString.c_str(), scene._bgShapes[idx]._name.c_str()) == 0)
+ if (tempString.equalsIgnoreCase(scene._bgShapes[idx]._name))
objId = idx;
}
if (objId == -1)
error("Could not find object %s to change", tempString.c_str());
// Should the script be overwritten?
- if (str[0] > 128) {
+ if (str[0] > 0x80) {
// Save the current sequence
_savedSequences.push(SequenceEntry());
SequenceEntry &seqEntry = _savedSequences.top();
@@ -1218,14 +1151,14 @@ void Talk::doScript(const Common::String &script) {
break;
case BANISH_WINDOW:
- if (!(_speaker & 128))
+ if (!(_speaker & SPEAKER_REMOVE))
people.clearTalking();
pullSequence();
if (_talkToAbort)
return;
- _speaker |= 128;
+ _speaker |= SPEAKER_REMOVE;
ui.banishWindow();
ui._menuMode = TALK_MODE;
noTextYet = true;
@@ -1369,12 +1302,12 @@ void Talk::doScript(const Common::String &script) {
tempString += str[idx + 1];
// Set comparison state according to if we want to hide or unhide
- bool state = (str[0] >= 128);
+ bool state = (str[0] >= SPEAKER_REMOVE);
str += str[0] & 127;
for (uint idx = 0; idx < scene._bgShapes.size(); ++idx) {
Object &object = scene._bgShapes[idx];
- if (scumm_stricmp(tempString.c_str(), object._name.c_str()) == 0) {
+ if (tempString.equalsIgnoreCase(object._name)) {
// Only toggle the object if it's not in the desired state already
if ((object._type == HIDDEN && state) || (object._type != HIDDEN && !state))
object.toggleHidden();
@@ -1429,7 +1362,7 @@ void Talk::doScript(const Common::String &script) {
tempString += str[idx + 1];
str += str[0];
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, tempString.c_str());
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", tempString.c_str());
ui._menuCounter = 30;
break;
@@ -1484,29 +1417,31 @@ void Talk::doScript(const Common::String &script) {
}
// If it's the first line, display the speaker
- if (!line && _speaker >= 0 && _speaker < MAX_PEOPLE) {
+ if (!line && _speaker >= 0 && _speaker < (int)people._characters.size()) {
// If the window is open, display the name directly on-screen.
// Otherwise, simply draw it on the back buffer
if (ui._windowOpen) {
- screen.print(Common::Point(16, yp), TALK_FOREGROUND, NAMES[_speaker & 127]);
+ screen.print(Common::Point(16, yp), TALK_FOREGROUND, "%s",
+ people._characters[_speaker & 127]._name);
} else {
- screen.gPrint(Common::Point(16, yp - 1), TALK_FOREGROUND, NAMES[_speaker & 127]);
+ screen.gPrint(Common::Point(16, yp - 1), TALK_FOREGROUND, "%s",
+ people._characters[_speaker & 127]._name);
openTalkWindow = true;
}
yp += 9;
}
- // Find amound of text that will fit on the line
+ // Find amount of text that will fit on the line
int width = 0, idx = 0;
do {
width += screen.charWidth(str[idx]);
++idx;
++charCount;
- } while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < 128);
+ } while (width < 298 && str[idx] && str[idx] != '{' && str[idx] < SWITCH_SPEAKER);
if (str[idx] || width >= 298) {
- if (str[idx] < 128 && str[idx] != '{') {
+ if (str[idx] < SWITCH_SPEAKER && str[idx] != '{') {
--idx;
--charCount;
}
@@ -1528,16 +1463,16 @@ void Talk::doScript(const Common::String &script) {
// If the speaker indicates a description file, print it in yellow
if (_speaker != -1) {
if (ui._windowOpen) {
- screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, lineStr.c_str());
+ screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, "%s", lineStr.c_str());
} else {
- screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, lineStr.c_str());
+ screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, "%s", lineStr.c_str());
openTalkWindow = true;
}
} else {
if (ui._windowOpen) {
- screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, lineStr.c_str());
+ screen.print(Common::Point(16, yp), COMMAND_FOREGROUND, "%s", lineStr.c_str());
} else {
- screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, lineStr.c_str());
+ screen.gPrint(Common::Point(16, yp - 1), COMMAND_FOREGROUND, "%s", lineStr.c_str());
openTalkWindow = true;
}
}
@@ -1546,7 +1481,7 @@ void Talk::doScript(const Common::String &script) {
str += idx;
// If line wrap occurred, then move to after the separating space between the words
- if (str[0] < 128 && str[0] != '{')
+ if (str[0] < SWITCH_SPEAKER && str[0] != '{')
++str;
yp += 9;
@@ -1576,8 +1511,8 @@ void Talk::doScript(const Common::String &script) {
}
// Open window if it wasn't already open, and text has already been printed
- if ((openTalkWindow && wait) || (openTalkWindow && str[0] >= 128 && str[0] != CARRIAGE_RETURN)) {
- if (!ui._windowStyle) {
+ if ((openTalkWindow && wait) || (openTalkWindow && str[0] >= SWITCH_SPEAKER && str[0] != CARRIAGE_RETURN)) {
+ if (!ui._slideWindows) {
screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
} else {
ui.summonWindow();
@@ -1626,15 +1561,11 @@ void Talk::doScript(const Common::String &script) {
}
pullSequence();
- if (_speaker >= 0 && _speaker < 128)
+ if (_speaker >= 0 && _speaker < SPEAKER_REMOVE)
people.clearTalking();
}
}
-/**
- * When the talk window has been displayed, waits a period of time proportional to
- * the amount of text that's been displayed
- */
int Talk::waitForMore(int delay) {
Events &events = *_vm->_events;
People &people = *_vm->_people;
@@ -1665,7 +1596,7 @@ int Talk::waitForMore(int delay) {
if (events.kbHit()) {
Common::KeyState keyState = events.getKey();
- if (keyState.keycode >= 32 && keyState.keycode < 128)
+ if (Common::isPrint(keyState.ascii))
key2 = keyState.keycode;
}
@@ -1714,9 +1645,6 @@ int Talk::waitForMore(int delay) {
return key2;
}
-/**
- * Pops an entry off of the script stack
- */
void Talk::popStack() {
if (!_scriptStack.empty()) {
ScriptStackEntry scriptEntry = _scriptStack.pop();
@@ -1727,9 +1655,6 @@ void Talk::popStack() {
}
}
-/**
- * Synchronize the data for a savegame
- */
void Talk::synchronize(Common::Serializer &s) {
for (int idx = 0; idx < MAX_TALK_FILES; ++idx) {
TalkHistoryEntry &he = _talkHistory[idx];
diff --git a/engines/sherlock/talk.h b/engines/sherlock/talk.h
index 5c87d793f3..48290e965e 100644
--- a/engines/sherlock/talk.h
+++ b/engines/sherlock/talk.h
@@ -99,6 +99,9 @@ struct Statement {
int _talkMap;
Common::Rect _talkPos;
+ /**
+ * Load the data for a single statement within a talk file
+ */
void synchronize(Common::SeekableReadStream &s);
};
@@ -125,9 +128,6 @@ class ScalpelUserInterface;
class Talk {
friend class ScalpelUserInterface;
private:
- Common::Array<TalkSequences> STILL_SEQUENCES;
- Common::Array<TalkSequences> TALK_SEQUENCES;
-private:
SherlockEngine *_vm;
Common::Stack<SequenceEntry> _savedSequences;
Common::Stack<SequenceEntry> _sequenceStack;
@@ -141,15 +141,37 @@ private:
int _talkToFlag;
int _scriptSaveIndex;
private:
+ /**
+ * Remove any voice commands from a loaded statement list
+ */
void stripVoiceCommands();
+
+ /**
+ * Form a table of the display indexes for statements
+ */
void setTalkMap();
+ /**
+ * Display a list of statements in a window at the bottom of the screen that the
+ * player can select from.
+ */
bool displayTalk(bool slamIt);
+ /**
+ * Prints a single conversation option in the interface window
+ */
int talkLine(int lineNum, int stateNum, byte color, int lineY, bool slamIt);
+ /**
+ * Parses a reply for control codes and display text. The found text is printed within
+ * the text window, handles delays, animations, and animating portraits.
+ */
void doScript(const Common::String &script);
+ /**
+ * When the talk window has been displayed, waits a period of time proportional to
+ * the amount of text that's been displayed
+ */
int waitForMore(int delay);
public:
bool _talkToAbort;
@@ -161,30 +183,87 @@ public:
int _converseNum;
public:
Talk(SherlockEngine *vm);
- void setSequences(const byte *talkSequences, const byte *stillSequences,
- int maxPeople);
+ /**
+ * Return a given talk statement
+ */
Statement &operator[](int idx) { return _statements[idx]; }
+ /**
+ * Called whenever a conversation or item script needs to be run. For standard conversations,
+ * it opens up a description window similar to how 'talk' does, but shows a 'reply' directly
+ * instead of waiting for a statement option.
+ * @remarks It seems that at some point, all item scripts were set up to use this as well.
+ * In their case, the conversation display is simply suppressed, and control is passed on to
+ * doScript to implement whatever action is required.
+ */
void talkTo(const Common::String &filename);
+ /**
+ * Main method for handling conversations when a character to talk to has been
+ * selected. It will make Holmes walk to the person to talk to, draws the
+ * interface window for the conversation and passes on control to give the
+ * player a list of options to make a selection from
+ */
void talk(int objNum);
+ /**
+ * Clear loaded talk data
+ */
void freeTalkVars();
+ /**
+ * Draws the interface for conversation display
+ */
void drawInterface();
+ /**
+ * Opens the talk file 'talk.tlk' and searches the index for the specified
+ * conversation. If found, the data for that conversation is loaded
+ */
void loadTalkFile(const Common::String &filename);
+ /**
+ * Change the sequence of a background object corresponding to a given speaker.
+ * The new sequence will display the character as "listening"
+ */
void setStillSeq(int speaker);
+
+ /**
+ * Clears the stack of pending object sequences associated with speakers in the scene
+ */
void clearSequences();
+
+ /**
+ * Pulls a background object sequence from the sequence stack and restore's the
+ * object's sequence
+ */
void pullSequence();
+
+ /**
+ * Push the sequence of a background object that's an NPC that needs to be
+ * saved onto the sequence stack.
+ */
void pushSequence(int speaker);
+
+ /**
+ * Change the sequence of the scene background object associated with the current speaker.
+ */
void setSequence(int speaker);
+
+ /**
+ * Returns true if the script stack is empty
+ */
bool isSequencesEmpty() const { return _scriptStack.empty(); }
+ /**
+ * Pops an entry off of the script stack
+ */
void popStack();
+ /**
+ * Synchronize the data for a savegame
+ */
void synchronize(Common::Serializer &s);
};
diff --git a/engines/sherlock/user_interface.cpp b/engines/sherlock/user_interface.cpp
index efe6c8ef59..7a6722a218 100644
--- a/engines/sherlock/user_interface.cpp
+++ b/engines/sherlock/user_interface.cpp
@@ -94,11 +94,12 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) {
_windowOpen = false;
_endKeyActive = true;
_invLookFlag = 0;
- _windowStyle = 1; // Sliding windows
+ _slideWindows = true;
_helpStyle = false;
+ _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1, SHERLOCK_SCREEN_HEIGHT - 1);
_lookScriptFlag = false;
- _key = _oldKey = 0;
+ _key = _oldKey = '\0';
_selector = _oldSelector = -1;
_temp = _oldTemp = 0;
_temp1 = 0;
@@ -110,16 +111,17 @@ UserInterface::UserInterface(SherlockEngine *vm) : _vm(vm) {
ScalpelUserInterface::ScalpelUserInterface(SherlockEngine *vm): UserInterface(vm) {
_controls = new ImageFile("menu.all");
_controlPanel = new ImageFile("controls.vgs");
+ _keyPress = '\0';
+ _lookHelp = 0;
_bgFound = 0;
_oldBgFound = -1;
- _keycode = Common::KEYCODE_INVALID;
_help = _oldHelp = 0;
- _oldLook = false;
+ _key = _oldKey = '\0';
+ _temp = _oldTemp = 0;
+ _oldLook = 0;
_keyboardInput = false;
_pause = false;
_cNum = 0;
- _windowBounds = Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH - 1,
- SHERLOCK_SCREEN_HEIGHT - 1);
_find = 0;
_oldUse = 0;
}
@@ -129,18 +131,12 @@ ScalpelUserInterface::~ScalpelUserInterface() {
delete _controlPanel;
}
-/**
- * Resets the user interface
- */
void ScalpelUserInterface::reset() {
_oldKey = -1;
_help = _oldHelp = -1;
_oldTemp = _temp = -1;
}
-/**
- * Draw the user interface onto the screen's back buffers
- */
void ScalpelUserInterface::drawInterface(int bufferNum) {
Screen &screen = *_vm->_screen;
@@ -152,9 +148,6 @@ void ScalpelUserInterface::drawInterface(int bufferNum) {
screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
}
-/**
- * Main input handler for the user interface
- */
void ScalpelUserInterface::handleInput() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -168,13 +161,13 @@ void ScalpelUserInterface::handleInput() {
Common::Point pt = events.mousePos();
_bgFound = scene.findBgShape(Common::Rect(pt.x, pt.y, pt.x + 1, pt.y + 1));
- _keycode = Common::KEYCODE_INVALID;
+ _keyPress = '\0';
// Check kbd and set the mouse released flag if Enter or space is pressed.
// Otherwise, the pressed _key is stored for later use
if (events.kbHit()) {
Common::KeyState keyState = events.getKey();
- _keycode = keyState.ascii;
+ _keyPress = keyState.ascii;
if (keyState.keycode == Common::KEYCODE_x && keyState.flags & Common::KBD_ALT) {
_vm->quitGame();
@@ -246,7 +239,7 @@ void ScalpelUserInterface::handleInput() {
if (_help != -1 && !scene._bgShapes[_bgFound]._description.empty()
&& scene._bgShapes[_bgFound]._description[0] != ' ')
screen.print(Common::Point(0, INFO_LINE + 1),
- INFO_FOREGROUND, scene._bgShapes[_bgFound]._description.c_str());
+ INFO_FOREGROUND, "%s", scene._bgShapes[_bgFound]._description.c_str());
_oldBgFound = _bgFound;
}
@@ -316,7 +309,7 @@ void ScalpelUserInterface::handleInput() {
case USE_MODE:
case GIVE_MODE:
case INV_MODE:
- if (inv._invMode == 1 || inv._invMode == 2 || inv._invMode == 3) {
+ if (inv._invMode == INVMODE_LOOK || inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE) {
if (pt.y > CONTROLS_Y)
lookInv();
else
@@ -331,8 +324,7 @@ void ScalpelUserInterface::handleInput() {
//
// Do input processing
//
- if (events._pressed || events._released || events._rightPressed ||
- _keycode != Common::KEYCODE_INVALID || _pause) {
+ if (events._pressed || events._released || events._rightPressed || _keyPress || _pause) {
if (((events._released && (_helpStyle || _help == -1)) || (events._rightReleased && !_helpStyle)) &&
(pt.y <= CONTROLS_Y) && (_menuMode == STD_MODE)) {
// The mouse was clicked in the playing area with no action buttons down.
@@ -399,33 +391,25 @@ void ScalpelUserInterface::handleInput() {
// As long as there isn't an open window, do main input processing.
// Windows are opened when in TALK, USE, INV, and GIVE modes
if ((!_windowOpen && !_menuCounter && pt.y > CONTROLS_Y) ||
- _keycode != Common::KEYCODE_INVALID) {
- if (events._pressed || events._released || _pause ||
- _keycode != Common::KEYCODE_INVALID)
+ _keyPress) {
+ if (events._pressed || events._released || _pause || _keyPress)
doMainControl();
}
- if (pt.y < CONTROLS_Y && events._pressed && _oldTemp != (_menuMode - 1) && _oldKey != -1)
+ if (pt.y < CONTROLS_Y && events._pressed && _oldTemp != (int)(_menuMode - 1) && _oldKey != -1)
restoreButton(_oldTemp);
}
}
-/**
- * Draws the image for a user interface button in the down/pressed state.
- */
void ScalpelUserInterface::depressButton(int num) {
Screen &screen = *_vm->_screen;
Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
- Graphics::Surface &s = (*_controls)[num]._frame;
- screen._backBuffer1.transBlitFrom(s, pt);
- screen.slamArea(pt.x, pt.y, pt.x + s.w, pt.y + s.h);
+ ImageFrame &frame = (*_controls)[num];
+ screen._backBuffer1.transBlitFrom(frame, pt);
+ screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
}
-/**
- * Draws the image for the given user interface button in the up
- * (not selected) position
- */
void ScalpelUserInterface::restoreButton(int num) {
Screen &screen = *_vm->_screen;
Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
@@ -441,10 +425,6 @@ void ScalpelUserInterface::restoreButton(int num) {
}
}
-/**
- * If he mouse button is pressed, then calls depressButton to draw the button
- * as pressed; if not, it will show it as released with a call to "restoreButton".
- */
void ScalpelUserInterface::pushButton(int num) {
Events &events = *_vm->_events;
_oldKey = -1;
@@ -462,15 +442,10 @@ void ScalpelUserInterface::pushButton(int num) {
restoreButton(num);
}
-/**
- * By the time this method has been called, the graphics for the button change
- * have already been drawn. This simply takes care of switching the mode around
- * accordingly
- */
void ScalpelUserInterface::toggleButton(int num) {
Screen &screen = *_vm->_screen;
- if (_menuMode != (num + 1)) {
+ if (_menuMode != (MenuMode)(num + 1)) {
_menuMode = (MenuMode)(num + 1);
_oldKey = COMMANDS[num];
_oldTemp = num;
@@ -483,10 +458,10 @@ void ScalpelUserInterface::toggleButton(int num) {
_keyboardInput = false;
- Graphics::Surface &s = (*_controls)[num]._frame;
+ ImageFrame &frame = (*_controls)[num];
Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
- screen._backBuffer1.transBlitFrom(s, pt);
- screen.slamArea(pt.x, pt.y, pt.x + s.w, pt.y + s.h);
+ screen._backBuffer1.transBlitFrom(frame, pt);
+ screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
}
} else {
_menuMode = STD_MODE;
@@ -495,9 +470,6 @@ void ScalpelUserInterface::toggleButton(int num) {
}
}
-/**
- * Clears the info line of the screen
- */
void ScalpelUserInterface::clearInfo() {
if (_infoFlag) {
_vm->_screen->vgaBar(Common::Rect(16, INFO_LINE, SHERLOCK_SCREEN_WIDTH - 19,
@@ -507,9 +479,6 @@ void ScalpelUserInterface::clearInfo() {
}
}
-/**
- * Clear any active text window
- */
void ScalpelUserInterface::clearWindow() {
if (_windowOpen) {
_vm->_screen->vgaBar(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
@@ -517,9 +486,6 @@ void ScalpelUserInterface::clearWindow() {
}
}
-/**
- * Handles counting down whilst checking for input, then clears the info line.
- */
void ScalpelUserInterface::whileMenuCounter() {
if (!(--_menuCounter) || _vm->_events->checkInput()) {
_menuCounter = 0;
@@ -528,10 +494,6 @@ void ScalpelUserInterface::whileMenuCounter() {
}
}
-/**
- * Creates a text window and uses it to display the in-depth description
- * of the highlighted object
- */
void ScalpelUserInterface::examine() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -568,7 +530,7 @@ void ScalpelUserInterface::examine() {
}
if (_invLookFlag) {
- // Dont close the inventory window when starting an examine display, since it's
+ // Don't close the inventory window when starting an examine display, since its
// window will slide up to replace the inventory display
_windowOpen = false;
_menuMode = LOOK_MODE;
@@ -583,9 +545,6 @@ void ScalpelUserInterface::examine() {
}
}
-/**
- * Print the name of an object in the scene
- */
void ScalpelUserInterface::lookScreen(const Common::Point &pt) {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -616,10 +575,10 @@ void ScalpelUserInterface::lookScreen(const Common::Point &pt) {
if (!tempStr.empty() && tempStr[0] != ' ') {
// If inventory is active and an item is selected for a Use or Give action
if ((_menuMode == INV_MODE || _menuMode == USE_MODE || _menuMode == GIVE_MODE) &&
- (inv._invMode == 2 || inv._invMode == 3)) {
+ (inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE)) {
int width1 = 0, width2 = 0;
int x, width;
- if (inv._invMode == 2) {
+ if (inv._invMode == INVMODE_USE) {
// Using an object
x = width = screen.stringWidth("Use ");
@@ -651,14 +610,14 @@ void ScalpelUserInterface::lookScreen(const Common::Point &pt) {
if (_selector != -1) {
screen.print(Common::Point(xStart + width, INFO_LINE + 1),
- TALK_FOREGROUND, inv[_selector]._name.c_str());
+ TALK_FOREGROUND, "%s", inv[_selector]._name.c_str());
screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1),
INFO_FOREGROUND, " on ");
screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1),
- INFO_FOREGROUND, tempStr.c_str());
+ INFO_FOREGROUND, "%s", tempStr.c_str());
} else {
screen.print(Common::Point(xStart + width, INFO_LINE + 1),
- INFO_FOREGROUND, tempStr.c_str());
+ INFO_FOREGROUND, "%s", tempStr.c_str());
}
} else if (temp >= 0 && temp < 1000 && _selector != -1 &&
scene._bgShapes[temp]._aType == PERSON) {
@@ -680,14 +639,14 @@ void ScalpelUserInterface::lookScreen(const Common::Point &pt) {
screen.print(Common::Point(xStart, INFO_LINE + 1),
INFO_FOREGROUND, "Give ");
screen.print(Common::Point(xStart + width, INFO_LINE + 1),
- TALK_FOREGROUND, inv[_selector]._name.c_str());
+ TALK_FOREGROUND, "%s", inv[_selector]._name.c_str());
screen.print(Common::Point(xStart + width + width1, INFO_LINE + 1),
INFO_FOREGROUND, " to ");
screen.print(Common::Point(xStart + width + width1 + width2, INFO_LINE + 1),
- INFO_FOREGROUND, tempStr.c_str());
+ INFO_FOREGROUND, "%s", tempStr.c_str());
}
} else {
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, tempStr.c_str());
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", tempStr.c_str());
}
_infoFlag = true;
@@ -699,9 +658,6 @@ void ScalpelUserInterface::lookScreen(const Common::Point &pt) {
}
}
-/**
- * Gets the item in the inventory the mouse is on and display's it's description
- */
void ScalpelUserInterface::lookInv() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -715,7 +671,7 @@ void ScalpelUserInterface::lookInv() {
if (temp < inv._holdings) {
clearInfo();
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND,
- inv[temp]._description.c_str());
+ "%s", inv[temp]._description.c_str());
_infoFlag = true;
_oldLook = temp;
}
@@ -727,9 +683,6 @@ void ScalpelUserInterface::lookInv() {
}
}
-/**
- * Handles input when the file list window is being displayed
- */
void ScalpelUserInterface::doEnvControl() {
Events &events = *_vm->_events;
SaveManager &saves = *_vm->_saves;
@@ -738,25 +691,24 @@ void ScalpelUserInterface::doEnvControl() {
Talk &talk = *_vm->_talk;
Common::Point mousePos = events.mousePos();
static const char ENV_COMMANDS[7] = "ELSUDQ";
+
byte color;
_key = _oldKey = -1;
_keyboardInput = false;
int found = saves.getHighlightedButton();
- if (events._pressed || events._released)
- {
+ if (events._pressed || events._released) {
events.clearKeyboard();
// Check for a filename entry being highlighted
- if ((events._pressed || events._released) && mousePos.y > (CONTROLS_Y + 10))
- {
+ if ((events._pressed || events._released) && mousePos.y > (CONTROLS_Y + 10)) {
int found1 = 0;
- for (_selector = 0; (_selector < 5) && !found1; ++_selector)
+ for (_selector = 0; (_selector < ONSCREEN_FILES_COUNT) && !found1; ++_selector)
if (mousePos.y > (CONTROLS_Y + 11 + _selector * 10) && mousePos.y < (CONTROLS_Y + 21 + _selector * 10))
found1 = 1;
- if (_selector + saves._savegameIndex - 1 < MAX_SAVEGAME_SLOTS + (saves._envMode != 1))
+ if (_selector + saves._savegameIndex - 1 < MAX_SAVEGAME_SLOTS + (saves._envMode != SAVEMODE_LOAD))
_selector = _selector + saves._savegameIndex - 1;
else
_selector = -1;
@@ -772,8 +724,8 @@ void ScalpelUserInterface::doEnvControl() {
saves._envMode = SAVEMODE_NONE;
}
- if (_keycode) {
- _key = toupper(_keycode);
+ if (_keyPress) {
+ _key = toupper(_keyPress);
// Escape _key will close the dialog
if (_key == Common::KEYCODE_ESCAPE)
@@ -790,7 +742,7 @@ void ScalpelUserInterface::doEnvControl() {
} else if (_key >= '1' && _key <= '9') {
_keyboardInput = true;
_selector = _key - '1';
- if (_selector >= MAX_SAVEGAME_SLOTS + (saves._envMode == 1 ? 0 : 1))
+ if (_selector >= MAX_SAVEGAME_SLOTS + (saves._envMode == SAVEMODE_LOAD ? 0 : 1))
_selector = -1;
if (saves.checkGameOnScreen(_selector))
@@ -802,7 +754,7 @@ void ScalpelUserInterface::doEnvControl() {
}
if (_selector != _oldSelector) {
- if (_oldSelector != -1 && _oldSelector >= saves._savegameIndex && _oldSelector < (saves._savegameIndex + 5)) {
+ if (_oldSelector != -1 && _oldSelector >= saves._savegameIndex && _oldSelector < (saves._savegameIndex + ONSCREEN_FILES_COUNT)) {
screen.print(Common::Point(6, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10),
INV_FOREGROUND, "%d.", _oldSelector + 1);
screen.print(Common::Point(24, CONTROLS_Y + 12 + (_oldSelector - saves._savegameIndex) * 10),
@@ -825,7 +777,7 @@ void ScalpelUserInterface::doEnvControl() {
_windowBounds.top = CONTROLS_Y1;
events._pressed = events._released = _keyboardInput = false;
- _keycode = Common::KEYCODE_INVALID;
+ _keyPress = '\0';
} else if ((found == 1 && events._released) || _key == 'L') {
saves._envMode = SAVEMODE_LOAD;
if (_selector != -1) {
@@ -837,13 +789,13 @@ void ScalpelUserInterface::doEnvControl() {
if (saves.checkGameOnScreen(_selector))
_oldSelector = _selector;
- if (saves.getFilename(_selector)) {
+ if (saves.promptForDescription(_selector)) {
saves.saveGame(_selector + 1, saves._savegames[_selector]);
banishWindow(1);
_windowBounds.top = CONTROLS_Y1;
_key = _oldKey = -1;
- _keycode = Common::KEYCODE_INVALID;
+ _keyPress = '\0';
_keyboardInput = false;
} else {
if (!talk._talkToAbort) {
@@ -866,9 +818,9 @@ void ScalpelUserInterface::doEnvControl() {
screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
- for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + 5); ++idx) {
+ for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT); ++idx) {
color = INV_FOREGROUND;
- if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + 5))
+ if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT))
color = TALK_FOREGROUND;
screen.gPrint(Common::Point(6, CONTROLS_Y + 11 + (idx - saves._savegameIndex) * 10), color, "%d.", idx + 1);
@@ -879,10 +831,10 @@ void ScalpelUserInterface::doEnvControl() {
color = !saves._savegameIndex ? COMMAND_NULL : COMMAND_FOREGROUND;
screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, true, "Up");
- color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - 5) ? COMMAND_NULL : COMMAND_FOREGROUND;
+ color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) ? COMMAND_NULL : COMMAND_FOREGROUND;
screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, true, "Down");
- // Check for there are more pending U keys pressed
+ // Check whether there are more pending U keys pressed
moreKeys = false;
if (events.kbHit()) {
Common::KeyState keyState = events.getKey();
@@ -891,15 +843,15 @@ void ScalpelUserInterface::doEnvControl() {
moreKeys = _key == 'U';
}
} while ((saves._savegameIndex) && moreKeys);
- } else if (((found == 4 && events._released) || _key == 'D') && saves._savegameIndex < (MAX_SAVEGAME_SLOTS - 5)) {
+ } else if (((found == 4 && events._released) || _key == 'D') && saves._savegameIndex < (MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT)) {
bool moreKeys;
do {
saves._savegameIndex++;
screen._backBuffer1.fillRect(Common::Rect(3, CONTROLS_Y + 11, SHERLOCK_SCREEN_WIDTH - 2,
SHERLOCK_SCREEN_HEIGHT - 1), INV_BACKGROUND);
- for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + 5); ++idx) {
- if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + 5))
+ for (int idx = saves._savegameIndex; idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT); ++idx) {
+ if (idx == _selector && idx >= saves._savegameIndex && idx < (saves._savegameIndex + ONSCREEN_FILES_COUNT))
color = TALK_FOREGROUND;
else
color = INV_FOREGROUND;
@@ -915,10 +867,10 @@ void ScalpelUserInterface::doEnvControl() {
color = (!saves._savegameIndex) ? COMMAND_NULL : COMMAND_FOREGROUND;
screen.buttonPrint(Common::Point(ENV_POINTS[3][2], CONTROLS_Y), color, true, "Up");
- color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - 5) ? COMMAND_NULL : COMMAND_FOREGROUND;
+ color = (saves._savegameIndex == MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) ? COMMAND_NULL : COMMAND_FOREGROUND;
screen.buttonPrint(Common::Point(ENV_POINTS[4][2], CONTROLS_Y), color, true, "Down");
- // Check for there are more pending D keys pressed
+ // Check whether there are more pending D keys pressed
moreKeys = false;
if (events.kbHit()) {
Common::KeyState keyState;
@@ -926,7 +878,7 @@ void ScalpelUserInterface::doEnvControl() {
moreKeys = _key == 'D';
}
- } while (saves._savegameIndex < (MAX_SAVEGAME_SLOTS - 5) && moreKeys);
+ } while (saves._savegameIndex < (MAX_SAVEGAME_SLOTS - ONSCREEN_FILES_COUNT) && moreKeys);
} else if ((found == 5 && events._released) || _key == 'Q') {
clearWindow();
screen.print(Common::Point(0, CONTROLS_Y + 20), INV_FOREGROUND, "Are you sure you wish to Quit ?");
@@ -959,11 +911,11 @@ void ScalpelUserInterface::doEnvControl() {
if (_key == Common::KEYCODE_ESCAPE)
_key = 'N';
- if (_key == Common::KEYCODE_RETURN || _key == Common::KEYCODE_SPACE) {
+ if (_key == Common::KEYCODE_RETURN || _key == ' ') {
events._pressed = false;
events._released = true;
events._oldButtons = 0;
- _keycode = Common::KEYCODE_INVALID;
+ _keyPress = '\0';
}
}
@@ -1003,17 +955,17 @@ void ScalpelUserInterface::doEnvControl() {
// Are we already in Load mode?
if (saves._envMode == SAVEMODE_LOAD) {
saves.loadGame(_selector + 1);
- } else if (saves._envMode == SAVEMODE_SAVE || _selector == MAX_SAVEGAME_SLOTS) {
- // We're alreaady in save mode, or pointed to an empty save slot
+ } else if (saves._envMode == SAVEMODE_SAVE || saves.isSlotEmpty(_selector)) {
+ // We're already in save mode, or pointing to an empty save slot
if (saves.checkGameOnScreen(_selector))
_oldSelector = _selector;
- if (saves.getFilename(_selector)) {
+ if (saves.promptForDescription(_selector)) {
saves.saveGame(_selector + 1, saves._savegames[_selector]);
banishWindow();
_windowBounds.top = CONTROLS_Y1;
_key = _oldKey = -1;
- _keycode = Common::KEYCODE_INVALID;
+ _keyPress = '\0';
_keyboardInput = false;
} else {
if (!talk._talkToAbort) {
@@ -1033,16 +985,12 @@ void ScalpelUserInterface::doEnvControl() {
}
}
-/**
- * Handle input whilst the inventory is active
- */
void ScalpelUserInterface::doInvControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Scene &scene = *_vm->_scene;
Screen &screen = *_vm->_screen;
Talk &talk = *_vm->_talk;
- UserInterface &ui = *_vm->_ui;
int colors[8];
Common::Point mousePos = events.mousePos();
@@ -1065,7 +1013,7 @@ void ScalpelUserInterface::doInvControl() {
events.clearKeyboard();
if (found != -1)
- // If a slot highlighted, set it's color
+ // If a slot highlighted, set its color
colors[found] = COMMAND_HIGHLIGHTED;
screen.buttonPrint(Common::Point(INVENTORY_POINTS[0][2], CONTROLS_Y1), colors[0], true, "Exit");
@@ -1088,7 +1036,7 @@ void ScalpelUserInterface::doInvControl() {
}
bool flag = false;
- if (inv._invMode == 1 || inv._invMode == 2 || inv._invMode == 3) {
+ if (inv._invMode == INVMODE_LOOK || inv._invMode == INVMODE_USE || inv._invMode == INVMODE_GIVE) {
Common::Rect r(15, CONTROLS_Y1 + 11, 314, SHERLOCK_SCREEN_HEIGHT - 2);
if (r.contains(mousePos)) {
_selector = (mousePos.x - 6) / 52 + inv._invIndex;
@@ -1101,22 +1049,22 @@ void ScalpelUserInterface::doInvControl() {
_selector = -1;
}
- if (_keycode != Common::KEYCODE_INVALID) {
- _key = toupper(_keycode);
+ if (_keyPress) {
+ _key = toupper(_keyPress);
if (_key == Common::KEYCODE_ESCAPE)
// Escape will also 'E'xit out of inventory display
- _key = Common::KEYCODE_e;
+ _key = 'E';
if (_key == 'E' || _key == 'L' || _key == 'U' || _key == 'G'
|| _key == '-' || _key == '+') {
- int temp = inv._invMode;
+ InvMode temp = inv._invMode;
const char *chP = strchr(INVENTORY_COMMANDS, _key);
inv._invMode = !chP ? INVMODE_INVALID : (InvMode)(chP - INVENTORY_COMMANDS);
inv.invCommands(true);
- inv._invMode = (InvMode)temp;
+ inv._invMode = temp;
_keyboardInput = true;
if (_key == 'E')
inv._invMode = INVMODE_EXIT;
@@ -1164,23 +1112,21 @@ void ScalpelUserInterface::doInvControl() {
COMMAND_HIGHLIGHTED, "^^");
inv.freeGraphics();
inv.loadGraphics();
- inv.putInv(1);
+ inv.putInv(SLAM_DISPLAY);
inv.invCommands(true);
- } else if (((found == 5 && events._released) || _key == Common::KEYCODE_MINUS
- || _key == Common::KEYCODE_KP_MINUS) && inv._invIndex > 0) {
+ } else if (((found == 5 && events._released) || _key == '-') && inv._invIndex > 0) {
--inv._invIndex;
screen.print(Common::Point(INVENTORY_POINTS[4][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "^");
inv.freeGraphics();
inv.loadGraphics();
- inv.putInv(1);
+ inv.putInv(SLAM_DISPLAY);
inv.invCommands(true);
- } else if (((found == 6 && events._released) || _key == Common::KEYCODE_PLUS
- || _key == Common::KEYCODE_KP_PLUS) && (inv._holdings - inv._invIndex) > 6) {
+ } else if (((found == 6 && events._released) || _key == '+') && (inv._holdings - inv._invIndex) > 6) {
++inv._invIndex;
screen.print(Common::Point(INVENTORY_POINTS[6][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_");
inv.freeGraphics();
inv.loadGraphics();
- inv.putInv(1);
+ inv.putInv(SLAM_DISPLAY);
inv.invCommands(true);
} else if (((found == 7 && events._released) || _key == '.') && (inv._holdings - inv._invIndex) > 6) {
inv._invIndex += 6;
@@ -1190,11 +1136,11 @@ void ScalpelUserInterface::doInvControl() {
screen.print(Common::Point(INVENTORY_POINTS[7][2], CONTROLS_Y1 + 1), COMMAND_HIGHLIGHTED, "_");
inv.freeGraphics();
inv.loadGraphics();
- inv.putInv(1);
+ inv.putInv(SLAM_DISPLAY);
inv.invCommands(true);
} else {
- // If something is being given, make sure it's to a person
- if (inv._invMode == 3) {
+ // If something is being given, make sure it's being given to a person
+ if (inv._invMode == INVMODE_GIVE) {
if (_bgFound != -1 && scene._bgShapes[_bgFound]._aType == PERSON)
_find = _bgFound;
else
@@ -1203,10 +1149,10 @@ void ScalpelUserInterface::doInvControl() {
_find = _bgFound;
}
- if ((mousePos.y < CONTROLS_Y1) && (inv._invMode == 1) && (_find >= 0) && (_find < 1000)) {
+ if ((mousePos.y < CONTROLS_Y1) && (inv._invMode == INVMODE_LOOK) && (_find >= 0) && (_find < 1000)) {
if (!scene._bgShapes[_find]._examine.empty() &&
scene._bgShapes[_find]._examine[0] >= ' ')
- ui.doInvJF();
+ inv.refreshInv();
} else if (_selector != -1 || _find >= 0) {
// Selector is the inventory object that was clicked on, or selected.
// If it's -1, then no inventory item is highlighted yet. Otherwise,
@@ -1214,29 +1160,29 @@ void ScalpelUserInterface::doInvControl() {
if (_selector != -1 && inv._invMode == INVMODE_LOOK
&& mousePos.y >(CONTROLS_Y1 + 11))
- ui.doInvJF();
+ inv.refreshInv();
if (talk._talkToAbort)
return;
- // Now check for the Use and Give actions. If inv_mode is 3,
+ // Now check for the Use and Give actions. If inv_mode is INVMODE_GIVE,
// that means GIVE is in effect, _selector is the object being
// given, and _find is the target.
// The same applies to USE, except if _selector is -1, then USE
// is being tried on an object in the scene without an inventory
// object being highlighted first.
- if ((inv._invMode == 2 || (_selector != -1 && inv._invMode == 3)) && _find >= 0) {
+ if ((inv._invMode == INVMODE_USE || (_selector != -1 && inv._invMode == INVMODE_GIVE)) && _find >= 0) {
events._pressed = events._released = false;
_infoFlag = true;
clearInfo();
- int temp = _selector; // Save the selector
+ int tempSel = _selector; // Save the selector
_selector = -1;
- inv.putInv(1);
- _selector = temp; // Restore it
- temp = inv._invMode;
+ inv.putInv(SLAM_DISPLAY);
+ _selector = tempSel; // Restore it
+ InvMode tempMode = inv._invMode;
inv._invMode = INVMODE_USE55;
inv.invCommands(true);
@@ -1247,12 +1193,13 @@ void ScalpelUserInterface::doInvControl() {
inv.freeInv();
+ bool giveFl = (tempMode >= INVMODE_GIVE);
if (_selector >= 0)
// Use/Give inv object with scene object
- checkUseAction(&scene._bgShapes[_find]._use[0], inv[_selector]._name, MUSE, _find, temp - 2);
+ checkUseAction(&scene._bgShapes[_find]._use[0], inv[_selector]._name, MUSE, _find, giveFl);
else
// Now inv object has been highlighted
- checkUseAction(&scene._bgShapes[_find]._use[0], "*SELF*", MUSE, _find, temp - 2);
+ checkUseAction(&scene._bgShapes[_find]._use[0], "*SELF*", MUSE, _find, giveFl);
_selector = _oldSelector = -1;
}
@@ -1261,16 +1208,13 @@ void ScalpelUserInterface::doInvControl() {
}
}
-/**
- * Handles waiting whilst an object's description window is open.
- */
void ScalpelUserInterface::doLookControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Screen &screen = *_vm->_screen;
_key = _oldKey = -1;
- _keyboardInput = (_keycode != Common::KEYCODE_INVALID);
+ _keyboardInput = (_keyPress != '\0');
if (events._released || events._rightReleased || _keyboardInput) {
// Is an inventory object being looked at?
@@ -1281,7 +1225,7 @@ void ScalpelUserInterface::doLookControl() {
} else if (!_lookHelp) {
// Need to close the window and depress the Look button
Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
- screen._backBuffer2.blitFrom((*_controls)[0]._frame, pt);
+ screen._backBuffer2.blitFrom((*_controls)[0], pt);
banishWindow(true);
_windowBounds.top = CONTROLS_Y1;
@@ -1308,7 +1252,7 @@ void ScalpelUserInterface::doLookControl() {
tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- inv.drawInventory(128);
+ inv.drawInventory(INVENTORY_DONT_DISPLAY);
banishWindow(true);
// Restore the ui
@@ -1325,9 +1269,6 @@ void ScalpelUserInterface::doLookControl() {
}
}
-/**
- * Handles input until one of the user interface buttons/commands is selected
- */
void ScalpelUserInterface::doMainControl() {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -1346,12 +1287,12 @@ void ScalpelUserInterface::doMainControl() {
_key = COMMANDS[_temp];
}
--_temp;
- } else if (_keycode != Common::KEYCODE_INVALID) {
+ } else if (_keyPress) {
// Keyboard control
_keyboardInput = true;
- if (_keycode >= Common::KEYCODE_a && _keycode <= Common::KEYCODE_z) {
- const char *c = strchr(COMMANDS, _keycode);
+ if (_keyPress >= 'A' && _keyPress <= 'Z') {
+ const char *c = strchr(COMMANDS, _keyPress);
_temp = !c ? 12 : c - COMMANDS;
} else {
_temp = 12;
@@ -1413,19 +1354,19 @@ void ScalpelUserInterface::doMainControl() {
pushButton(6);
_selector = _oldSelector = -1;
_menuMode = INV_MODE;
- inv.drawInventory(1);
+ inv.drawInventory(PLAIN_INVENTORY);
break;
case 'U':
pushButton(7);
_selector = _oldSelector = -1;
_menuMode = USE_MODE;
- inv.drawInventory(2);
+ inv.drawInventory(USE_INVENTORY_MODE);
break;
case 'G':
pushButton(8);
_selector = _oldSelector = -1;
_menuMode = GIVE_MODE;
- inv.drawInventory(3);
+ inv.drawInventory(GIVE_INVENTORY_MODE);
break;
case 'J':
pushButton(9);
@@ -1466,9 +1407,6 @@ void ScalpelUserInterface::doMainControl() {
}
}
-/**
- * Handles the input for the MOVE, OPEN, and CLOSE commands
- */
void ScalpelUserInterface::doMiscControl(int allowed) {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
@@ -1518,9 +1456,6 @@ void ScalpelUserInterface::doMiscControl(int allowed) {
}
}
-/**
- * Handles input for picking up items
- */
void ScalpelUserInterface::doPickControl() {
Events &events = *_vm->_events;
Scene &scene = *_vm->_scene;
@@ -1544,10 +1479,6 @@ void ScalpelUserInterface::doPickControl() {
}
}
-/**
- * Handles input when in talk mode. It highlights the buttons and available statements,
- * and handles allowing the user to click on them
- */
void ScalpelUserInterface::doTalkControl() {
Events &events = *_vm->_events;
Journal &journal = *_vm->_journal;
@@ -1590,8 +1521,8 @@ void ScalpelUserInterface::doTalkControl() {
_selector = -1;
}
- if (_keycode != Common::KEYCODE_INVALID) {
- _key = toupper(_keycode);
+ if (_keyPress) {
+ _key = toupper(_keyPress);
if (_key == Common::KEYCODE_ESCAPE)
_key = 'E';
@@ -1798,12 +1729,6 @@ void ScalpelUserInterface::doTalkControl() {
}
}
-/**
- * Handles events when the Journal is active.
- * @remarks Whilst this would in theory be better in the Journal class, since it displays in
- * the user interface, it uses so many internal UI fields, that it sort of made some sense
- * to put it in the UserInterface class.
- */
void ScalpelUserInterface::journalControl() {
Events &events = *_vm->_events;
Journal &journal = *_vm->_journal;
@@ -1838,7 +1763,7 @@ void ScalpelUserInterface::journalControl() {
// Finish up
_infoFlag = _keyboardInput = false;
- _keycode = Common::KEYCODE_INVALID;
+ _keyPress = '\0';
_windowOpen = false;
_windowBounds.top = CONTROLS_Y1;
_key = -1;
@@ -1852,9 +1777,6 @@ void ScalpelUserInterface::journalControl() {
screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
}
-/**
-* Print the description of an object
-*/
void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool firstTime) {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
@@ -1884,8 +1806,8 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
- Common::Rect(pt.x, pt.y, pt.x + tempSurface.w, pt.y + tempSurface.h));
- screen._backBuffer2.transBlitFrom((*_controls)[0]._frame, pt);
+ Common::Rect(pt.x, pt.y, pt.x + tempSurface.w(), pt.y + tempSurface.h()));
+ screen._backBuffer2.transBlitFrom((*_controls)[0], pt);
banishWindow(1);
events.setCursor(MAGNIFY);
@@ -1912,7 +1834,7 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
// Reload the inventory graphics and draw the inventory
inv.loadInv();
- inv.putInv(2);
+ inv.putInv(SLAM_SECONDARY_BUFFER);
inv.freeInv();
banishWindow(1);
@@ -1955,7 +1877,7 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
// Loop through displaying up to five lines
bool endOfStr = false;
const char *msgP = str.c_str();
- for (int lineNum = 0; lineNum < 5 && !endOfStr; ++lineNum) {
+ for (int lineNum = 0; lineNum < ONSCREEN_FILES_COUNT && !endOfStr; ++lineNum) {
int width = 0;
const char *lineStartP = msgP;
@@ -1980,7 +1902,7 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
// Print out the line
Common::String line(lineStartP, msgP);
screen.gPrint(Common::Point(16, CONTROLS_Y + 12 + lineNum * 9),
- INV_FOREGROUND, line.c_str());
+ INV_FOREGROUND, "%s", line.c_str());
if (!endOfStr)
// Start next line at start of the nxet word after space
@@ -2007,7 +1929,7 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
}
if (firstTime) {
- if (!_windowStyle) {
+ if (!_slideWindows) {
screen.slamRect(Common::Rect(0, CONTROLS_Y,
SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
} else {
@@ -2023,16 +1945,10 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
}
}
-/**
- * Print the previously selected object's decription
- */
void ScalpelUserInterface::printObjectDesc() {
printObjectDesc(_cAnimStr, true);
}
-/**
- * Displays a passed window by gradually scrolling it vertically on-screen
- */
void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
@@ -2043,9 +1959,9 @@ void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp)
if (slideUp) {
// Gradually slide up the display of the window
- for (int idx = 1; idx <= bgSurface.h; idx += 2) {
+ for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx),
- Common::Rect(0, 0, bgSurface.w, idx));
+ Common::Rect(0, 0, bgSurface.w(), idx));
screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx,
SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
@@ -2053,29 +1969,25 @@ void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp)
}
} else {
// Gradually slide down the display of the window
- for (int idx = 1; idx <= bgSurface.h; idx += 2) {
+ for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
screen._backBuffer->blitFrom(bgSurface,
- Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h),
- Common::Rect(0, bgSurface.h - idx, bgSurface.w, bgSurface.h));
- screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h,
- SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - bgSurface.h + idx));
+ Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
+ Common::Rect(0, bgSurface.h() - idx, bgSurface.w(), bgSurface.h()));
+ screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(),
+ SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - bgSurface.h() + idx));
events.delay(10);
}
}
// Final display of the entire window
- screen._backBuffer->blitFrom(bgSurface, Common::Point(0,
- SHERLOCK_SCREEN_HEIGHT - bgSurface.h),
- Common::Rect(0, 0, bgSurface.w, bgSurface.h));
- screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h, bgSurface.w, bgSurface.h);
+ screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
+ Common::Rect(0, 0, bgSurface.w(), bgSurface.h()));
+ screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(), bgSurface.w(), bgSurface.h());
_windowOpen = true;
}
-/**
- * Slide the window stored in the back buffer onto the screen
- */
void ScalpelUserInterface::summonWindow(bool slideUp, int height) {
Screen &screen = *_vm->_screen;
@@ -2093,19 +2005,15 @@ void ScalpelUserInterface::summonWindow(bool slideUp, int height) {
summonWindow(tempSurface, slideUp);
}
-/**
- * Close a currently open window
- * @param flag 0 = slide old window down, 1 = slide prior UI back up
- */
void ScalpelUserInterface::banishWindow(bool slideUp) {
Events &events = *_vm->_events;
Screen &screen = *_vm->_screen;
if (_windowOpen) {
- if (slideUp || !_windowStyle) {
+ if (slideUp || !_slideWindows) {
// Slide window down
// Only slide the window if the window style allows it
- if (_windowStyle) {
+ if (_slideWindows) {
for (int idx = 2; idx < (SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y); idx += 2) {
// Shift the window down by 2 lines
byte *pSrc = (byte *)screen._backBuffer1.getBasePtr(0, CONTROLS_Y + idx - 2);
@@ -2163,11 +2071,8 @@ void ScalpelUserInterface::banishWindow(bool slideUp) {
_menuMode = STD_MODE;
}
-/**
- * Checks to see whether a USE action is valid on the given object
- */
void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::String &invName,
- const char *const messages[], int objNum, int giveMode) {
+ const char *const messages[], int objNum, bool giveMode) {
Events &events = *_vm->_events;
Inventory &inv = *_vm->_inventory;
Scene &scene = *_vm->_scene;
@@ -2190,18 +2095,18 @@ void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::Stri
// Scan for target item
int targetNum = -1;
if (giveMode) {
- for (int idx = 0; idx < 4 && targetNum == -1; ++idx) {
- if ((scumm_stricmp(use[idx]._target.c_str(), "*GIVE*") == 0 || scumm_stricmp(use[idx]._target.c_str(), "*GIVEP*") == 0)
- && scumm_stricmp(use[idx]._names[0].c_str(), invName.c_str()) == 0) {
+ for (int idx = 0; idx < USE_COUNT && targetNum == -1; ++idx) {
+ if ((use[idx]._target.equalsIgnoreCase("*GIVE*") || use[idx]._target.equalsIgnoreCase("*GIVEP*"))
+ && use[idx]._names[0].equalsIgnoreCase(invName)) {
// Found a match
targetNum = idx;
- if (scumm_stricmp(use[idx]._target.c_str(), "*GIVE*") == 0)
+ if (use[idx]._target.equalsIgnoreCase("*GIVE*"))
inv.deleteItemFromInventory(invName);
}
}
} else {
- for (int idx = 0; idx < 4 && targetNum == -1; ++idx) {
- if (scumm_stricmp(use[idx]._target.c_str(), invName.c_str()) == 0)
+ for (int idx = 0; idx < USE_COUNT && targetNum == -1; ++idx) {
+ if (use[idx]._target.equalsIgnoreCase(invName))
targetNum = idx;
}
}
@@ -2224,7 +2129,7 @@ void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::Stri
if (!talk._talkToAbort) {
Object &obj = scene._bgShapes[objNum];
- for (int idx = 0; idx < 4 && !talk._talkToAbort; ++idx) {
+ for (int idx = 0; idx < NAMES_COUNT && !talk._talkToAbort; ++idx) {
if (obj.checkNameForCodes(action._names[idx], messages)) {
if (!talk._talkToAbort)
printed = true;
@@ -2249,7 +2154,7 @@ void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::Stri
} else if (messages == nullptr) {
screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "You can't do that.");
} else {
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[0]);
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[0]);
}
_infoFlag = true;
@@ -2259,9 +2164,6 @@ void ScalpelUserInterface::checkUseAction(const UseType *use, const Common::Stri
events.setCursor(ARROW);
}
-/**
- * Called for OPEN, CLOSE, and MOVE actions are being done
- */
void ScalpelUserInterface::checkAction(ActionType &action, const char *const messages[], int objNum) {
Events &events = *_vm->_events;
People &people = *_vm->_people;
@@ -2278,7 +2180,7 @@ void ScalpelUserInterface::checkAction(ActionType &action, const char *const mes
// Invalid action, to print error message
_infoFlag = true;
clearInfo();
- screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, messages[action._cAnimNum]);
+ screen.print(Common::Point(0, INFO_LINE + 1), INFO_FOREGROUND, "%s", messages[action._cAnimNum]);
_infoFlag = true;
// Set how long to show the message
@@ -2316,7 +2218,7 @@ void ScalpelUserInterface::checkAction(ActionType &action, const char *const mes
events.setCursor(WAIT);
bool printed = false;
- for (int nameIdx = 0; nameIdx < 4; ++nameIdx) {
+ for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2
&& toupper(action._names[nameIdx][1]) == 'W') {
if (obj.checkNameForCodes(Common::String(action._names[nameIdx].c_str() + 2), messages)) {
@@ -2327,7 +2229,7 @@ void ScalpelUserInterface::checkAction(ActionType &action, const char *const mes
}
bool doCAnim = true;
- for (int nameIdx = 0; nameIdx < 4; ++nameIdx) {
+ for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2) {
char ch = toupper(action._names[nameIdx][1]);
@@ -2357,7 +2259,7 @@ void ScalpelUserInterface::checkAction(ActionType &action, const char *const mes
people.walkToCoords(pt, dir);
}
- for (int nameIdx = 0; nameIdx < 4; ++nameIdx) {
+ for (int nameIdx = 0; nameIdx < NAMES_COUNT; ++nameIdx) {
if (action._names[nameIdx].hasPrefix("*") && action._names[nameIdx].size() >= 2
&& toupper(action._names[nameIdx][1]) == 'F') {
if (obj.checkNameForCodes(action._names[nameIdx].c_str() + 2, messages)) {
@@ -2371,7 +2273,7 @@ void ScalpelUserInterface::checkAction(ActionType &action, const char *const mes
scene.startCAnim(cAnimNum, action._cAnimSpeed);
if (!talk._talkToAbort) {
- for (int nameIdx = 0; nameIdx < 4 && !talk._talkToAbort; ++nameIdx) {
+ for (int nameIdx = 0; nameIdx < NAMES_COUNT && !talk._talkToAbort; ++nameIdx) {
if (obj.checkNameForCodes(action._names[nameIdx], messages)) {
if (!talk._talkToAbort)
printed = true;
@@ -2394,31 +2296,6 @@ void ScalpelUserInterface::checkAction(ActionType &action, const char *const mes
events.setCursor(ARROW);
}
-/**
- * Support method for updating the screen
- */
-void ScalpelUserInterface::doInvJF() {
- Inventory &inv = *_vm->_inventory;
- Screen &screen = *_vm->_screen;
- Talk &talk = *_vm->_talk;
-
- _invLookFlag = true;
- inv.freeInv();
-
- _infoFlag = true;
- clearInfo();
-
- screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
- Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
- examine();
-
- if (!talk._talkToAbort) {
- screen._backBuffer2.blitFrom((*_controlPanel)[0]._frame,
- Common::Point(0, CONTROLS_Y));
- inv.loadInv();
- }
-}
-
/*----------------------------------------------------------------*/
TattooUserInterface::TattooUserInterface(SherlockEngine *vm): UserInterface(vm) {
diff --git a/engines/sherlock/user_interface.h b/engines/sherlock/user_interface.h
index acbb0c0ed0..8a0f4f5613 100644
--- a/engines/sherlock/user_interface.h
+++ b/engines/sherlock/user_interface.h
@@ -74,14 +74,14 @@ public:
bool _windowOpen;
bool _endKeyActive;
int _invLookFlag;
- int _windowStyle;
+ bool _slideWindows;
bool _helpStyle;
Common::Rect _windowBounds;
bool _lookScriptFlag;
// TODO: Not so sure these should be in the base class. May want to refactor them to SherlockEngine, or refactor
// various Scalpel dialogs to keep their own private state of key/selections
- int _key, _oldKey;
+ char _key, _oldKey;
int _selector, _oldSelector;
int _temp, _oldTemp;
int _temp1;
@@ -89,17 +89,50 @@ public:
public:
static UserInterface *init(SherlockEngine *vm);
+ /**
+ * Resets the user interface
+ */
virtual void reset() {}
+
+ /**
+ * Draw the user interface onto the screen's back buffers
+ */
virtual void drawInterface(int bufferNum = 3) {}
+
+ /**
+ * Main input handler for the user interface
+ */
virtual void handleInput() {}
- virtual void doInvJF() {}
+ /**
+ * Displays a passed window by gradually scrolling it vertically on-screen
+ */
virtual void summonWindow(const Surface &bgSurface, bool slideUp = true) {}
+
+ /**
+ * Slide the window stored in the back buffer onto the screen
+ */
virtual void summonWindow(bool slideUp = true, int height = CONTROLS_Y) {}
+
+ /**
+ * Close a currently open window
+ * @param flag 0 = slide old window down, 1 = slide prior UI back up
+ */
virtual void banishWindow(bool slideUp = true) {}
+
+ /**
+ * Clears the info line of the screen
+ */
virtual void clearInfo() {}
+
+ /**
+ * Clear any active text window
+ */
virtual void clearWindow() {}
+ /**
+ * Print the previously selected object's decription
+ */
virtual void printObjectDesc() {}
};
@@ -110,10 +143,12 @@ class ScalpelUserInterface: public UserInterface {
private:
ImageFile *_controlPanel;
ImageFile *_controls;
- int _bgFound;
- int _oldBgFound;
- int _keycode;
+ char _keyPress;
+ int _lookHelp;
+ int _bgFound, _oldBgFound;
int _help, _oldHelp;
+ char _key, _oldKey;
+ int _temp, _oldTemp;
int _oldLook;
bool _keyboardInput;
bool _pause;
@@ -123,54 +158,158 @@ private:
int _find;
int _oldUse;
private:
+ /**
+ * Draws the image for a user interface button in the down/pressed state.
+ */
void depressButton(int num);
+ /**
+ * If he mouse button is pressed, then calls depressButton to draw the button
+ * as pressed; if not, it will show it as released with a call to "restoreButton".
+ */
void pushButton(int num);
+ /**
+ * By the time this method has been called, the graphics for the button change
+ * have already been drawn. This simply takes care of switching the mode around
+ * accordingly
+ */
void toggleButton(int num);
+ /**
+ * Creates a text window and uses it to display the in-depth description
+ * of the highlighted object
+ */
void examine();
+ /**
+ * Print the name of an object in the scene
+ */
void lookScreen(const Common::Point &pt);
+ /**
+ * Gets the item in the inventory the mouse is on and display's it's description
+ */
void lookInv();
+ /**
+ * Handles input when the file list window is being displayed
+ */
void doEnvControl();
+
+ /**
+ * Handle input whilst the inventory is active
+ */
void doInvControl();
+
+ /**
+ * Handles waiting whilst an object's description window is open.
+ */
void doLookControl();
+
+ /**
+ * Handles input until one of the user interface buttons/commands is selected
+ */
void doMainControl();
+
+ /**
+ * Handles the input for the MOVE, OPEN, and CLOSE commands
+ */
void doMiscControl(int allowed);
+
+ /**
+ * Handles input for picking up items
+ */
void doPickControl();
+
+ /**
+ * Handles input when in talk mode. It highlights the buttons and available statements,
+ * and handles allowing the user to click on them
+ */
void doTalkControl();
+
+ /**
+ * Handles events when the Journal is active.
+ * @remarks Whilst this would in theory be better in the Journal class, since it displays in
+ * the user interface, it uses so many internal UI fields, that it sort of made some sense
+ * to put it in the UserInterface class.
+ */
void journalControl();
+ /**
+ * Checks to see whether a USE action is valid on the given object
+ */
void checkUseAction(const UseType *use, const Common::String &invName, const char *const messages[],
- int objNum, int giveMode);
+ int objNum, bool giveMode);
+
+ /**
+ * Called for OPEN, CLOSE, and MOVE actions are being done
+ */
void checkAction(ActionType &action, const char *const messages[], int objNum);
+ /**
+ * Print the previously selected object's decription
+ */
void printObjectDesc(const Common::String &str, bool firstTime);
public:
ScalpelUserInterface(SherlockEngine *vm);
~ScalpelUserInterface();
+ /**
+ * Handles counting down whilst checking for input, then clears the info line.
+ */
void whileMenuCounter();
+ /**
+ * Draws the image for the given user interface button in the up
+ * (not selected) position
+ */
void restoreButton(int num);
public:
+ /**
+ * Resets the user interface
+ */
virtual void reset();
+ /**
+ * Main input handler for the user interface
+ */
virtual void handleInput();
+ /**
+ * Draw the user interface onto the screen's back buffers
+ */
virtual void drawInterface(int bufferNum = 3);
- virtual void doInvJF();
-
+ /**
+ * Displays a passed window by gradually scrolling it vertically on-screen
+ */
virtual void summonWindow(const Surface &bgSurface, bool slideUp = true);
+
+ /**
+ * Slide the window stored in the back buffer onto the screen
+ */
virtual void summonWindow(bool slideUp = true, int height = CONTROLS_Y);
+
+ /**
+ * Close a currently open window
+ * @param flag 0 = slide old window down, 1 = slide prior UI back up
+ */
virtual void banishWindow(bool slideUp = true);
+
+ /**
+ * Clears the info line of the screen
+ */
virtual void clearInfo();
+
+ /**
+ * Clear any active text window
+ */
virtual void clearWindow();
+ /**
+ * Print the previously selected object's decription
+ */
virtual void printObjectDesc();
};
@@ -178,6 +317,9 @@ class TattooUserInterface : public UserInterface {
public:
TattooUserInterface(SherlockEngine *vm);
public:
+ /**
+ * Main input handler for the user interface
+ */
virtual void handleInput();
};
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 09f865f798..9e2905f454 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -1785,7 +1785,7 @@ int32 ToonEngine::runEventScript(int32 x, int32 y, int32 mode, int32 id, int32 s
_currentScriptRegion++;
_script->start(status, 1);
- while (_script->run(status))
+ while (_script->run(status) && !_shouldQuit)
waitForScriptStep();
_currentScriptRegion--;