[Scummvm-git-logs] scummvm master -> 9b490a0864d1bf25510ddc1fb598974f8bc97adf
bluegr
bluegr at gmail.com
Wed Sep 15 16:14:32 UTC 2021
This automated email contains information about 52 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
b5e62ffdaf GROOVIE: Update game detection. Add TLC-DE and engine can differ between each game
46ebbe8000 GROOVIE: Support of TLC ROQ video files
1e2c395d12 GROOVIE: Add printfunction opcode for V2 engine
d0f247f7b0 GROOVIE: Add cursor hotspots for V2 engine
1a006ea3e3 GROOVIE: Add support for TLC
7004f65557 GROOVIE: Minor changes in debug messages / hotspot debugging
7b397d8ec9 GROOVIE: Bugfixes in TLC specific calculations
0c919bc38b GROOVIE: Extensions to ROQ Player for 11H
76c71278fb GROOVIE: Described unknown filed in resource database
d4fea1aa34 GROOVIE: Added german version of 11h
e0ed66fe58 GROOVIE: Adaptions for transparent cursor
6525123663 GROOVIE: TLC Music / Small Bugfixes / Better Comments
d3493f2352 GROOVIE: Bugfixes ROQ Player / Stubs for 11H Staufs moves
9c68ffb79f GROOVIE: Overlay corrections, some other bugfixes
efcc882cc8 GROOVIE: Added calc of final profile for TLC
3d8cb28b8c GROOVIE: Bugfix. Videos with ID0 were skipped
71e2e2654a GROOVIE: Added T11H Engish version available on Steam
cc61104b98 GROOVIE: Start implementation of gallery puzzle
ee91abb26a GROOVIE: fix compiler errors
21449e3e5a GROOVIE: fix duplicated debug channels
5fbf8bd146 GROOVIE: fix accidental o2 in _opcodesT7G
7465118de6 GROOVIE: fix T7G regression with intro and outro songs (track2.ogg)
e7a406657f GROOVIE:Grooovie2 clearer names for different versions of The 11th Hour
3494ce638c GROOVIE: add o2_copybgtofg and fix o_videofromstring1
7e53331044 GROOVIE: Codacy and formatting
c7e4c851f6 GROOVIE: some cleanup
454dbff264 GROOVIE: v2 use o2_printstring opcode
7a09ae0a15 GROOVIE: T11H fix mouse trap crash
87e98d1e86 GROOVIE: stubs for T11H AI puzzles
132ac84bdb GROOVIE: replace strcmpi with scumm_stricmp
6fb5822f98 GROOVIE: fix video frame pacing
8da84fdda9 GROOVIE: added background sound effects
038758a7f2 GROOVIE: Clandestiny music
a72ac69b4e GROOVIE: right click to fast forward
58a795c022 GROOVIE: stop audio when fast forwarding
c0f489fe09 GROOVIE: fix op 0x0A o2_bf0on
f1890553ed GROOVIE: fix o2_midicontrol stop command
1dd7a5f66a GROOVIE: code review feedback
bb7975e719 GROOVIE: fix crash when skipping many short sounds
cfd928f296 GROOVIE: cleanup signed/unsigned compiler warnings
02ade73150 GROOVIE: fix compiler errors and warnings
1687b7f08b GROOVIE: fix error missing limits.h
6822711c91 GROOVIE: T11H mouse trap WIP
f3337a4cd2 GROOVIE: cleanup detection.cpp
70386000b6 GROOVIE: detection updates and cleanup
1af1d35540 GROOVIE: fix detection for T7G Mac
328a47dffa GROOVIE: improve cursor/fades fps
5d4303566b GROOVIE: tweak script timer
1a9cd3e900 GROOVIE: fix uses of ENABLE_GROOVIE2
f6c50c7238 GROOVIE: updates to detection and adding demos
b09a330921 GROOVIE: tweak _waitingForInput loop
9b490a0864 GROOVIE: unset _waitingForInput and cleanup
Commit: b5e62ffdafdfc553312a132cf9a5d81319abf0e8
https://github.com/scummvm/scummvm/commit/b5e62ffdafdfc553312a132cf9a5d81319abf0e8
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Update game detection. Add TLC-DE and engine can differ between each game
Changed paths:
engines/groovie/detection.cpp
engines/groovie/groovie.cpp
engines/groovie/script.cpp
engines/groovie/script.h
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 24a3eca514..7a022bd962 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -145,7 +145,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieV2, 1
+ kGroovieT11H, 1
},
// The 11th Hour Windows English
@@ -168,7 +168,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieV2, 1
+ kGroovieT11H, 1
},
// The 11th Hour Macintosh English (Installed)
@@ -180,7 +180,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieV2, 1
+ kGroovieT11H, 1
},
// The 11th Hour DOS Demo English
@@ -191,7 +191,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE,
GUIO5(GUIO_NOLAUNCHLOAD, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieV2, 1
+ kGroovieT11H, 1
},
// The Making of The 11th Hour DOS English
@@ -202,7 +202,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
},
- kGroovieV2, 2
+ kGroovieT11H, 2
},
// The Making of The 11th Hour Macintosh English
@@ -214,7 +214,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieV2, 2
+ kGroovieT11H, 2
},
// The Making of The 11th Hour Macintosh English (Installed)
@@ -226,7 +226,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieV2, 2
+ kGroovieT11H, 2
},
// Clandestiny Trailer DOS English
@@ -237,7 +237,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
},
- kGroovieV2, 3
+ kGroovieCDY, 3
},
// Clandestiny Trailer Macintosh English
@@ -249,7 +249,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieV2, 3
+ kGroovieCDY, 3
},
// Clandestiny Trailer Macintosh English (Installed)
@@ -261,7 +261,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieV2, 3
+ kGroovieCDY, 3
},
// Clandestiny DOS English
@@ -272,7 +272,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
},
- kGroovieV2, 1
+ kGroovieCDY, 1
},
// Uncle Henry's Playhouse PC English
@@ -283,7 +283,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
},
- kGroovieV2, 1
+ kGroovieUHP, 1
},
// Tender Loving Care PC English
@@ -294,7 +294,18 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
},
- kGroovieV2, 1
+ kGroovieTLC, 1
+ },
+
+ // Tender Loving Care PC Deutsch
+ {
+ {
+ "tlc", "deu",
+ AD_ENTRY1s("disk.1", "07fd3381128b0035a72d41548241c82b", 77),
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE,
+ GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
+ },
+ kGroovieTLC, 1
},
{AD_TABLE_END_MARKER, kGroovieT7G, 0}
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 533db607fe..446eef1173 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -78,7 +78,7 @@ GroovieEngine::~GroovieEngine() {
}
Common::Error GroovieEngine::run() {
- if (_gameDescription->version == kGroovieV2 && getPlatform() == Common::kPlatformMacintosh) {
+ if (_gameDescription->version == kGroovieT11H && getPlatform() == Common::kPlatformMacintosh) {
// Load the Mac installer with the lowest priority (in case the user has installed
// the game and has the MIDI folder present; faster to just load them)
Common::Archive *archive = Common::createStuffItArchive("The 11th Hour Installer");
@@ -91,7 +91,10 @@ Common::Error GroovieEngine::run() {
// Initialize the graphics
switch (_gameDescription->version) {
- case kGroovieV2: {
+ case kGroovieT11H:
+ case kGroovieCDY:
+ case kGroovieUHP:
+ case kGroovieTLC: {
// Request the mode with the highest precision available
Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
initGraphics(640, 480, &format);
@@ -107,8 +110,9 @@ Common::Error GroovieEngine::run() {
initGraphics(640, 480);
_pixelFormat = Graphics::PixelFormat::createFormatCLUT8();
break;
+
default:
- break;
+ error("GROOVIE: Unknown Game version. groovie.cpp:run()");
}
// Create debugger. It requires GFX to be initialized
@@ -146,15 +150,20 @@ Common::Error GroovieEngine::run() {
_grvCursorMan = new GrvCursorMan_t7g(_system, _macResFork);
_videoPlayer = new VDXPlayer(this);
break;
- case kGroovieV2:
+
+ case kGroovieT11H:
+ case kGroovieCDY:
+ case kGroovieUHP:
+ case kGroovieTLC:
_resMan = new ResMan_v2();
_grvCursorMan = new GrvCursorMan_v2(_system);
#ifdef ENABLE_GROOVIE2
_videoPlayer = new ROQPlayer(this);
#endif
break;
+
default:
- break;
+ error("GROOVIE: Unknown Game version. groovie.cpp:run()");
}
// Detect ScummVM Music Enhancement Project presence (T7G only)
@@ -190,7 +199,7 @@ Common::Error GroovieEngine::run() {
filename = "demo.grv";
else if (getPlatform() == Common::kPlatformMacintosh)
filename = "script.grv"; // Stored inside the executable's resource fork
- } else if (_gameDescription->version == kGroovieV2) {
+ } else if (_gameDescription->version != kGroovieT7G) {
// Open the disk index
Common::File disk;
if (!disk.open(filename)) {
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 5d5f606fe1..a15a63d744 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -71,11 +71,9 @@ Script::Script(GroovieEngine *vm, EngineVersion version) :
_version(version), _random("GroovieScripts") {
// Initialize the opcode set depending on the engine version
- switch (version) {
- case kGroovieT7G:
+ if (version == kGroovieT7G) {
_opcodes = _opcodesT7G;
- break;
- case kGroovieV2:
+ } else {
_opcodes = _opcodesV2;
break;
default:
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index 2a09cc4a0f..75d5484ec5 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -38,6 +38,14 @@ struct Surface;
namespace Groovie {
+enum EngineVersion {
+ kGroovieT7G,
+ kGroovieT11H,
+ kGroovieCDY,
+ kGroovieUHP,
+ kGroovieTLC
+};
+
class CellGame;
class Debugger;
Commit: 46ebbe80008eda79611a090db3ed03277a1ec51f
https://github.com/scummvm/scummvm/commit/46ebbe80008eda79611a090db3ed03277a1ec51f
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Support of TLC ROQ video files
Changed paths:
engines/groovie/roq.cpp
engines/groovie/roq.h
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index aadbd44b2e..531ac7551b 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -50,7 +50,8 @@ ROQPlayer::ROQPlayer(GroovieEngine *vm) :
VideoPlayer(vm), _codingTypeCount(0),
_fg(&_vm->_graphicsMan->_foreground),
_bg(&_vm->_graphicsMan->_background),
- _firstFrame(true) {
+ _firstFrame(true),
+ _origX(0), _origY(0) {
// Create the work surfaces
_currBuf = new Graphics::Surface();
@@ -65,6 +66,11 @@ ROQPlayer::~ROQPlayer() {
delete _prevBuf;
}
+void ROQPlayer::setOrigin(int16 x, int16 y) {
+ _origX = x;
+ _origY = y;
+}
+
uint16 ROQPlayer::loadInternal() {
if (DebugMan.isDebugChannelEnabled(kDebugVideo)) {
int8 i;
@@ -91,6 +97,10 @@ uint16 ROQPlayer::loadInternal() {
return 0;
}
+ debugC(1, kDebugVideo, "Groovie::ROQ: First Block type = 0x%02X", blockHeader.type);
+ debugC(1, kDebugVideo, "Groovie::ROQ: First Block size = 0x%08X", blockHeader.size);
+ debugC(1, kDebugVideo, "Groovie::ROQ: First Block param = 0x%04X", blockHeader.param);
+
// Verify the file signature
if (blockHeader.type != 0x1084) {
return 0;
@@ -112,7 +122,7 @@ uint16 ROQPlayer::loadInternal() {
// Hardcoded FPS
return 30;
- } else if (blockHeader.size == (uint32)-1) {
+ } else if (blockHeader.size == (uint32)-1 || blockHeader.size == 0) {
// Set the offset scaling to 1
_offScale = 1;
@@ -128,11 +138,14 @@ void ROQPlayer::buildShowBuf() {
if (_alpha)
_fg->copyFrom(*_bg);
- for (int line = 0; line < _bg->h; line++) {
+ for (int line = _origY; line < _bg->h; line++) {
uint32 *out = _alpha ? (uint32 *)_fg->getBasePtr(0, line) : (uint32 *)_bg->getBasePtr(0, line);
- uint32 *in = (uint32 *)_currBuf->getBasePtr(0, line / _scaleY);
+ uint32 *in = (uint32 *)_currBuf->getBasePtr(0, (line - _origY) / _scaleY);
- for (int x = 0; x < _bg->w; x++) {
+ // Apply offset
+ out += _origX;
+
+ for (int x = _origX; x < _bg->w; x++) {
// Copy a pixel, checking the alpha channel first
if (_alpha && !(*in & 0xFF))
out++;
@@ -193,8 +206,12 @@ bool ROQPlayer::playFrameInternal() {
}
// Report the end of the video if we reached the end of the file or if we
- // just wanted to play one frame.
- return _file->eos() || playFirstFrame();
+ // just wanted to play one frame. Also reset origin for next video / image
+ if (_file->eos() || playFirstFrame()) {
+ _origX = _origY = 0;
+ return true;
+ }
+ return false;
}
bool ROQPlayer::readBlockHeader(ROQBlockHeader &blockHeader) {
@@ -314,6 +331,12 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
_prevBuf->create(width, height, _vm->_pixelFormat);
}
+ // Hack: Detect a video with interlaced black lines, by checking its height compared to width
+ if (height <= width / 3) {
+ _offScale = 2;
+ }
+ debugC(1, kDebugVideo, "Groovie::ROQ: widht=%d, height=%d, scaleX=%d, scaleY=%d, _offScale=%d", width, height, _scaleX, _scaleY, _offScale);
+
// Switch from/to fullscreen, if needed
if (_bg->h != 480 && height == 480)
_vm->_graphicsMan->switchToFullScreen(true);
diff --git a/engines/groovie/roq.h b/engines/groovie/roq.h
index 11b97ef84e..9971b4584a 100644
--- a/engines/groovie/roq.h
+++ b/engines/groovie/roq.h
@@ -38,7 +38,8 @@ struct ROQBlockHeader {
class ROQPlayer : public VideoPlayer {
public:
ROQPlayer(GroovieEngine *vm);
- ~ROQPlayer() override;
+ ~ROQPlayer();
+ void setOrigin(int16 x, int16 y);
protected:
uint16 loadInternal() override;
@@ -64,6 +65,9 @@ private:
void paint8(byte i, int destx, int desty);
void copy(byte size, int destx, int desty, int offx, int offy);
+ // Origin
+ int16 _origX, _origY;
+
// Block coding type
byte getCodingType();
uint16 _codingType;
Commit: 1e2c395d12d8503f088e2bff31490d196d019113
https://github.com/scummvm/scummvm/commit/1e2c395d12d8503f088e2bff31490d196d019113
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Add printfunction opcode for V2 engine
Changed paths:
engines/groovie/groovie.cpp
engines/groovie/script.cpp
engines/groovie/script.h
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 446eef1173..5a259e115a 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -155,6 +155,7 @@ Common::Error GroovieEngine::run() {
case kGroovieCDY:
case kGroovieUHP:
case kGroovieTLC:
+ _font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
_resMan = new ResMan_v2();
_grvCursorMan = new GrvCursorMan_v2(_system);
#ifdef ENABLE_GROOVIE2
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index a15a63d744..19ecfbb458 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -1202,7 +1202,9 @@ void Script::o_loadgame() {
debugC(1, kDebugScript, "LOADGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot);
loadgame(slot);
- _vm->_system->fillScreen(0);
+ if (_version == kGroovieT7G) {
+ _vm->_system->fillScreen(0);
+ }
}
void Script::o_savegame() {
@@ -1734,6 +1736,33 @@ void Script::o_stub59() {
debugC(1, kDebugScript, "STUB59: 0x%04X 0x%02X", val1, val2);
}
+void Script::o2_printstring() {
+ uint16 posx = readScript16bits();
+ uint16 posy = readScript16bits();
+ uint8 colr = readScript8bits();
+ uint8 colg = readScript8bits();
+ uint8 colb = readScript8bits();
+ uint32 col = _vm->_pixelFormat.RGBToColor(colr, colg, colb);
+ char message[20];
+ memset(message, 0, sizeof(message));
+
+ for (int i = 0; i < 19; i++) {
+ if (_variables[i] > 0) {
+ message[i] = _variables[i] + 0x30;
+ }
+ }
+
+ debugC(1, kDebugScript, "PRINTSTRING (%d, %d): %s", posx, posy, message);
+
+ Graphics::Surface *gamescreen = _vm->_system->lockScreen();
+ _vm->_font->drawString(gamescreen, message, posx, posy, 640, col, Graphics::kTextAlignLeft);
+ _vm->_system->unlockScreen();
+ _vm->_graphicsMan->change(); // Force Update screen after step
+
+ // 42 Bytes unknown
+ _currentInstruction += 39;
+}
+
void Script::o2_playsong() {
uint32 fileref = readScript32bits();
debugC(1, kDebugScript, "PlaySong(0x%08X): Play xmidi file", fileref);
@@ -1894,7 +1923,7 @@ Script::OpcodeFunc Script::_opcodesT7G[NUM_OPCODES] = {
&Script::o_copyrecttobg,
&Script::o_restorestkpnt, // 0x38
&Script::o_obscureswap,
- &Script::o_printstring,
+ &Script::o2_printstring,
&Script::o_hotspot_slot,
&Script::o_checkvalidsaves, // 0x3C
&Script::o_resetvars,
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index 75d5484ec5..980e4ccb00 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -237,6 +237,7 @@ private:
void o_stub56();
void o_stub59();
+ void o2_printstring();
void o2_playsong();
void o2_setbackgroundsong();
void o2_videofromref();
Commit: d0f247f7b0b3c7c4d66d4a4bfbb64ebe3a175384
https://github.com/scummvm/scummvm/commit/d0f247f7b0b3c7c4d66d4a4bfbb64ebe3a175384
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Add cursor hotspots for V2 engine
Changed paths:
engines/groovie/cursor.cpp
engines/groovie/cursor.h
diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp
index 6d17e392ad..705bb16bef 100644
--- a/engines/groovie/cursor.cpp
+++ b/engines/groovie/cursor.cpp
@@ -259,15 +259,14 @@ Cursor_v2::Cursor_v2(Common::File &file) {
_numFrames = file.readUint16LE();
_width = file.readUint16LE();
_height = file.readUint16LE();
+ _hotspotX = file.readUint16LE();
+ _hotspotY = file.readUint16LE();
_img = new byte[_width * _height * _numFrames * 4];
- debugC(1, kDebugCursor, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames);
+ debugC(1, kDebugCursor, "Groovie::Cursor: width: %d, height: %d, frames:%d, hotspot: %d, %d", _width, _height, _numFrames, _hotspotX, _hotspotY);
- uint16 tmp16 = file.readUint16LE();
- debugC(5, kDebugCursor, "hotspot x?: %d\n", tmp16);
- tmp16 = file.readUint16LE();
- debugC(5, kDebugCursor, "hotspot y?: %d\n", tmp16);
+ uint16 tmp16;
int loop2count = file.readUint16LE();
debugC(5, kDebugCursor, "loop2count?: %d\n", loop2count);
for (int l = 0; l < loop2count; l++) {
@@ -386,7 +385,7 @@ void Cursor_v2::enable() {
void Cursor_v2::showFrame(uint16 frame) {
int offset = _width * _height * frame * 4;
- CursorMan.replaceCursor((const byte *)(_img + offset), _width, _height, _width >> 1, _height >> 1, 0, false, &_format);
+ CursorMan.replaceCursor((const byte *)(_img + offset), _width, _height, _hotspotX, _hotspotY, 0, false, &_format);
}
diff --git a/engines/groovie/cursor.h b/engines/groovie/cursor.h
index 07e0400dfd..85548f76ee 100644
--- a/engines/groovie/cursor.h
+++ b/engines/groovie/cursor.h
@@ -42,6 +42,8 @@ public:
protected:
uint16 _width;
uint16 _height;
+ uint16 _hotspotX;
+ uint16 _hotspotY;
uint16 _numFrames;
};
Commit: 1a006ea3e3b303e83755d61a2cb808e0124ce4eb
https://github.com/scummvm/scummvm/commit/1a006ea3e3b303e83755d61a2cb808e0124ce4eb
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Add support for TLC
Changed paths:
A engines/groovie/tlcgame.cpp
A engines/groovie/tlcgame.h
engines/groovie/groovie.cpp
engines/groovie/groovie.h
engines/groovie/module.mk
engines/groovie/script.cpp
engines/groovie/script.h
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 5a259e115a..96bd87f2eb 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -54,6 +54,19 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) :
_graphicsMan(NULL), _macResFork(NULL), _waitingForInput(false), _font(NULL),
_spookyMode(false) {
+ // Initialize the custom debug levels
+ DebugMan.addDebugChannel(kDebugVideo, "Video", "Debug video and audio playback");
+ DebugMan.addDebugChannel(kDebugResource, "Resource", "Debug resource management");
+ DebugMan.addDebugChannel(kDebugScript, "Script", "Debug the scripts");
+ DebugMan.addDebugChannel(kDebugUnknown, "Unknown", "Report values of unknown data in files");
+ DebugMan.addDebugChannel(kDebugHotspots, "Hotspots", "Show the hotspots");
+ DebugMan.addDebugChannel(kDebugCursor, "Cursor", "Debug cursor decompression / switching");
+ DebugMan.addDebugChannel(kDebugMIDI, "MIDI", "Debug MIDI / XMIDI files");
+ DebugMan.addDebugChannel(kDebugScriptvars, "Scriptvars", "Print out any change to script variables");
+ DebugMan.addDebugChannel(kDebugCell, "Cell", "Debug the cell game (in the microscope)");
+ DebugMan.addDebugChannel(kDebugFast, "Fast", "Play videos quickly, with no sound (unstable)");
+ DebugMan.addDebugChannel(kDebugTlcGame, "TlcGame", "Debug special TLC commands");
+
// Adding the default directories
const Common::FSNode gameDataDir(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "groovie");
diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h
index 26d4af116b..0737305580 100644
--- a/engines/groovie/groovie.h
+++ b/engines/groovie/groovie.h
@@ -68,7 +68,8 @@ enum DebugLevels {
kDebugMIDI = 1 << 6,
kDebugScriptvars = 1 << 7,
kDebugCell = 1 << 8,
- kDebugFast = 1 << 9
+ kDebugFast = 1 << 9,
+ kDebugTlcGame = 1 << 10
// the current limitation is 32 debug levels (1 << 31 is the last one)
// but some are used by system, so avoid high values.
};
diff --git a/engines/groovie/module.mk b/engines/groovie/module.mk
index edeb9962af..dfe764a255 100644
--- a/engines/groovie/module.mk
+++ b/engines/groovie/module.mk
@@ -18,7 +18,8 @@ MODULE_OBJS := \
ifdef ENABLE_GROOVIE2
MODULE_OBJS += \
- roq.o
+ roq.o \
+ tlcgame.o
endif
# This module can be built as a plugin
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 19ecfbb458..2146dd61c2 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -30,6 +30,7 @@
#include "groovie/player.h"
#include "groovie/resource.h"
#include "groovie/saveload.h"
+#include "groovie/tlcgame.h"
#include "common/archive.h"
#include "common/config-manager.h"
@@ -68,7 +69,7 @@ const byte t7gMidiInitScript[] = {
Script::Script(GroovieEngine *vm, EngineVersion version) :
_code(NULL), _savedCode(NULL), _stacktop(0), _debugger(NULL), _vm(vm),
_videoFile(NULL), _videoRef(0), _staufsMove(NULL), _lastCursor(0xff),
- _version(version), _random("GroovieScripts") {
+ _version(version), _random("GroovieScripts"), _tlcGame(0) {
// Initialize the opcode set depending on the engine version
if (version == kGroovieT7G) {
@@ -115,6 +116,9 @@ Script::~Script() {
delete[] _savedCode;
delete _videoFile;
+
+ delete _staufsMove;
+ delete _tlcGame;
}
void Script::setVariable(uint16 variablenum, byte value) {
@@ -753,6 +757,11 @@ void Script::o_bf5on() { // 0x0A
void Script::o_inputloopstart() { //0x0B
debugC(5, kDebugScript, "Input loop start");
+ // For TLC the regions for many questions are in an extra database. Reset internal region counters
+ if (_version == kGroovieTLC && _tlcGame != NULL) {
+ _tlcGame->getRegionRewind();
+ }
+
// Reset the input action and the mouse cursor
_inputAction = -1;
_newCursorStyle = 5;
@@ -798,6 +807,14 @@ void Script::o_hotspot_rect() {
uint16 address = readScript16bits();
uint8 cursor = readScript8bits();
+ // TLC: The regions for many questions are in an extra database
+ if (_version == kGroovieTLC && left == 0 && top == 0 && right == 0 && bottom == 0 && _tlcGame != NULL) {
+ if (_tlcGame->getRegionNext(left, top, right, bottom) < 0) {
+ debugC(5, kDebugScript, "HOTSPOT-RECT(x,x,x,x) @0x%04X cursor=%d SKIPPED", left, top, right, bottom, address, cursor);
+ return;
+ }
+ }
+
debugC(5, kDebugScript, "HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d", left, top, right, bottom, address, cursor);
// Mark the specified rectangle
@@ -1477,6 +1494,8 @@ void Script::o_hotspot_slot() {
}
}
+// Checks valid save games. Even for TLC (uses only 4 user save games) the function
+// checks for 10 save games.
void Script::o_checkvalidsaves() {
debugC(1, kDebugScript, "CHECKVALIDSAVES");
@@ -1848,10 +1867,47 @@ void Script::o2_setvideoskip() {
debugC(1, kDebugScript, "SetVideoSkip (0x%04X)", _videoSkipAddress);
}
+// This function depends on the actual game played. So it is different for
+// T7G, 11H, TLC, ...
void Script::o2_stub42() {
uint8 arg = readScript8bits();
- // TODO: Switch with 5 cases (0 - 5). Anything above 5 is a NOP
- debugC(1, kDebugScript, "STUB42 (0x%02X)", arg);
+
+ switch (_version) {
+ case kGroovieTLC:
+ if (_tlcGame == NULL) {
+ _tlcGame = new TlcGame();
+ _tlcGame->setVariables(_variables);
+ }
+ switch (arg) {
+ case 0:
+ debugC(1, kDebugScript, "Op42 (0x%02X): TLC Regions", arg);
+ _tlcGame->opRegions();
+ break;
+
+ case 1:
+ debugC(1, kDebugScript, "Op42 (0x%02X): TLC Exit Polls", arg);
+ _tlcGame->opExitPoll();
+ break;
+
+ case 2:
+ _tlcGame->opFlags();
+ debugC(1, kDebugScript, "Op42 (0x%02X): TLC TATFlags", arg);
+ break;
+
+ case 3:
+ debugC(1, kDebugScript, "Op42 (0x%02X): TLC TATs (TODO)", arg);
+ _tlcGame->opTat();
+ break;
+
+ default:
+ debugC(1, kDebugScript, "Op42 (0x%02X): TLC Invalid -> NOP", arg);
+ }
+ break;
+
+ default:
+ debugC(1, kDebugScript, "STUB42 (0x%02X)", arg);
+ warning("OpCode 0x42 for current game not implemented yet.");
+ }
}
void Script::o2_stub52() {
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index 980e4ccb00..a4b2e4a6e8 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -48,6 +48,8 @@ enum EngineVersion {
class CellGame;
class Debugger;
+class GroovieEngine;
+class TlcGame;
class Script {
friend class Debugger;
@@ -133,7 +135,9 @@ private:
Common::String _debugString;
uint16 _oldInstruction;
+ // Special classes depending on played game
CellGame *_staufsMove;
+ TlcGame *_tlcGame;
// Helper functions
uint8 getCodeByte(uint16 address);
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
new file mode 100644
index 0000000000..40e0678df4
--- /dev/null
+++ b/engines/groovie/tlcgame.cpp
@@ -0,0 +1,1194 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "groovie/tlcgame.h"
+#include "groovie/groovie.h"
+
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/macresman.h"
+#include "common/translation.h"
+
+namespace Groovie {
+
+// This a list of files for background music. These list is hard-coded in the TLC player.
+const Common::String kTlcMidiFiles[] = {"ep01epm.mpg", "ep01tatm.mpg", "amb_hs.mpg", "amb_mr.mpg", "amb_kr.mpg", "amb_mo.mpg", "music_rc.mpg", "amb_ds.mpg", "amb_ds3.mpg", "amb_jr.mpg", "amb_mr4.mpg", "amb_jr4.mpg", "amb_jr2.mpg", "amb_kr2.mpg", "amb_mr2.mpg", "amb_br.mpg", "amb_ds2.mpg", "amb_jr3.mpg", "amb_ds4.mpg", "amb_kr3.mpg", "amb_to1.mpg", "amb_to2.mpg", "ep02epm.mpg", "ep02tatm.mpg", "ep03epm.mpg", "ep03tatm.mpg", "ep04epm.mpg", "ep04tatm.mpg", "ep05epm.mpg", "ep05tatm.mpg", "ep06epm.mpg", "ep06tatm.mpg", "ep07epm.mpg", "ep07tatm.mpg", "ep08epm.mpg", "ep08tatm.mpg", "ep09epm.mpg", "ep09tatm.mpg", "ep10epm.mpg", "ep10tatm.mpg", "ep11epm.mpg", "ep11tatm.mpg", "ep12epm.mpg", "ep12tatm.mpg", "ep13epm.mpg", "ep13tatm.mpg", "ep14epm.mpg", "ep14tatm.mpg", "ep15epm.mpg", "ep15tatm.mpg" };
+const uint8 kTlcEpQuestToPlay[] = { 0x0E, 0x0F, 0x0B, 0x10, 0x11, 0x12, 0x0C, 0x0C, 0x09, 0x06, 0x0F, 0x0C, 0x0B, 0x0D, 0x0D };
+
+
+TlcGame::TlcGame() :
+ _numRegionHeaders(0), _regionHeader(NULL), _curQuestNumAnswers(-1), _epQuestionsData(NULL),
+ _random("GroovieTlcGame"), _scriptVariables(NULL),
+ _tatHeaders(NULL), _tatQuestions(NULL) {
+}
+
+
+TlcGame::~TlcGame() {
+ delete[] _regionHeader;
+ delete[] _epQuestionsData;
+ delete[] _tatHeaders;
+ delete[] _tatQuestions;
+}
+
+
+void TlcGame::setVariables(byte *scriptVariables) {
+ _scriptVariables = scriptVariables;
+}
+
+// This function is mainly for debugging purpose
+void inline TlcGame::setScriptVar(uint16 var, byte value) {
+ _scriptVariables[var] = value;
+ debugC(5, kDebugTlcGame, "script variable[0x%03X] = %d (0x%04X)", var, value, value);
+}
+
+void inline TlcGame::setScriptVar16(uint16 var, uint16 value) {
+ _scriptVariables[var] = value & 0xFF;
+ _scriptVariables[var + 1] = (value >> 8) & 0xFF;
+ debugC(5, kDebugTlcGame, "script variable[0x%03X, 0x%03X] = %d (0x%02X, 0x%02X)", var, var+1, value, _scriptVariables[var], _scriptVariables[var+1]);
+}
+
+uint16 inline TlcGame::getScriptVar16(uint16 var) {
+ uint16 value;
+
+ value = _scriptVariables[var];
+ value += _scriptVariables[var + 1] << 8;
+
+ return value;
+}
+
+
+void TlcGame::opRegions() {
+ if (_scriptVariables[0x1A] == 1) {
+ regionsInit();
+ setScriptVar(0x1A, 0);
+
+ } else {
+ regionsLoad();
+ }
+}
+
+
+// Loads the header of the file regions.rle into memory. This files contains
+// a database for the GUI positions (regions) of all answers for the questions.
+void TlcGame::regionsInit() {
+ Common::SeekableReadStream *regionsfile = 0;
+
+ _curQuestNumAnswers = -1;
+
+ // Check if header was already loaded.
+ if (_regionHeader != NULL) {
+ debugC(1, kDebugTlcGame, "TLC:RegionsInit: Regions already loaded.");
+ return;
+ }
+
+ regionsfile = SearchMan.createReadStreamForMember("SYSTEM/REGIONS.RLE");
+ if (!regionsfile) {
+ error("TLC:RegionsInit: Could not open 'SYSTEM/REGIONS.RLE'");
+ }
+
+ // Read number of question entries
+ _numRegionHeaders = regionsfile->readUint32LE();
+ if (regionsfile->eos()) {
+ error("TLC:RegionsInit: Error reading numEntries from 'REGIONS.RLE'");
+ }
+
+ // Read header for each question entry
+ _regionHeader = new TlcRegionsHeader[_numRegionHeaders];
+ for (int i = 0; i < _numRegionHeaders; i++) {
+ regionsfile->read(&_regionHeader[i].name, sizeof(TlcRegionsHeader::name));
+ regionsfile->seek(25 - sizeof(TlcRegionsHeader::name), SEEK_CUR);
+ _regionHeader[i].numAnswers = regionsfile->readUint32LE();
+ _regionHeader[i].offset = regionsfile->readUint32LE();
+ }
+
+ if (regionsfile->eos()) {
+ error("TLC:RegionsInit: Error reading headers from 'REGIONS.RLE'");
+ }
+
+ delete regionsfile;
+
+ debugC(1, kDebugTlcGame, "TLC:RegionsInit: Loaded %d region headers", _numRegionHeaders);
+}
+
+
+// Loads the specific regions for one questions.
+void TlcGame::regionsLoad() {
+ Common::SeekableReadStream *regionsfile = 0;
+ int nameLen;
+ int i;
+ char questName[sizeof(TlcRegionsHeader::name)];
+
+ // Check if initRegions was called before
+ if (_regionHeader == NULL) {
+ error("TLC:RegionsLoad: initRegions was not called.");
+ }
+
+ // Open regions.rle
+ regionsfile = SearchMan.createReadStreamForMember("SYSTEM/REGIONS.RLE");
+ if (!regionsfile) {
+ error("TLC:RegionsLoad: Could not open 'SYSTEM/REGIONS.RLE'");
+ }
+
+ // Get length of question name from variables
+ nameLen = _scriptVariables[0x1B] * 10 + _scriptVariables[0x1C];
+ if (nameLen >= sizeof(TlcRegionsHeader::name)) {
+ error("TLC:RegionsLoad: Name to long for loadRegions!");
+ }
+
+ // Decoded and copy name from variables
+ for (i = 0; i < nameLen; i++) {
+ setScriptVar(0x1D + i, _scriptVariables[0x1D + i] + 0x30);
+ questName[i] = _scriptVariables[0x1D + i];
+ }
+ questName[i] = '\0';
+
+ // Search for the question entry
+ for (i = 0; i <= _numRegionHeaders; i++) {
+ if (strcmp(questName, _regionHeader[i].name) == 0) {
+
+ // move to coordinates for this question
+ regionsfile->seek(_regionHeader[i].offset, SEEK_SET);
+
+ // Copy region of each answer
+ _curQuestNumAnswers = _regionHeader[i].numAnswers;
+ for (int iAns = 0; iAns < _curQuestNumAnswers; iAns++) {
+ _curQuestRegions[iAns].left = regionsfile->readUint16LE();
+ _curQuestRegions[iAns].top = regionsfile->readUint16LE();
+ _curQuestRegions[iAns].right = regionsfile->readUint16LE();
+ _curQuestRegions[iAns].bottom = regionsfile->readUint16LE();
+ }
+
+ delete regionsfile;
+
+ debugC(1, kDebugTlcGame, "TLC:RegionsLoad: Loaded %d regions for question %s", _curQuestNumAnswers, questName);
+ return;
+ }
+ }
+
+ // If we got here, the entry was not found
+ error("TLC:RegionsLoad: Question '%s' was not found", questName);
+ delete regionsfile; // unreachable
+}
+
+
+void TlcGame::getRegionRewind() {
+ _curAnswerIndex = 0;
+}
+
+
+int TlcGame::getRegionNext(uint16 &left, uint16 &top, uint16 &right, uint16 &bottom) {
+
+ // Check if initialization was done
+ if (_curQuestNumAnswers < 0) {
+ warning("TLC:GetRegionNext: Uninitialized call to getRegionNext.");
+ return -1;
+ }
+
+ // Check if there is another region for this answer
+ if (_curAnswerIndex >= _curQuestNumAnswers) {
+ return -1;
+ }
+
+ // return next region
+ left = _curQuestRegions[_curAnswerIndex].left;
+ top = _curQuestRegions[_curAnswerIndex].top;
+ right = _curQuestRegions[_curAnswerIndex].right;
+ bottom = _curQuestRegions[_curAnswerIndex].bottom;
+ _curAnswerIndex++;
+
+ return 0;
+}
+
+
+void TlcGame::opExitPoll() {
+ switch (_scriptVariables[0]) {
+ case 0x00:
+ epInit();
+ break;
+ case 0x01:
+ epSelectNextQuestion();
+ break;
+ case 0x02:
+ epResultQuestion();
+ break;
+ case 0x03:
+ epResultEpisode();
+ break;
+ case 0x04:
+ // Load internal score-bin 4 and 5
+ _epScoreBin[4] = _scriptVariables[1];
+ _epScoreBin[5] = _scriptVariables[2];
+ setScriptVar(0, 0x09);
+ debugC(1, kDebugTlcGame, "TLC:EpInitBins: Init bins: bin[4]=%d, bin[5]=%d", _epScoreBin[4], _epScoreBin[5]);
+
+ break;
+ default:
+ // Unknown subcommand
+ setScriptVar(0, 0x08);
+ }
+}
+
+
+void TlcGame::epInit() {
+ Common::SeekableReadStream *epaidbfile = 0;
+ int i;
+ int numEpisodesInDB;
+ uint32 scoreDataOffset;
+
+ // Delete previous question data
+ delete[] _epQuestionsData;
+
+ // Get current episode from script variables
+ _epEpisodeIdx = _scriptVariables[0x01] - 0x31;
+ _epQuestionIdx = 0;
+
+ // Init score bin 0..3 of overall 6
+ _epScoreBin[0] = 0;
+ _epScoreBin[1] = 0;
+ _epScoreBin[2] = 0;
+ _epScoreBin[3] = 0;
+ if (_epEpisodeIdx == 0) {
+ _epScoreBin[4] = 0;
+ _epScoreBin[5] = 0;
+ }
+
+ // Open epaidb.rle
+ epaidbfile = SearchMan.createReadStreamForMember("SYSTEM/EPAIDB.RLE");
+ if (!epaidbfile) {
+ error("TLC:EpInit: Could not open 'SYSTEM/EPAIDB.RLE'");
+ }
+
+ // Read number of episodes. It is not dynamic because the result functions highly depend on the database
+ // Thus we knew, we must check the result functions, if this would change (most propably not)
+ numEpisodesInDB = epaidbfile->readSint32LE();
+ if (numEpisodesInDB != GROOVIE_TLC_MAX_EPSIODES) {
+ error("TLC:EpInit: Unexpected number of episodes in epaidb.rle. Read: %d, expected: %d", numEpisodesInDB, GROOVIE_TLC_MAX_EPSIODES);
+ }
+
+ // read header of ep score data of current episode TO
+ if (_epEpisodeIdx < 0 || _epEpisodeIdx >= numEpisodesInDB) {
+ error("TLC:EpInit: Requested episode out of range (0..%d)", GROOVIE_TLC_MAX_EPSIODES-1);
+ }
+ epaidbfile->seek((_epEpisodeIdx * 8) + 4, SEEK_SET);
+ _epQuestionsInEpisode = epaidbfile->readSint32LE();
+ scoreDataOffset = epaidbfile->readSint32LE();
+
+ // Load scores for this episode.
+ _epQuestionsData = new TlcEpQuestionData[_epQuestionsInEpisode];
+ epaidbfile->seek(scoreDataOffset, SEEK_SET);
+
+ for (i = 0; i < _epQuestionsInEpisode; i++) {
+ _epQuestionsData[i].questionUsed = false;
+ _epQuestionsData[i].questionScore = epaidbfile->readUint32LE();
+ }
+
+ if (epaidbfile->eos()) {
+ error("TLC:EpInit: Error reading scores from 'REGIONS.RLE'");
+ }
+
+ // Close file
+ delete epaidbfile;
+
+ // Initialize register 0x01 with values from database
+ if (_epEpisodeIdx >= sizeof(kTlcEpQuestToPlay)) {
+ error("TLC:EpInit: EposdeIdx out of range for init data of reg0x01");
+ }
+ setScriptVar(2, kTlcEpQuestToPlay[_epEpisodeIdx] + 0x30);
+
+ // Return code
+ setScriptVar(0, 0x09);
+
+ debugC(1, kDebugTlcGame, "TLC:EpInit: For episode %d loaded %d question scores. Will play %d questions", _epEpisodeIdx+1, _epQuestionsInEpisode, kTlcEpQuestToPlay[_epEpisodeIdx]);
+}
+
+
+void TlcGame::epSelectNextQuestion() {
+ _epQuestionIdx++;
+ _epQuestionNumOfPool = -1;
+
+ /* check if there is a dedicated quesition at this position */
+ switch (_epEpisodeIdx) { // _epEpsiodeIdx: 0..14
+ case 1:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 5; break;
+ case 7: _epQuestionNumOfPool = 16; break;
+ case 11: _epQuestionNumOfPool = 18; break;
+ }
+ break;
+ case 2:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 7; break;
+ case 7: _epQuestionNumOfPool = 13; break;
+ case 11: _epQuestionNumOfPool = 16; break;
+ }
+ break;
+ case 3:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 8; break;
+ case 11: _epQuestionNumOfPool = 17; break;
+ }
+ break;
+ case 4:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 18; break;
+ case 7: _epQuestionNumOfPool = 22; break;
+ case 11: _epQuestionNumOfPool = 21; break;
+ }
+ break;
+ case 5:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 22; break;
+ case 11: _epQuestionNumOfPool = 24; break;
+ }
+ break;
+ case 6:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 12; break;
+ case 7: _epQuestionNumOfPool = 14; break;
+ case 11: _epQuestionNumOfPool = 18; break;
+ }
+ break;
+ case 7:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 15; break;
+ case 7: _epQuestionNumOfPool = 16; break;
+ case 11: _epQuestionNumOfPool = 17; break;
+ }
+ break;
+ case 8:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 11; break;
+ case 7: _epQuestionNumOfPool = 14; break;
+ case 9: _epQuestionNumOfPool = 15; break;
+ }
+ break;
+ case 9:
+ switch (_epQuestionIdx) {
+ case 2: _epQuestionNumOfPool = 2; break;
+ case 4: _epQuestionNumOfPool = 8; break;
+ case 6: _epQuestionNumOfPool = 11; break;
+ }
+ break;
+ case 10:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 15; break;
+ case 7: _epQuestionNumOfPool = 16; break;
+ case 11: _epQuestionNumOfPool = 17; break;
+ }
+ break;
+ case 11:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 14; break;
+ case 7: _epQuestionNumOfPool = 15; break;
+ case 11: _epQuestionNumOfPool = 17; break;
+ }
+ break;
+ case 12:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 12; break;
+ case 7: _epQuestionNumOfPool = 14; break;
+ case 11: _epQuestionNumOfPool = 16; break;
+ }
+ break;
+ case 13:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 15; break;
+ case 7: _epQuestionNumOfPool = 18; break;
+ case 11: _epQuestionNumOfPool = 19; break;
+ }
+ break;
+ case 14:
+ switch (_epQuestionIdx) {
+ case 3: _epQuestionNumOfPool = 1; break;
+ case 7: _epQuestionNumOfPool = 14; break;
+ case 11: _epQuestionNumOfPool = 16; break;
+ }
+ break;
+ }
+
+ // get a random question if there was no predefined
+ if (_epQuestionNumOfPool == -1) {
+ do {
+ _epQuestionNumOfPool = _random.getRandomNumber(32767) / 2000;
+ } while (_epQuestionNumOfPool < 1 || _epQuestionNumOfPool > _epQuestionsInEpisode);
+
+ debugC(1, kDebugTlcGame, "TLC:EpSelNextQuest: Question %d: Selected question %d/%d by random.", _epQuestionIdx, _epQuestionNumOfPool, _epQuestionsInEpisode);
+
+ } else {
+ debugC(1, kDebugTlcGame, "TLC:EpSelNextQuest: Question %d: Selected question %d/%d by predefined data.", _epQuestionIdx, _epQuestionNumOfPool, _epQuestionsInEpisode);
+ }
+
+ // Choose next question, if question was already played
+ while (_epQuestionsData[_epQuestionNumOfPool - 1].questionUsed) {
+ _epQuestionNumOfPool++;
+ if (_epQuestionNumOfPool > _epQuestionsInEpisode) {
+ _epQuestionNumOfPool = 1;
+ }
+ }
+ _epQuestionsData[_epQuestionNumOfPool - 1].questionUsed = true;
+ debugC(1, kDebugTlcGame, "TLC:EpSelNextQuest: Question %d: Forward to question %d/%d. (used-flag)", _epQuestionIdx, _epQuestionNumOfPool, _epQuestionsInEpisode);
+
+ // write selected episode and question to script variables
+ setScriptVar(4, (_epEpisodeIdx + 1) / 10);
+ setScriptVar(5, (_epEpisodeIdx + 1) % 10);
+ setScriptVar(6, _epQuestionNumOfPool / 10);
+ setScriptVar(7, _epQuestionNumOfPool % 10);
+
+ // Set return value
+ setScriptVar(0, 9);
+
+ // Debug output
+ {
+ uint32 dbgQScore = _epQuestionsData[_epQuestionNumOfPool - 1].questionScore;
+ debugC(1, kDebugTlcGame, "TLC:EpSelNextQuest: Bins for Answers: %d %d %d %d %d %d %d %d",
+ (dbgQScore >> 28) & 0xf, (dbgQScore >> 24) & 0xf, (dbgQScore >> 20) & 0xf, (dbgQScore >> 16) & 0xf,
+ (dbgQScore >> 12) & 0xf, (dbgQScore >> 8) & 0xf, (dbgQScore >> 4) & 0xf, (dbgQScore) & 0xf);
+ }
+
+}
+
+
+void TlcGame::epResultQuestion() {
+ int answerIdx, shift, scoreBinId;
+ int specialReg;
+ uint32 questionScore;
+
+ // Add special question results here
+ specialReg = -1;
+ switch (_epEpisodeIdx) { // _epEpsiodeIdx: 0..14
+ case 1:
+ switch (_epQuestionNumOfPool) {
+ case 5: specialReg = 0x09; break;
+ case 16: specialReg = 0x0A; break;
+ case 18: specialReg = 0x0B; break;
+ }
+ break;
+ case 2:
+ switch (_epQuestionNumOfPool) {
+ case 7: specialReg = 0x09; break;
+ case 13: specialReg = 0x0A; break;
+ case 16: specialReg = 0x0B; break;
+ }
+ break;
+ case 3:
+ switch (_epQuestionNumOfPool) {
+ case 8: specialReg = 0x09; break;
+ case 17: specialReg = 0x0A; break;
+ }
+ break;
+ case 4:
+ switch (_epQuestionNumOfPool) {
+ case 18: specialReg = 0x09; break;
+ case 22: specialReg = 0x0A; break;
+ case 21: specialReg = 0x0B; break;
+ }
+ break;
+ case 5:
+ switch (_epQuestionNumOfPool) {
+ case 22: specialReg = 0x09; break;
+ case 24: specialReg = 0x0A; break;
+ }
+ break;
+ case 6:
+ switch (_epQuestionNumOfPool) {
+ case 12: specialReg = 0x09; break;
+ case 14: specialReg = 0x0A; break;
+ case 18: specialReg = 0x0B; break;
+ }
+ break;
+ case 7:
+ switch (_epQuestionNumOfPool) {
+ case 15: specialReg = 0x09; break;
+ case 16: specialReg = 0x0A; break;
+ case 17: specialReg = 0x0B; break;
+ }
+ break;
+ case 8:
+ switch (_epQuestionNumOfPool) {
+ case 11: specialReg = 0x09; break;
+ case 14: specialReg = 0x0A; break;
+ case 15: specialReg = 0x0B; break;
+ }
+ break;
+ case 9:
+ switch (_epQuestionNumOfPool) {
+ case 2: specialReg = 0x09; break;
+ case 8: specialReg = 0x0A; break;
+ case 11: specialReg = 0x0B; break;
+ }
+ break;
+ case 10:
+ switch (_epQuestionNumOfPool) {
+ case 15: specialReg = 0x09; break;
+ case 16: specialReg = 0x0A; break;
+ case 17: specialReg = 0x0B; break;
+ }
+ break;
+ case 11:
+ switch (_epQuestionNumOfPool) {
+ case 14: specialReg = 0x09; break;
+ case 15: specialReg = 0x0A; break;
+ case 17: specialReg = 0x0B; break;
+ }
+ break;
+ case 12:
+ switch (_epQuestionNumOfPool) {
+ case 12: specialReg = 0x09; break;
+ case 14: specialReg = 0x0A; break;
+ case 16: specialReg = 0x0B; break;
+ }
+ break;
+ case 13:
+ switch (_epQuestionNumOfPool) {
+ case 15: specialReg = 0x09; break;
+ case 18: specialReg = 0x0A; break;
+ case 19: specialReg = 0x0B; break;
+ }
+ break;
+ case 14:
+ switch (_epQuestionNumOfPool) {
+ case 1: specialReg = 0x09; break;
+ case 14: specialReg = 0x0A; break;
+ case 16: specialReg = 0x0B; break;
+ }
+ break;
+ }
+
+ // Add value of register 3 (answer register) to spezial register
+ if (specialReg >= 0) {
+ setScriptVar(specialReg, _scriptVariables[specialReg] + _scriptVariables[3]);
+ debugC(1, kDebugTlcGame, "TLC:EpResultQuest: Question: %d vars[0x%02x] += %d. New Value: %d", _epQuestionIdx, specialReg, _scriptVariables[3], _scriptVariables[specialReg]);
+ }
+
+
+ // Process info from score database
+ answerIdx = _scriptVariables[3];
+ shift = (7 - answerIdx) * 4;
+ questionScore = _epQuestionsData[_epQuestionNumOfPool - 1].questionScore;
+ scoreBinId = (questionScore >> shift) & 0xF;
+ if (scoreBinId > 5) {
+ error("TLC:EpResultQuest: Invalid score bin %d (0..5 allowed)", scoreBinId);
+ }
+
+ _epScoreBin[scoreBinId] = _epScoreBin[scoreBinId] + 1;
+
+ debugC(1, kDebugTlcGame, "TLC:EpResultQuest: Answer: %d -> Inc bin[%d] -> bin[0..5] = %d, %d, %d, %d, %d, %d",
+ answerIdx+1, scoreBinId, _epScoreBin[0], _epScoreBin[1], _epScoreBin[2], _epScoreBin[3], _epScoreBin[4], _epScoreBin[5]);
+}
+/*
+ * Processes the result of the questions for this episode.
+ * _epScoreBin[ 0]: Ignored. Used if this answer for a question has no influence. Reset with each new Exit Poll.
+ * _epScoreBin[1..3]: Seems to be used to select alternative video for this episode. Reset with each new Exit Poll.
+ * _epScoreBin[4..5]: Seems to be used over the whole game. (Values are kept over the episodes in the script variables.
+ */
+void TlcGame::epResultEpisode() {
+
+ uint16 maxBinValue;
+ int i;
+
+ /* keep only the maxium scores of bin[1], bin[2], bin[3]. -> Set all other to 0 */
+ debugCN(1, kDebugTlcGame, "TLC:EpResultEpisode: bins[1..3] = %d, %d, %d ", _epScoreBin[1], _epScoreBin[2], _epScoreBin[3]);
+ maxBinValue = _epScoreBin[1];
+ for (i = 2; i < 4; i++) {
+ if (maxBinValue < _epScoreBin[i]) {
+ maxBinValue = _epScoreBin[i];
+ }
+ }
+ for (i = 1; i < 4; i++) {
+ if (_epScoreBin[i] < maxBinValue) {
+ _epScoreBin[i] = 0;
+ }
+ }
+ debugC(1, kDebugTlcGame, "-> bins[1..3] = %d, %d, %d ", _epScoreBin[1], _epScoreBin[2], _epScoreBin[3]);
+
+ /* Select next stream according to which bin(s) are still >0. */
+ if (_epScoreBin[1] != 0 && _epScoreBin[2] == 0 && _epScoreBin[3] == 0) {
+ setScriptVar(3, 1);
+ }
+ else if (_epScoreBin[1] == 0 && _epScoreBin[2] != 0 && _epScoreBin[3] == 0) {
+ setScriptVar(3, 2);
+ }
+ else if (_epScoreBin[1] == 0 && _epScoreBin[2] == 0 && _epScoreBin[3] != 0) {
+ setScriptVar(3, 3);
+ }
+ else if (_epScoreBin[1] != 0 && _epScoreBin[2] != 0 && _epScoreBin[3] == 0) {
+ setScriptVar(3, _random.getRandomNumberRng(1, 2));
+ }
+ else if (_epScoreBin[1] != 0 && _epScoreBin[2] == 0 && _epScoreBin[3] != 0) {
+ setScriptVar(3, (_random.getRandomNumberRng(0, 1) * 2) + 1);
+ }
+ else if (_epScoreBin[1] == 0 && _epScoreBin[2] != 0 && _epScoreBin[3] != 0) {
+ setScriptVar(3, _random.getRandomNumberRng(2, 3));
+ }
+ else if (_epScoreBin[1] != 0 && _epScoreBin[2] != 0 && _epScoreBin[3] != 0) {
+ setScriptVar(3, _random.getRandomNumberRng(1, 3));
+ }
+ else {
+ error("Tlc:EpResultEpisode: Stream selection failed. bins[0..5] = %d, %d, %d, %d, %d, %d",
+ _epScoreBin[0], _epScoreBin[1], _epScoreBin[2], _epScoreBin[3], _epScoreBin[4], _epScoreBin[5]);
+ }
+ debugC(1, kDebugTlcGame, "Selected stream [1..3] = %d ", _scriptVariables[3]);
+
+ /* save bin values of bin[4..5] to script variables */
+ setScriptVar(1, _epScoreBin[4]);
+ setScriptVar(2, _epScoreBin[5]);
+
+ /* return values */
+ setScriptVar(0, 9);
+}
+
+void TlcGame::opFlags() {
+ int x;
+ int y;
+
+ switch (_scriptVariables[0]) {
+
+ // Initialize the flags all to 0. Done at the beginning of a new TAT
+ case 0x00:
+ for (x = 0; x < 0x0E; x++) {
+ for (y = 0; y < 0x09; y++) {
+ _tatFlags[x][y] = 0;
+ }
+ }
+ debugC(1, kDebugTlcGame, "Tlc:TatFlags: Initialized fields", x, y);
+ break;
+
+ // Get and set flags
+ case 0x01:
+ // Calculate position in flag field
+ x = 10 * _scriptVariables[0x04] + _scriptVariables[0x05];
+ y = _scriptVariables[0x06];
+
+ if (x >= 0x0E) {
+ warning("Tlc:TatFlags: x=%d out of range (0...13).", x);
+ x = 0x0E;
+ }
+ if (y >= 0x09) {
+ warning("Tlc:TatFlags: y=%d out of range (0...8).", x);
+ x = 0x0E;
+ }
+
+ // Check flags in field
+ if (_tatFlags[x][y] == 0) {
+ setScriptVar(0x01, 0);
+ _tatFlags[x][y] = 1;
+
+ debugC(1, kDebugTlcGame, "Tlc:TatFlags: Set x=%d, y=%d to 1", x, y);
+ debugC(5, kDebugTlcGame, "Tlc:TatFlags: %d%d%d%d%d%d%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d%d%d%d%d%d%d",
+ _tatFlags[0][0], _tatFlags[1][0], _tatFlags[2][0], _tatFlags[ 3][0], _tatFlags[ 4][0], _tatFlags[ 5][0], _tatFlags[ 6][0],
+ _tatFlags[7][0], _tatFlags[8][0], _tatFlags[9][0], _tatFlags[10][0], _tatFlags[11][0], _tatFlags[12][0], _tatFlags[13][0],
+ _tatFlags[0][1], _tatFlags[1][1], _tatFlags[2][1], _tatFlags[ 3][1], _tatFlags[ 4][1], _tatFlags[ 5][1], _tatFlags[ 6][1],
+ _tatFlags[7][1], _tatFlags[8][1], _tatFlags[9][1], _tatFlags[10][1], _tatFlags[11][1], _tatFlags[12][1], _tatFlags[13][1]);
+ debugC(5, kDebugTlcGame, "Tlc:TatFlags: %d%d%d%d%d%d%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d%d%d%d%d%d%d",
+ _tatFlags[0][2], _tatFlags[1][2], _tatFlags[2][2], _tatFlags[ 3][2], _tatFlags[ 4][2], _tatFlags[ 5][2], _tatFlags[ 6][2],
+ _tatFlags[7][2], _tatFlags[8][2], _tatFlags[9][2], _tatFlags[10][2], _tatFlags[11][2], _tatFlags[12][2], _tatFlags[13][2],
+ _tatFlags[0][3], _tatFlags[1][3], _tatFlags[2][3], _tatFlags[ 3][3], _tatFlags[ 4][3], _tatFlags[ 5][3], _tatFlags[ 6][3],
+ _tatFlags[7][3], _tatFlags[8][3], _tatFlags[9][3], _tatFlags[10][3], _tatFlags[11][3], _tatFlags[12][3], _tatFlags[13][3]);
+ debugC(5, kDebugTlcGame, "Tlc:TatFlags: %d%d%d%d%d%d%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d%d%d%d%d%d%d",
+ _tatFlags[0][4], _tatFlags[1][4], _tatFlags[2][4], _tatFlags[ 3][4], _tatFlags[ 4][4], _tatFlags[ 5][4], _tatFlags[ 6][4],
+ _tatFlags[7][4], _tatFlags[8][4], _tatFlags[9][4], _tatFlags[10][4], _tatFlags[11][4], _tatFlags[12][4], _tatFlags[13][4],
+ _tatFlags[0][5], _tatFlags[1][5], _tatFlags[2][5], _tatFlags[ 3][5], _tatFlags[ 4][5], _tatFlags[ 5][5], _tatFlags[ 6][5],
+ _tatFlags[7][5], _tatFlags[8][5], _tatFlags[9][5], _tatFlags[10][5], _tatFlags[11][5], _tatFlags[12][5], _tatFlags[13][5]);
+ debugC(5, kDebugTlcGame, "Tlc:TatFlags: %d%d%d%d%d%d%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d%d%d%d%d%d%d",
+ _tatFlags[0][6], _tatFlags[1][6], _tatFlags[2][6], _tatFlags[ 3][6], _tatFlags[ 4][6], _tatFlags[ 5][6], _tatFlags[ 6][6],
+ _tatFlags[7][6], _tatFlags[8][6], _tatFlags[9][6], _tatFlags[10][6], _tatFlags[11][6], _tatFlags[12][6], _tatFlags[13][6],
+ _tatFlags[0][7], _tatFlags[1][7], _tatFlags[2][7], _tatFlags[ 3][7], _tatFlags[ 4][7], _tatFlags[ 5][7], _tatFlags[ 6][7],
+ _tatFlags[7][7], _tatFlags[8][7], _tatFlags[9][7], _tatFlags[10][7], _tatFlags[11][7], _tatFlags[12][7], _tatFlags[13][7]);
+ }
+ else {
+ setScriptVar(0x01, 1);
+ }
+ break;
+ }
+}
+
+
+void TlcGame::opTat() {
+ switch (_scriptVariables[0x40]) {
+ case 1:
+ tatInitRegs();
+ setScriptVar(0x40, 0);
+ break;
+
+ case 2:
+ tatLoadDB();
+ setScriptVar(0x40, 0);
+ break;
+
+ case 3:
+ tatResultQuest();
+ setScriptVar(0x40, 0);
+ break;
+
+ case 4:
+ tatResultEpisode();
+ setScriptVar(0x40, 0);
+ break;
+
+ case 9:
+ tatGetProfile();
+ setScriptVar(0x40, 0);
+ break;
+ }
+}
+
+void TlcGame::tatInitRegs() {
+ int i;
+
+ for (i = 0; i < 0x10; i++) {
+ setScriptVar(0x4D + i, 0);
+ setScriptVar16(0x5D + i*2, 0);
+ }
+
+ // TODO:
+ // memset(_tatUnkData0_14, 0, 15);
+}
+
+void TlcGame::tatLoadDB() {
+ Common::SeekableReadStream *tataidbfile = 0;
+ int i, d;
+ int episode;
+ uint32 questOffset;
+
+ for (i = 0; i < 0x10; i++) {
+ setScriptVar(0x4D + i, 0);
+ }
+
+ // Open epaidb.rle
+ tataidbfile = SearchMan.createReadStreamForMember("SYSTEM/TATAIDB.RLE");
+ if (!tataidbfile) {
+ error("TLC:TatLoadDB: Could not open 'SYSTEM/TATAIDB.RLE'");
+ }
+
+ // Load tat headers if not already done
+ if (_tatHeaders == NULL) {
+ _tatCount = tataidbfile->readUint32LE();
+ _tatHeaders = new TlcTatHeader[_tatCount];
+
+ for (i = 0; i < _tatCount; i++) {
+ _tatHeaders[i].questionsNum = tataidbfile->readUint32LE();
+ _tatHeaders[i].questionsOffset = tataidbfile->readUint32LE();
+ for (d = 0; d < 16; d++) {
+ _tatHeaders[i].binDividends[d] = tataidbfile->readByte();
+ }
+ }
+ }
+
+ if (tataidbfile->eos()) {
+ error("TLC:TatLoadDB: Error reading headers from 'TATAIDB.RLE'");
+ }
+
+ // Load questions for the requested episode
+ episode = _scriptVariables[0x47] - 0x31; // -'1'
+ _tatQuestCount = _tatHeaders[episode].questionsNum;
+ questOffset = _tatHeaders[episode].questionsOffset;
+
+ delete[] _tatQuestions;
+ _tatQuestions = new TlcTatQuestions[_tatQuestCount];
+ tataidbfile->seek(questOffset, SEEK_SET);
+
+ for (int iQuest = 0; iQuest < _tatQuestCount; iQuest++) {
+ tataidbfile->read(_tatQuestions[iQuest].name, 5);
+ _tatQuestions[iQuest].name[5] = '\0';
+ _tatQuestions[iQuest].answerCount = tataidbfile->readByte();
+
+ for (int iAns = 0; iAns < _tatQuestions[iQuest].answerCount; iAns++) {
+ for (int iBin = 0; iBin < 16; iBin++) {
+ _tatQuestions[iQuest].answerData[iAns].binScore[iBin] = tataidbfile->readByte();
+ }
+ }
+ }
+
+ if (tataidbfile->eos()) {
+ error("TLC:TatLoadDB: Error reading questions from 'TATAIDB.RLE'");
+ }
+
+ // tatData[iQ*232 ] <= 5 Bytes Name
+ // tatData[iQ*232+6] <= 1 Byte iAnswers
+
+}
+
+void TlcGame::tatResultQuest() {
+ char questName[6];
+ int questIdx;
+ int selectedAns;
+ if (_tatQuestions == NULL) {
+ error("TLC:ResultQuest: Error, TATAIDB not loaded.");
+ }
+
+ // Get name of current question from script variables
+ for (int i = 0; i < 5; i++) {
+ questName[i] = _scriptVariables[0x41 + i] + 0x30;
+ }
+ questName[6] = '\0';
+
+ // search for question in the database
+ questIdx = -1;
+ do {
+ questIdx++;
+ if (questIdx >= _tatQuestCount) {
+ error("TLC:ResultQuest: Could not find question '%s' in TATAIDB. Count: %d", questName, _tatQuestCount);
+ }
+ } while (strcmpi(questName, _tatQuestions[questIdx].name) != 0);
+
+ // Get selected answer. Range: 0..7
+ selectedAns = _scriptVariables[0x46];
+ if (selectedAns >= _tatQuestions[questIdx].answerCount) {
+ error("TLC:ResultQuest: Chosen answer out of range for question: '%s'. Answer: %d/%d, questIdx: %d", questName, selectedAns+1, _tatQuestions[questIdx].answerCount, questIdx);
+ }
+
+ // Add answer score for each bin to the dedicated script variables
+ for (int iBin = 0; iBin < 16; iBin++) {
+ int score = _tatQuestions[questIdx].answerData[selectedAns].binScore[iBin];
+ setScriptVar(0x4d + iBin, _scriptVariables[0x4D] + score);
+ }
+}
+
+void TlcGame::tatResultEpisode() {
+
+ int episode = _scriptVariables[0x47] - 0x31;
+ float ratioCur = 0;
+ float ratioA = 0;
+ float ratioB = 0;
+ int idxA = 0xff;
+ int idxB = 0xff;
+ int product;
+ char resultStrA[5];
+ char resultStrB[5];
+
+ // Process the bin scores
+ for (int iBin = 0; iBin < 16; iBin++) {
+ int binScoreSum = _scriptVariables[0x4D + iBin];
+
+ // increment 16 Bit interpreted variables with score sum of the current episode
+ setScriptVar16(0x5D + iBin * 2, getScriptVar16(0x5D + iBin * 2) + binScoreSum);
+
+ // Find the two biggest bin ratios. Remeber idx and ratio, A is biggest, B second
+ if (binScoreSum != 0) {
+ ratioCur = binScoreSum / _tatHeaders[episode].binDividends[iBin];
+ if (ratioCur > ratioA) {
+ ratioB = ratioA;
+ idxB = idxA;
+ ratioA = ratioCur;
+ idxA = iBin;
+ } else {
+ if (ratioCur > ratioB) {
+ ratioB = ratioCur;
+ idxB = iBin;
+ }
+ }
+ }
+ }
+
+ // Process result according to biggest ratio (ratioA)
+ switch (idxA) {
+ case 0:
+ product = ratioA * 18.0;
+ if (product <= 3) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product - 4);
+ }
+ break;
+
+ case 1:
+ product = ratioA * 13.0;
+ if (product <= 3) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product - 4);
+ }
+ break;
+
+ case 2:
+ product = ratioA * 12.0;
+ if (product <= 3) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product - 4);
+ }
+ break;
+
+ case 3:
+ product = ratioA * 13.0;
+ if (product <= 8) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product - 9);
+ }
+ break;
+
+ case 4:
+ product = ratioA * 11.0;
+ if (product <= 3) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product - 4);
+ }
+ break;
+
+ case 5:
+ product = ratioA * 11.0;
+ if (product >= 4) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product - 4);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product);
+ }
+ break;
+
+ case 6:
+ product = ratioA * 9.0;
+ if (product <= 4) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product - 5);
+ }
+ break;
+
+ case 7:
+ product = ratioA * 10.0;
+ if (product <= 3) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product - 4);
+ }
+ break;
+
+ case 8:
+ product = ratioA * 12.0;
+ if (product <= 4) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product - 5);
+ }
+ break;
+
+ case 9:
+ product = ratioA * 10.0;
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product);
+ break;
+
+ case 10:
+ product = ratioA * 7.0;
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product);
+ break;
+
+ case 11:
+ product = ratioA * 10.0;
+ if (product >= 4) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product - 4);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product);
+ }
+ break;
+
+ case 12:
+ product = ratioA * 9.0;
+ if (product >= 4) {
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product - 4);
+ } else {
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product);
+ }
+ break;
+
+ case 13:
+ product = ratioA * 6.0;
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product);
+ break;
+
+ case 14:
+ product = ratioA * 7.0;
+ sprintf(resultStrA, "%cP%02d", idxA + 'A', product);
+ break;
+
+ case 15:
+ product = ratioA * 8.0;
+ sprintf(resultStrA, "%cN%02d", idxA + 'A', product);
+ break;
+ }
+
+
+ // The same for the second biggest ratio (ratioB)
+ switch (idxB) {
+ case 0:
+ product = ratioB * 18.0;
+ if (product <= 3) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product - 4);
+ }
+ break;
+
+ case 1:
+ product = ratioB * 13.0;
+ if (product <= 3) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product - 4);
+ }
+ break;
+
+ case 2:
+ product = ratioB * 12.0;
+ if (product <= 3) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product - 4);
+ }
+ break;
+
+ case 3:
+ product = ratioB * 13.0;
+ if (product <= 8) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product - 9);
+ }
+ break;
+
+ case 4:
+ product = ratioB * 11.0;
+ if (product <= 3) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product - 4);
+ }
+ break;
+
+ case 5:
+ product = ratioB * 11.0;
+ if (product >= 4) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product - 4);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product);
+ }
+ break;
+
+ case 6:
+ product = ratioB * 9.0;
+ if (product <= 4) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product - 5);
+ }
+ break;
+
+ case 7:
+ product = ratioB * 10.0;
+ if (product <= 3) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product - 4);
+ }
+ break;
+
+ case 8:
+ product = ratioB * 12.0;
+ if (product <= 4) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product - 5);
+ }
+ break;
+
+ case 9:
+ product = ratioB * 10.0;
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product);
+ break;
+
+ case 10:
+ product = ratioB * 7.0;
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product);
+ break;
+
+ case 11:
+ product = ratioB * 10.0;
+ if (product >= 4) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product - 4);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product);
+ }
+ break;
+
+ case 12:
+ product = ratioB * 9.0;
+ if (product >= 4) {
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product - 4);
+ } else {
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product);
+ }
+ break;
+
+ case 13:
+ product = ratioB * 6.0;
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product);
+ break;
+
+ case 14:
+ product = ratioB * 7.0;
+ sprintf(resultStrB, "%cP%02d", idxB + 'A', product);
+ break;
+
+ case 15:
+ product = ratioB * 8.0;
+ sprintf(resultStrB, "%cN%02d", idxB + 'A', product);
+ break;
+ }
+
+ // Write result to script variables
+ setScriptVar(0x4D, resultStrA[0] - 0x30);
+ setScriptVar(0x4E, resultStrA[1] - 0x30);
+ setScriptVar(0x4F, resultStrA[2] - 0x30);
+ setScriptVar(0x50, resultStrA[3] - 0x30);
+ setScriptVar(0x51, resultStrB[0] - 0x30);
+ setScriptVar(0x52, resultStrB[1] - 0x30);
+ setScriptVar(0x53, resultStrB[2] - 0x30);
+ setScriptVar(0x54, resultStrB[3] - 0x30);
+ setScriptVar(0x55, '\0');
+}
+
+
+void TlcGame::tatGetProfile() {
+ uint16 scoreTable[16];
+ int iBin, iEpisode;
+
+ for (iBin = 0; iBin < 16; iBin++) {
+ scoreTable[iBin] = 0;
+ }
+
+ for (iEpisode = 0; iEpisode < 15; iEpisode++) {
+ for (iBin = 0; iBin < 16; iBin++) {
+ scoreTable[iBin] += _tatCoeffs[iEpisode][iBin];
+ }
+ }
+
+ for (iBin = 0; iBin <= 16; iBin++) {
+ getScriptVar16(0x5D + 2 * iBin);
+ }
+
+
+}
+
+} // End of Namespace Groovie
diff --git a/engines/groovie/tlcgame.h b/engines/groovie/tlcgame.h
new file mode 100644
index 0000000000..3648c3fbcd
--- /dev/null
+++ b/engines/groovie/tlcgame.h
@@ -0,0 +1,193 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef GROOVIE_TLCGAME_H
+#define GROOVIE_TLCGAME_H
+
+#include "common/textconsole.h"
+#include "common/random.h"
+
+#define GROOVIE_TLC_MAX_EPSIODES (15)
+#define GROOVIE_TLC_MAX_QUEST_EP (50)
+
+namespace Groovie {
+
+class GroovieEngine;
+
+// The regions.rle contains 898 entries. Round about 18 kByte in memory.
+struct TlcRegionsHeader {
+ char name[12];
+ int numAnswers;
+ uint32 offset;
+};
+
+struct TlcRegion {
+ uint16 left;
+ uint16 top;
+ uint16 right;
+ uint16 bottom;
+};
+
+struct TlcEpQuestionData {
+ bool questionUsed;
+ uint32 questionScore;
+};
+
+struct TlcTatHeader {
+ uint32 questionsNum;
+ uint32 questionsOffset;
+ uint8 binDividends[16];
+};
+
+struct TlcTatAnswer {
+ uint8 binScore[8];
+};
+
+struct TlcTatQuestions {
+ char name[6];
+ int answerCount;
+ TlcTatAnswer answerData[8];
+};
+
+class TlcGame
+{
+public:
+ TlcGame();
+ ~TlcGame();
+
+ /**
+ * Sets a pointer to the script variables. This makes it easier if we want
+ * to debug write accesses to the script variables
+ * @param scriptVariables The current variables from the script.
+ */
+ void setVariables(byte *scriptVariables);
+
+ /**
+ * Handle region commands. A region describes the coordinates of
+ * a rectangle as clickable area in the question dialogs. These regions
+ * are provided by a the extra file.
+ * screen coordinates.
+ */
+ void opRegions();
+
+ /**
+ * Get the coordiantes of the region for the next answer. There are
+ * up to 8 answers possible for each question. In the script the
+ * coordinates are (0,0,0,0) which will be replace by the new ones.
+ * @param left Left value of the rectangle
+ * @param top Top value of the rectangle
+ * @param right Right value of the rectangle
+ * @param bottom Bottom value of the rectangle
+ * @return 0 if anwer was found. -1 in case no more answer
+ * available for this question
+ */
+ int getRegionNext(uint16 &left, uint16 &top, uint16 &right, uint16 &bottom);
+
+ /**
+ * Rewinds the internal answer counter for the function
+ * getRegionNext()
+ */
+ void getRegionRewind();
+
+
+ /**
+ * Handles some flags which are used during a TAT. The game seems to
+ * use this flags to skip some questions during a TAT.
+ * OpCode_0x42(2)
+ */
+ void opFlags();
+
+
+ /**
+ * Handles all Exit Poll commands. The exit poll (EP) questions are
+ * described in detail in the file EPAIDB.RLE.
+ * OpCode_0x42(1)
+ */
+ void opExitPoll();
+
+ /**
+ * Handles all TAT commands. The TAT questions are described in detail
+ * in the file TATAIDB.RLE
+ */
+ void opTat();
+
+private:
+ Common::RandomSource _random;
+
+ void inline setScriptVar(uint16 var, byte value);
+ void inline setScriptVar16(uint16 var, uint16 value);
+ uint16 inline getScriptVar16(uint16 var);
+ byte *_scriptVariables;
+
+ /**
+ * Loads the description part of the regions.rle file into memory
+ * This makes it faster to search for the correct quesion.
+ */
+ void regionsInit();
+ void regionsLoad();
+
+ // Variables for region handling
+ int _numRegionHeaders;
+ int _curAnswerIndex;
+ int _curQuestNumAnswers;
+ TlcRegion _curQuestRegions[8];
+ TlcRegionsHeader *_regionHeader;
+
+ /**
+ * Functions for Exit Poll Commands
+ */
+ void epInit();
+ void epSelectNextQuestion();
+ void epResultQuestion();
+ void epResultEpisode();
+
+ // Variables for Exit Poll handling
+ int16 _epScoreBin[6];
+ int _epEpisodeIdx; // 15 Episodes: 0..14
+ int _epQuestionIdx; // 1..X (questions in current episode. counted up for every question)
+ int _epQuestionNumOfPool; // 1..X (question number in the data base. The questions are played in random order)
+ int _epQuestionsInEpisode;
+ TlcEpQuestionData *_epQuestionsData;
+
+ // Variables for flag handling
+ byte _tatFlags[0x0E][0x09];
+
+ /**
+ * Functions for TAT Commands
+ */
+ void tatInitRegs();
+ void tatLoadDB();
+ void tatResultQuest();
+ void tatResultEpisode();
+ void tatGetProfile();
+
+ // Variables for TAT handling
+ int _tatCount;
+ int _tatQuestCount;
+ TlcTatHeader *_tatHeaders;
+ TlcTatQuestions *_tatQuestions;
+ uint8 _tatCoeffs[15][16];
+};
+
+} // End of Groovie namespace
+
+#endif // GROOVIE_TLCGAME_H
Commit: 7004f6555768793ca3b44222a7a83c5e135daa81
https://github.com/scummvm/scummvm/commit/7004f6555768793ca3b44222a7a83c5e135daa81
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Minor changes in debug messages / hotspot debugging
Changed paths:
engines/groovie/script.cpp
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 2146dd61c2..17dab95fc7 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -418,10 +418,11 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) {
// Show hotspots when debugging
if (DebugMan.isDebugChannelEnabled(kDebugHotspots)) {
- if (!_vm->_graphicsMan->isFullScreen())
+ if (_vm->_graphicsMan->isFullScreen())
rect.translate(0, -80);
- _vm->_graphicsMan->_foreground.frameRect(rect, 250);
- _vm->_graphicsMan->updateScreen(&_vm->_graphicsMan->_foreground);
+ Graphics::Surface *gamescreen = _vm->_system->lockScreen();
+ gamescreen->frameRect(rect, 0xcc2338ff);
+ _vm->_system->unlockScreen();
_vm->_system->updateScreen();
}
@@ -782,20 +783,23 @@ void Script::o_keyboardaction() {
uint8 val = readScript8bits();
uint16 address = readScript16bits();
- debugC(5, kDebugScript, "Test key == 0x%02X @0x%04X", val, address);
-
// If there's an already planned action, do nothing
if (_inputAction != -1) {
+ debugC(5, kDebugScript, "Test key == 0x%02X @0x%04X - skipped", val, address);
return;
}
// Check the typed key
if (_kbdChar == val) {
+ debugC(5, kDebugScript, "Test key == 0x%02X @0x%04X - match", val, address);
+
// Exit the input loop
_inputLoopAddress = 0;
// Save the action address
_inputAction = address;
+ } else {
+ debugC(5, kDebugScript, "Test key == 0x%02X @0x%04X", val, address);
}
}
Commit: 7b397d8ec9455cda1e456d42c9af31c1f358481d
https://github.com/scummvm/scummvm/commit/7b397d8ec9455cda1e456d42c9af31c1f358481d
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Bugfixes in TLC specific calculations
Changed paths:
engines/groovie/tlcgame.cpp
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
index 40e0678df4..537f573914 100644
--- a/engines/groovie/tlcgame.cpp
+++ b/engines/groovie/tlcgame.cpp
@@ -842,7 +842,7 @@ void TlcGame::tatResultQuest() {
for (int i = 0; i < 5; i++) {
questName[i] = _scriptVariables[0x41 + i] + 0x30;
}
- questName[6] = '\0';
+ questName[5] = '\0';
// search for question in the database
questIdx = -1;
@@ -862,7 +862,7 @@ void TlcGame::tatResultQuest() {
// Add answer score for each bin to the dedicated script variables
for (int iBin = 0; iBin < 16; iBin++) {
int score = _tatQuestions[questIdx].answerData[selectedAns].binScore[iBin];
- setScriptVar(0x4d + iBin, _scriptVariables[0x4D] + score);
+ setScriptVar(0x4d + iBin, _scriptVariables[0x4D + iBin] + score);
}
}
@@ -887,7 +887,7 @@ void TlcGame::tatResultEpisode() {
// Find the two biggest bin ratios. Remeber idx and ratio, A is biggest, B second
if (binScoreSum != 0) {
- ratioCur = binScoreSum / _tatHeaders[episode].binDividends[iBin];
+ ratioCur = (float)binScoreSum / (float)_tatHeaders[episode].binDividends[iBin];
if (ratioCur > ratioA) {
ratioB = ratioA;
idxB = idxA;
Commit: 0c919bc38bf99e8bba4813f293436511b19fa1e6
https://github.com/scummvm/scummvm/commit/0c919bc38bf99e8bba4813f293436511b19fa1e6
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Extensions to ROQ Player for 11H
Changed paths:
engines/groovie/roq.cpp
engines/groovie/roq.h
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 531ac7551b..5e3c93bd9a 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -44,8 +44,46 @@
#include "audio/mixer.h"
#include "audio/decoders/raw.h"
+/* copied from transparent_surface.cpp */
+#ifdef SCUMM_LITTLE_ENDIAN
+static const int kAIndex = 0;
+static const int kBIndex = 1;
+static const int kGIndex = 2;
+static const int kRIndex = 3;
+
+#else
+static const int kAIndex = 3;
+static const int kBIndex = 2;
+static const int kGIndex = 1;
+static const int kRIndex = 0;
+#endif
+
namespace Groovie {
+// Overwrites one pixel of destination regardless of the alpha value
+static inline void copyPixel(byte *dst, byte *src) {
+ dst[kAIndex] = src[kAIndex];
+ dst[kRIndex] = src[kRIndex];
+ dst[kGIndex] = src[kGIndex];
+ dst[kBIndex] = src[kBIndex];
+}
+
+// Copies one pixel to destination but respects the alpha value of the source
+static inline void copyPixelWithA(byte *dst, byte *src) {
+ if (src[kAIndex] == 255) {
+ copyPixel(dst, src);
+ } else {
+ if (src[kAIndex] > 0) {
+ dst[kAIndex] = 255;
+ dst[kRIndex] = ((src[kRIndex] * src[kAIndex]) + dst[kRIndex] * (255 - src[kAIndex])) >> 8;
+ dst[kGIndex] = ((src[kGIndex] * src[kAIndex]) + dst[kGIndex] * (255 - src[kAIndex])) >> 8;
+ dst[kBIndex] = ((src[kBIndex] * src[kAIndex]) + dst[kBIndex] * (255 - src[kAIndex])) >> 8;
+ }
+ }
+ // In case of alpha == 0 just do not copy
+}
+
+
ROQPlayer::ROQPlayer(GroovieEngine *vm) :
VideoPlayer(vm), _codingTypeCount(0),
_fg(&_vm->_graphicsMan->_foreground),
@@ -56,6 +94,8 @@ ROQPlayer::ROQPlayer(GroovieEngine *vm) :
// Create the work surfaces
_currBuf = new Graphics::Surface();
_prevBuf = new Graphics::Surface();
+ _overBuf = new Graphics::Surface(); // Overlay buffer. Object move behind this layer
+ _restoreArea = new Common::Rect();
}
ROQPlayer::~ROQPlayer() {
@@ -64,6 +104,9 @@ ROQPlayer::~ROQPlayer() {
delete _currBuf;
_prevBuf->free();
delete _prevBuf;
+ _overBuf->free();
+ delete _overBuf;
+ delete _restoreArea;
}
void ROQPlayer::setOrigin(int16 x, int16 y) {
@@ -74,7 +117,7 @@ void ROQPlayer::setOrigin(int16 x, int16 y) {
uint16 ROQPlayer::loadInternal() {
if (DebugMan.isDebugChannelEnabled(kDebugVideo)) {
int8 i;
- debugN(1, "Groovie::ROQ: New ROQ: bitflags are ");
+ debugN(1, "Groovie::ROQ: Loading video. New ROQ: bitflags are ");
for (i = 15; i >= 0; i--) {
debugN(1, "%d", _flags & (1 << i)? 1 : 0);
if (i % 4 == 0) {
@@ -86,10 +129,8 @@ uint16 ROQPlayer::loadInternal() {
// Flags:
// - 2 For overlay videos, show the whole video
- _flagTwo = ((_flags & (1 << 2)) != 0);
-
- // Begin reading the file
- debugC(1, kDebugVideo, "Groovie::ROQ: Loading video");
+ _flagOne = ((_flags & (1 << 1)) != 0);
+ _flagTwo = ((_flags & (1 << 2)) != 0);
// Read the file header
ROQBlockHeader blockHeader;
@@ -97,17 +138,21 @@ uint16 ROQPlayer::loadInternal() {
return 0;
}
- debugC(1, kDebugVideo, "Groovie::ROQ: First Block type = 0x%02X", blockHeader.type);
- debugC(1, kDebugVideo, "Groovie::ROQ: First Block size = 0x%08X", blockHeader.size);
- debugC(1, kDebugVideo, "Groovie::ROQ: First Block param = 0x%04X", blockHeader.param);
+ debugC(6, kDebugVideo, "Groovie::ROQ: First Block type = 0x%02X", blockHeader.type);
+ debugC(6, kDebugVideo, "Groovie::ROQ: First Block size = 0x%08X", blockHeader.size);
+ debugC(6, kDebugVideo, "Groovie::ROQ: First Block param = 0x%04X", blockHeader.param);
// Verify the file signature
if (blockHeader.type != 0x1084) {
return 0;
}
- // Clear the dirty flag
- _dirty = true;
+ // Clear the dirty flag and restore area
+ _dirty = false;
+ _restoreArea->top = 480;
+ _restoreArea->left = 640;
+ _restoreArea->bottom = 0;
+ _restoreArea->right = 0;
// Reset the codebooks
_num2blocks = 0;
@@ -134,31 +179,96 @@ uint16 ROQPlayer::loadInternal() {
}
}
+
+// Calculate the overlapping area for the rendered frame to the visible frame. The game can use an origin to
+// place the rendered image at different places.
+void ROQPlayer::calcStartStop(int &start, int &stop, int origin, int length) {
+ if (origin >= 0) {
+ start = origin;
+ stop = length;
+ } else {
+ start = 0;
+ stop = length + origin;
+ }
+}
+
void ROQPlayer::buildShowBuf() {
- if (_alpha)
- _fg->copyFrom(*_bg);
-
- for (int line = _origY; line < _bg->h; line++) {
- uint32 *out = _alpha ? (uint32 *)_fg->getBasePtr(0, line) : (uint32 *)_bg->getBasePtr(0, line);
- uint32 *in = (uint32 *)_currBuf->getBasePtr(0, (line - _origY) / _scaleY);
-
- // Apply offset
- out += _origX;
-
- for (int x = _origX; x < _bg->w; x++) {
- // Copy a pixel, checking the alpha channel first
- if (_alpha && !(*in & 0xFF))
- out++;
- else if (_fg->h == 480 && *in == _vm->_pixelFormat.RGBToColor(255, 255, 255))
- // Handle transparency in Gamepad videos
- // TODO: For now, we detect these videos by checking for full screen
- out++;
- else
- *out++ = *in;
+ // Restore the background by data from the foreground. Only restore the area which was overwritten during the last frame
+ // Therefore we have the _restoreArea which reduces the area for restoring. We also use the _prevBuf to only overwrite the
+ // Pixels which have been written during the last frame. This means _restoreArea is just an optimization.
+ if (_alpha) {
+ if (!_restoreArea->isEmpty()) {
+ int width = _restoreArea->right - _restoreArea->left;
+ for (int line = _restoreArea->top; line < _restoreArea->bottom; line++) {
+ byte *src = (byte *)_fg->getBasePtr(_restoreArea->left, line);
+ byte *dst = (byte *)_bg->getBasePtr(_restoreArea->left, line);
+ byte *prv = (byte *)_prevBuf->getBasePtr((_restoreArea->left - _origX) / _scaleX, (line - _origY) / _scaleY);
+ byte *ovr = (byte *)_overBuf->getBasePtr(_restoreArea->left, line);
+ for (int i = 0; i < width; i++) {
+ if (prv[kAIndex] != 0) {
+ copyPixel(dst, src);
+ copyPixelWithA(dst, ovr);
+ }
+ src += _fg->format.bytesPerPixel;
+ dst += _fg->format.bytesPerPixel;
+ prv += _fg->format.bytesPerPixel;
+ ovr += _fg->format.bytesPerPixel;
+ }
+ }
+ }
+
+ // Reset _restoreArea for the next frame
+ _restoreArea->top = 480;
+ _restoreArea->left = 640;
+ _restoreArea->bottom = 0;
+ _restoreArea->right = 0;
+ }
+
+
+ // Select the destination buffer according to the given flags
+ Graphics::Surface *destBuf;
+ if (_flagOne) {
+ if (_flagTwo) {
+ destBuf = _overBuf;
+ } else {
+ destBuf = _fg;
+ }
+ } else {
+ destBuf = _bg;
+ }
+
+
+ // _origY and _origX may be negative (11th hour uses this in the chapel puzzle against Stauf)
+ int startX, startY, stopX, stopY;
+ calcStartStop(startX, stopX, _origX, _bg->w);
+ calcStartStop(startY, stopY, _origY, _bg->h);
+
+ for (int line = startY; line < stopY; line++) {
+ byte *in = (byte *)_currBuf->getBasePtr(MAX(0, -_origX) / _scaleX, (line - _origY) / _scaleY);
+ byte *inOvr = (byte *)_overBuf->getBasePtr(startX, line);
+ byte *out = (byte *)destBuf->getBasePtr(startX, line);
+
+ for (int x = startX; x < stopX; x++) {
+ if (_alpha && destBuf != _overBuf) {
+ copyPixelWithA(out, in);
+ } else {
+ copyPixel(out, in);
+ }
+
+ if (_alpha && in[kAIndex] && destBuf != _overBuf) {
+ _restoreArea->top = MIN(line, (int)_restoreArea->top);
+ _restoreArea->left = MIN(x, (int)_restoreArea->left);
+ _restoreArea->bottom = MAX(line + 1, (int)_restoreArea->bottom);
+ _restoreArea->right = MAX(x + 1, (int)_restoreArea->right);
+
+ copyPixelWithA(out, inOvr);
+ }
// Skip to the next pixel
+ out += _bg->format.bytesPerPixel;
+ inOvr += _bg->format.bytesPerPixel;
if (!(x % _scaleX))
- in++;
+ in += _bg->format.bytesPerPixel;
}
}
@@ -193,18 +303,23 @@ bool ROQPlayer::playFrameInternal() {
if (_dirty) {
// Update the screen
- void *src = (_alpha) ? _fg->getPixels() : _bg->getPixels();
+ void *src = (_alpha && 0) ? _fg->getPixels() : _bg->getPixels();
_syst->copyRectToScreen(src, _bg->pitch, 0, (_syst->getHeight() - _bg->h) / 2, _bg->w, _bg->h);
_syst->updateScreen();
// For overlay videos, set the background buffer when the video ends
- if (_alpha && (!_flagTwo || (_flagTwo && _file->eos())))
- _bg->copyFrom(*_fg);
+ if (_alpha && (!_flagTwo || (_flagTwo && _file->eos()))) {
+ //_bg->copyFrom(*_fg);
+ }
// Clear the dirty flag
_dirty = false;
}
+ if (_file->eos()) {
+ _overBuf->fillRect(Common::Rect(0, 0, _overBuf->w, _overBuf->h), _overBuf->format.ARGBToColor(0, 0, 0, 0));
+ }
+
// Report the end of the video if we reached the end of the file or if we
// just wanted to play one frame. Also reset origin for next video / image
if (_file->eos() || playFirstFrame()) {
@@ -258,11 +373,13 @@ bool ROQPlayer::processBlock() {
ok = processBlockQuadVector(blockHeader);
_dirty = true;
endframe = true;
+ debugC(3, kDebugVideo, "Groovie::ROQ: Decoded Quad Vector frame.");
break;
case 0x1012: // Still image (JPEG)
ok = processBlockStill(blockHeader);
_dirty = true;
endframe = true;
+ debugC(3, kDebugVideo, "Groovie::ROQ: Decoded Still image (JPG).");
break;
case 0x1013: // Hang
assert(blockHeader.size == 0 && blockHeader.param == 0);
@@ -274,7 +391,7 @@ bool ROQPlayer::processBlock() {
case 0x1021: // Stereo sound samples
ok = processBlockSoundStereo(blockHeader);
break;
- case 0x1030: // Audio container
+ case 0x1030: // Container Chunk -> Just skip the chunk header and continue
endpos = _file->pos();
ok = processBlockAudioContainer(blockHeader);
break;
@@ -325,17 +442,19 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
// Free the previous surfaces
_currBuf->free();
_prevBuf->free();
+ _overBuf->free();
// Allocate new buffers
_currBuf->create(width, height, _vm->_pixelFormat);
_prevBuf->create(width, height, _vm->_pixelFormat);
+ _overBuf->create(width, height, _vm->_pixelFormat);
}
// Hack: Detect a video with interlaced black lines, by checking its height compared to width
if (height <= width / 3) {
_offScale = 2;
}
- debugC(1, kDebugVideo, "Groovie::ROQ: widht=%d, height=%d, scaleX=%d, scaleY=%d, _offScale=%d", width, height, _scaleX, _scaleY, _offScale);
+ debugC(2, kDebugVideo, "Groovie::ROQ: width=%d, height=%d, scaleX=%d, scaleY=%d, _offScale=%d, _alpha=%d", width, height, _scaleX, _scaleY, _offScale, _alpha);
// Switch from/to fullscreen, if needed
if (_bg->h != 480 && height == 480)
diff --git a/engines/groovie/roq.h b/engines/groovie/roq.h
index 9971b4584a..bc1e01d721 100644
--- a/engines/groovie/roq.h
+++ b/engines/groovie/roq.h
@@ -58,7 +58,7 @@ private:
bool processBlockSoundMono(ROQBlockHeader &blockHeader);
bool processBlockSoundStereo(ROQBlockHeader &blockHeader);
bool processBlockAudioContainer(ROQBlockHeader &blockHeader);
- bool playFirstFrame() { return _alpha && !_flagTwo; }
+ bool playFirstFrame() { return _flagOne; }; // _alpha && !_flagTwo; }
void paint2(byte i, int destx, int desty);
void paint4(byte i, int destx, int desty);
@@ -67,6 +67,7 @@ private:
// Origin
int16 _origX, _origY;
+ void calcStartStop(int &start, int &stop, int origin, int length);
// Block coding type
byte getCodingType();
@@ -80,10 +81,11 @@ private:
byte _codebook4[256 * 4];
// Flags
- bool _flagTwo;
+ bool _flagOne; // Play only first frame and do not print the image to the screen
+ bool _flagTwo; // If _flagOne is set. Copy frame to the foreground otherwise to the background
// Buffers
- Graphics::Surface *_fg, *_bg;
+ Graphics::Surface *_fg, *_bg, *_overBuf;
Graphics::Surface *_currBuf, *_prevBuf;
void buildShowBuf();
byte _scaleX, _scaleY;
@@ -91,6 +93,7 @@ private:
bool _dirty;
byte _alpha;
bool _firstFrame;
+ Common::Rect *_restoreArea; // Area to be repainted by foreground
};
} // End of Groovie namespace
Commit: 76c71278fb453f45bd3a45234bad018ecf8fcd56
https://github.com/scummvm/scummvm/commit/76c71278fb453f45bd3a45234bad018ecf8fcd56
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Described unknown filed in resource database
Changed paths:
engines/groovie/resource.cpp
engines/groovie/resource.h
diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp
index 75eba95240..8432ba143b 100644
--- a/engines/groovie/resource.cpp
+++ b/engines/groovie/resource.cpp
@@ -275,7 +275,7 @@ bool ResMan_v2::getResInfo(uint32 fileRef, ResInfo &resInfo) {
}
// Read the resource information
- rlFile.readUint32LE(); // Unknown
+ resInfo.disks = rlFile.readUint32LE(); // Seems to be a bitfield indicating on which disk(s) the file can be found
resInfo.offset = rlFile.readUint32LE();
resInfo.size = rlFile.readUint32LE();
resInfo.gjd = rlFile.readUint16LE();
diff --git a/engines/groovie/resource.h b/engines/groovie/resource.h
index 3b361cbab9..8d76ee4e2d 100644
--- a/engines/groovie/resource.h
+++ b/engines/groovie/resource.h
@@ -30,6 +30,7 @@ class MacResManager;
namespace Groovie {
struct ResInfo {
+ uint32 disks; // This seems to be a bitfield indicating on which disk(s) the file is located.
uint16 gjd;
uint32 offset;
uint32 size;
Commit: d4fea1aa340b9bb65e7c497e903091b0324fcfeb
https://github.com/scummvm/scummvm/commit/d4fea1aa340b9bb65e7c497e903091b0324fcfeb
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Added german version of 11h
Changed paths:
engines/groovie/detection.cpp
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 7a022bd962..37d663b6f0 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -148,7 +148,17 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieT11H, 1
},
- // The 11th Hour Windows English
+ {
+ {
+ "11h", "deu",
+ AD_ENTRY1s("disk.1", "3d5133fc457e80b80591086dce283792", 76),
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE,
+ GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ },
+ kGroovieT11H, 1
+ },
+
+ // The 11th Hour Macintosh English
{
{
"11h", "",
Commit: e0ed66fe58e8e6bf881d7c70c24e3411526e8c76
https://github.com/scummvm/scummvm/commit/e0ed66fe58e8e6bf881d7c70c24e3411526e8c76
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Adaptions for transparent cursor
Changed paths:
engines/groovie/cursor.cpp
diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp
index 705bb16bef..31222fce58 100644
--- a/engines/groovie/cursor.cpp
+++ b/engines/groovie/cursor.cpp
@@ -308,6 +308,8 @@ void Cursor_v2::decodeFrame(byte *pal, byte *data, byte *dest) {
byte r, g, b;
+ const byte alphaDecoded[8] = {0, 36, 73, 109, 146, 182, 219, 255}; // Calculated by: alpha = ((int)(*data & 0xE0) * 255) / 224;
+
// Start frame decoding
for (int y = 0; y < _height; y++) {
for (int x = 0; x < _width; x++) {
@@ -317,7 +319,7 @@ void Cursor_v2::decodeFrame(byte *pal, byte *data, byte *dest) {
ctrA = (*data++ & 0x7F) + 1;
} else {
ctrB = *data++ + 1;
- alpha = *data & 0xE0;
+ alpha = alphaDecoded[(*data & 0xE0) >> 5];
palIdx = *data++ & 0x1F;
}
}
@@ -325,7 +327,7 @@ void Cursor_v2::decodeFrame(byte *pal, byte *data, byte *dest) {
if (ctrA) {
// Block type A - chunk of non-continuous pixels
palIdx = *data & 0x1F;
- alpha = *data++ & 0xE0;
+ alpha = alphaDecoded[(*data++ & 0xE0) >> 5];
r = *(pal + palIdx);
g = *(pal + palIdx + 0x20);
@@ -343,17 +345,7 @@ void Cursor_v2::decodeFrame(byte *pal, byte *data, byte *dest) {
// Decode pixel
if (alpha) {
- if (alpha != 0xE0) {
- alpha = ((alpha << 8) / 224);
-
- // TODO: The * 0 to be replaced by the component value of each pixel
- // below, respectively - does blending
- r = (byte)((alpha * r + (256 - alpha) * 0) >> 8);
- g = (byte)((alpha * g + (256 - alpha) * 0) >> 8);
- b = (byte)((alpha * b + (256 - alpha) * 0) >> 8);
- }
-
- *ptr = 1;
+ *ptr = alpha;
*(ptr + 1) = r;
*(ptr + 2) = g;
*(ptr + 3) = b;
@@ -367,11 +359,7 @@ void Cursor_v2::decodeFrame(byte *pal, byte *data, byte *dest) {
ptr = tmp;
for (int y = 0; y < _height; y++) {
for (int x = 0; x < _width; x++) {
- if (*ptr == 1) {
- *(uint32 *)dest = _format.RGBToColor(*(ptr + 1), *(ptr + 2), *(ptr + 3));
- } else {
- *(uint32 *)dest = 0;
- }
+ *(uint32 *)dest = _format.ARGBToColor(*ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3));
dest += 4;
ptr += 4;
}
Commit: 6525123663600d420e04652708b7a1076f58fc0b
https://github.com/scummvm/scummvm/commit/6525123663600d420e04652708b7a1076f58fc0b
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: TLC Music / Small Bugfixes / Better Comments
Changed paths:
engines/groovie/groovie.cpp
engines/groovie/music.cpp
engines/groovie/music.h
engines/groovie/script.cpp
engines/groovie/script.h
engines/groovie/tlcgame.cpp
engines/groovie/tlcgame.h
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 96bd87f2eb..3c80c1f16b 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -180,28 +180,42 @@ Common::Error GroovieEngine::run() {
error("GROOVIE: Unknown Game version. groovie.cpp:run()");
}
- // Detect ScummVM Music Enhancement Project presence (T7G only)
- if (Common::File::exists("gu16.ogg") && _gameDescription->version == kGroovieT7G) {
- // Load player for external files
- _musicPlayer = new MusicPlayerIOS(this);
- } else {
- // Create the music player
- switch (getPlatform()) {
- case Common::kPlatformMacintosh:
- if (_gameDescription->version == kGroovieT7G)
- _musicPlayer = new MusicPlayerMac_t7g(this);
- else
- _musicPlayer = new MusicPlayerMac_v2(this);
- break;
- case Common::kPlatformIOS:
+
+ switch (_gameDescription->version) {
+ case kGroovieT7G:
+ case kGroovieT11H:
+ case kGroovieCDY:
+ case kGroovieUHP:
+ // Detect ScummVM Music Enhancement Project presence (T7G only)
+ if (Common::File::exists("gu16.ogg") && _gameDescription->version == kGroovieT7G) {
+ // Load player for external files
_musicPlayer = new MusicPlayerIOS(this);
- break;
- default:
- _musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample");
- break;
}
+ else {
+ // Create the music player
+ switch (getPlatform()) {
+ case Common::kPlatformMacintosh:
+ if (_gameDescription->version == kGroovieT7G)
+ _musicPlayer = new MusicPlayerMac_t7g(this);
+ else
+ _musicPlayer = new MusicPlayerMac_v2(this);
+ break;
+ case Common::kPlatformIOS:
+ _musicPlayer = new MusicPlayerIOS(this);
+ break;
+ default:
+ _musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample");
+ break;
+ }
+ }
+ break;
+
+ case kGroovieTLC:
+ _musicPlayer = new MusicPlayerTlc(this);
+ break;
}
+
// Load volume levels
syncSoundSettings();
@@ -268,7 +282,7 @@ Common::Error GroovieEngine::run() {
// Check that the game files and the audio tracks aren't together run from
// the same cd
- if (getPlatform() != Common::kPlatformIOS) {
+ if (getPlatform() != Common::kPlatformIOS && _gameDescription->version != kGroovieTLC) {
if (!existExtractedCDAudioFiles()
&& !isDataAndCDAudioReadFromSameCD()) {
warnMissingExtractedCDAudio();
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 4640f59615..5e53b92ccf 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -26,6 +26,7 @@
#include "groovie/music.h"
#include "groovie/groovie.h"
#include "groovie/resource.h"
+#include "groovie/tlcgame.h"
#include "backends/audiocd/audiocd.h"
#include "common/config-manager.h"
@@ -37,6 +38,7 @@
#include "audio/audiostream.h"
#include "audio/midiparser.h"
#include "audio/miles.h"
+#include "audio/decoders/mp3.h"
namespace Groovie {
@@ -746,4 +748,59 @@ bool MusicPlayerIOS::load(uint32 fileref, bool loop) {
return true;
}
+
+MusicPlayerTlc::MusicPlayerTlc(GroovieEngine *vm) : MusicPlayer(vm) {
+ vm->getTimerManager()->installTimerProc(&onTimer, 50 * 1000, this, "groovieMusic");
+}
+
+MusicPlayerTlc::~MusicPlayerTlc() {
+ _vm->getTimerManager()->removeTimerProc(&onTimer);
+}
+
+void MusicPlayerTlc::updateVolume() {
+ // Just set the mixer volume for the music sound type
+ _vm->_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _userVolume * _gameVolume / 100);
+}
+
+void MusicPlayerTlc::unload() {
+ MusicPlayer::unload();
+
+ _vm->_system->getMixer()->stopHandle(_handle);
+}
+
+bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
+ // Find correct filename
+ Common::String filename;
+ Common::File *fileHandle = new Common::File();
+ Audio::SeekableAudioStream *seekStream = NULL;
+
+ // Create the audio stream from fileref
+ filename = TlcGame::getTlcMusicFilename(fileref);
+ fileHandle->open(filename);
+ if (fileHandle->isOpen()) {
+ seekStream = Audio::makeMP3Stream(fileHandle, DisposeAfterUse::YES);
+ } else {
+ delete fileHandle;
+ }
+
+ if (!seekStream) {
+ warning("Could not play audio file '%s'", filename.c_str());
+ return false;
+ }
+
+ Audio::AudioStream *audStream = seekStream;
+
+ // Loop if requested
+ if (loop || 1)
+ audStream = Audio::makeLoopingAudioStream(seekStream, 0);
+
+ // MIDI player handles volume reset on load, IOS player doesn't - force update here
+ updateVolume();
+
+ // Play!
+ _vm->_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_handle, audStream);
+ return true;
+}
+
+
} // End of Groovie namespace
diff --git a/engines/groovie/music.h b/engines/groovie/music.h
index 35a4ae0cbd..06d1408fc5 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -35,6 +35,7 @@ class MidiParser;
namespace Groovie {
class GroovieEngine;
+class TlcGame;
class MusicPlayer {
public:
@@ -204,6 +205,20 @@ private:
Audio::SoundHandle _handle;
};
+class MusicPlayerTlc : public MusicPlayer {
+public:
+ MusicPlayerTlc(GroovieEngine *vm);
+ ~MusicPlayerTlc();
+
+protected:
+ void updateVolume();
+ bool load(uint32 fileref, bool loop);
+ void unload();
+
+private:
+ Audio::SoundHandle _handle;
+};
+
} // End of Groovie namespace
#endif // GROOVIE_MUSIC_H
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 17dab95fc7..e81f12b74f 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -371,8 +371,7 @@ uint8 Script::readScriptChar(bool allow7C, bool limitVal, bool limitVar) {
return result;
}
-uint32 Script::getVideoRefString() {
- Common::String str;
+void Script::readScriptString(Common::String &str) {
byte c;
while ((c = readScript8bits())) {
@@ -398,17 +397,22 @@ uint32 Script::getVideoRefString() {
// Append the current character at the end of the string
str += c;
}
+}
+
+uint32 Script::getVideoRefString(Common::String &resName) {
+ // Read String from Script (includes variable values)
+ readScriptString(resName);
// Add a trailing dot
- str += 0x2E;
+ resName += 0x2E;
- debugCN(0, kDebugScript, "%s", str.c_str());
+ debugCN(0, kDebugScript, "%s", resName.c_str());
// Extract the script name.
Common::String scriptname(_scriptFile.c_str(), _scriptFile.size() - 4);
// Get the fileref of the resource
- return _vm->_resMan->getRef(str, scriptname);
+ return _vm->_resMan->getRef(resName, scriptname);
}
bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) {
@@ -521,77 +525,82 @@ void Script::printString(Graphics::Surface *surface, const char *str) {
Common::rtrim(message);
// Draw the string
- _vm->_font->drawString(surface, message, 0, 16, 640, 0xE2, Graphics::kTextAlignCenter);
+ if (_version == kGroovieT7G) {
+ _vm->_font->drawString(surface, message, 0, 16, 640, 0xE2, Graphics::kTextAlignCenter);
+ } else {
+ _vm->_font->drawString(surface, message, 190, 190, 640, _vm->_pixelFormat.RGBToColor(0xff, 0x0A, 0x0A), Graphics::kTextAlignLeft);
+ }
}
// OPCODES
void Script::o_invalid() {
- error("Invalid opcode");
+ error("Groovie::Script: Invalid opcode");
}
void Script::o_nop() {
- debugC(1, kDebugScript, "NOP");
+ debugC(1, kDebugScript, "Groovie::Script: NOP");
}
void Script::o_nop8() {
uint8 tmp = readScript8bits();
- debugC(1, kDebugScript, "NOP8: 0x%02X", tmp);
+ debugC(1, kDebugScript, "Groovie::Script: NOP8: 0x%02X", tmp);
}
void Script::o_nop16() {
uint16 tmp = readScript16bits();
- debugC(1, kDebugScript, "NOP16: 0x%04X", tmp);
+ debugC(1, kDebugScript, "Groovie::Script: NOP16: 0x%04X", tmp);
}
void Script::o_nop32() {
uint32 tmp = readScript32bits();
- debugC(1, kDebugScript, "NOP32: 0x%08X", tmp);
+ debugC(1, kDebugScript, "Groovie::Script: NOP32: 0x%08X", tmp);
}
void Script::o_nop8or16() {
uint16 tmp = readScript8or16bits();
- debugC(1, kDebugScript, "NOP8OR16: 0x%04X", tmp);
+ debugC(1, kDebugScript, "Groovie::Script: NOP8OR16: 0x%04X", tmp);
}
void Script::o_playsong() { // 0x02
uint16 fileref = readScript16bits();
- debugC(1, kDebugScript, "PlaySong(0x%04X): Play xmidi file", fileref);
+ debugC(1, kDebugScript, "Groovie::Script: PlaySong(0x%04X): Play xmidi file", fileref);
if (fileref == 0x4C17) {
- warning("this song is special somehow");
+ warning("Groovie::Script: this song is special somehow");
// don't save the reference?
}
_vm->_musicPlayer->playSong(fileref);
}
void Script::o_bf9on() { // 0x03
- debugC(1, kDebugScript, "BF9ON: bitflag 9 turned on");
+ debugC(1, kDebugScript, "Groovie::Script: BF9ON: bitflag 9 turned on");
_bitflags |= 1 << 9;
}
void Script::o_palfadeout() {
- debugC(1, kDebugScript, "PALFADEOUT");
+ debugC(1, kDebugScript, "Groovie::Script: PALFADEOUT");
+ debugC(2, kDebugVideo, "Groovie::Script: PALFADEOUT");
_vm->_graphicsMan->fadeOut();
}
void Script::o_bf8on() { // 0x05
- debugC(1, kDebugScript, "BF8ON: bitflag 8 turned on");
+ debugC(1, kDebugScript, "Groovie::Script: BF8ON: bitflag 8 turned on");
_bitflags |= 1 << 8;
}
void Script::o_bf6on() { // 0x06
- debugC(1, kDebugScript, "BF6ON: bitflag 6 turned on");
+ debugC(1, kDebugScript, "Groovie::Script: BF6ON: bitflag 6 turned on");
_bitflags |= 1 << 6;
}
void Script::o_bf7on() { // 0x07
- debugC(1, kDebugScript, "BF7ON: bitflag 7 turned on");
+ debugC(1, kDebugScript, "Groovie::Script: BF7ON: bitflag 7 turned on");
_bitflags |= 1 << 7;
}
void Script::o_setbackgroundsong() { // 0x08
uint16 fileref = readScript16bits();
- debugC(1, kDebugScript, "SetBackgroundSong(0x%04X)", fileref);
+ debugC(1, kDebugScript, "Groovie::Script: SetBackgroundSong(0x%04X)", fileref);
_vm->_musicPlayer->setBackgroundSong(fileref);
}
@@ -600,15 +609,15 @@ void Script::o_videofromref() { // 0x09
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugC(1, kDebugScript, "VIDEOFROMREF(0x%04X) (Not fully imp): Play video file from ref", fileref);
- debugC(5, kDebugVideo, "Playing video 0x%04X via 0x09", fileref);
+ debugC(1, kDebugScript, "Groovie::Script: VIDEOFROMREF(0x%04X) (Not fully imp): Play video file from ref", fileref);
+ debugC(2, kDebugVideo, "\nGroovie::Script: @0x%04X: Playing video %d via 0x09 (VideoFromRef)", _currentInstruction-3, fileref);
}
switch (fileref) {
case 0x1C03: // Trilobyte logo
case 0x1C04: // Virgin logo
case 0x1C05: // Credits
if (fileref != _videoRef) {
- debugC(1, kDebugScript, "Use external file if available");
+ debugC(1, kDebugScript, "Groovie::Script: Use external file if available");
}
break;
@@ -620,8 +629,8 @@ void Script::o_videofromref() { // 0x09
case 0x206D: // Cards on table puzzle (bedroom)
case 0x2001: // Coins on table puzzle (bedroom)
if (fileref != _videoRef) {
- debugCN(1, kDebugScript, " (This video is special somehow!)");
- warning("(This video (0x%04X) is special somehow!)", fileref);
+ debugCN(1, kDebugScript, "Groovie::Script: (This video is special somehow!)");
+ warning("Groovie::Script: (This video (0x%04X) is special somehow!)", fileref);
}
default:
@@ -659,7 +668,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
if (fileref != _videoRef) {
// Debug bitflags
- debugCN(1, kDebugScript, "Play video 0x%04X (bitflags:", fileref);
+ debugCN(1, kDebugScript, "Groovie::Script: Play video 0x%04X (bitflags:", fileref);
for (int i = 15; i >= 0; i--) {
debugCN(1, kDebugScript, "%d", _bitflags & (1 << i)? 1 : 0);
if (i % 4 == 0) {
@@ -685,7 +694,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
_bitflags |= (1 << 15);
_vm->_videoPlayer->load(_videoFile, _bitflags);
} else {
- error("Couldn't open file");
+ error("Groovie::Script: Couldn't open file");
return true;
}
@@ -751,12 +760,12 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
}
void Script::o_bf5on() { // 0x0A
- debugC(1, kDebugScript, "BF5ON: bitflag 5 turned on");
+ debugC(1, kDebugScript, "Groovie::Script: BF5ON: bitflag 5 turned on");
_bitflags |= 1 << 5;
}
void Script::o_inputloopstart() { //0x0B
- debugC(5, kDebugScript, "Input loop start");
+ debugC(5, kDebugScript, "Groovie::Script: Input loop start");
// For TLC the regions for many questions are in an extra database. Reset internal region counters
if (_version == kGroovieTLC && _tlcGame != NULL) {
@@ -785,13 +794,13 @@ void Script::o_keyboardaction() {
// If there's an already planned action, do nothing
if (_inputAction != -1) {
- debugC(5, kDebugScript, "Test key == 0x%02X @0x%04X - skipped", val, address);
+ debugC(5, kDebugScript, "Groovie::Script: Test key == 0x%02X @0x%04X - skipped", val, address);
return;
}
// Check the typed key
if (_kbdChar == val) {
- debugC(5, kDebugScript, "Test key == 0x%02X @0x%04X - match", val, address);
+ debugC(5, kDebugScript, "Groovie::Script: Test key == 0x%02X @0x%04X - match", val, address);
// Exit the input loop
_inputLoopAddress = 0;
@@ -799,7 +808,7 @@ void Script::o_keyboardaction() {
// Save the action address
_inputAction = address;
} else {
- debugC(5, kDebugScript, "Test key == 0x%02X @0x%04X", val, address);
+ debugC(5, kDebugScript, "Groovie::Script: Test key == 0x%02X @0x%04X", val, address);
}
}
@@ -814,12 +823,12 @@ void Script::o_hotspot_rect() {
// TLC: The regions for many questions are in an extra database
if (_version == kGroovieTLC && left == 0 && top == 0 && right == 0 && bottom == 0 && _tlcGame != NULL) {
if (_tlcGame->getRegionNext(left, top, right, bottom) < 0) {
- debugC(5, kDebugScript, "HOTSPOT-RECT(x,x,x,x) @0x%04X cursor=%d SKIPPED", left, top, right, bottom, address, cursor);
+ debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-RECT(x,x,x,x) @0x%04X cursor=%d SKIPPED", left, top, right, bottom, address, cursor);
return;
}
}
- debugC(5, kDebugScript, "HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d", left, top, right, bottom, address, cursor);
+ debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d", left, top, right, bottom, address, cursor);
// Mark the specified rectangle
Common::Rect rect(left, top, right, bottom);
@@ -829,7 +838,7 @@ void Script::o_hotspot_rect() {
void Script::o_hotspot_left() {
uint16 address = readScript16bits();
- debugC(5, kDebugScript, "HOTSPOT-LEFT @0x%04X", address);
+ debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-LEFT @0x%04X", address);
// Mark the leftmost 100 pixels of the game area
Common::Rect rect(0, 80, 100, 400);
@@ -839,7 +848,7 @@ void Script::o_hotspot_left() {
void Script::o_hotspot_right() {
uint16 address = readScript16bits();
- debugC(5, kDebugScript, "HOTSPOT-RIGHT @0x%04X", address);
+ debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-RIGHT @0x%04X", address);
// Mark the rightmost 100 pixels of the game area
Common::Rect rect(540, 80, 640, 400);
@@ -849,7 +858,7 @@ void Script::o_hotspot_right() {
void Script::o_hotspot_center() {
uint16 address = readScript16bits();
- debugC(5, kDebugScript, "HOTSPOT-CENTER @0x%04X", address);
+ debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-CENTER @0x%04X", address);
// Mark the centermost 240 pixels of the game area
Common::Rect rect(200, 80, 440, 400);
@@ -859,7 +868,7 @@ void Script::o_hotspot_center() {
void Script::o_hotspot_current() {
uint16 address = readScript16bits();
- debugC(5, kDebugScript, "HOTSPOT-CURRENT @0x%04X", address);
+ debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-CURRENT @0x%04X", address);
// The original interpreter doesn't check the position, so accept the
// whole screen
@@ -868,7 +877,7 @@ void Script::o_hotspot_current() {
}
void Script::o_inputloopend() {
- debugC(5, kDebugScript, "Input loop end");
+ debugC(5, kDebugScript, "Groovie::Script: Input loop end");
// Handle the predefined hotspots
if (_hotspotTopAction) {
@@ -921,15 +930,20 @@ void Script::o_random() {
uint16 varnum = readScript8or16bits();
uint8 maxnum = readScript8bits();
- debugC(1, kDebugScript, "RANDOM: var[0x%04X] = rand(%d)", varnum, maxnum);
+ debugC(1, kDebugScript, "Groovie::Script: RANDOM: var[0x%04X] = rand(%d)", varnum, maxnum);
- setVariable(varnum, _random.getRandomNumber(maxnum));
+ // TODO: Check if this is really different between the Engines
+ if (_version == kGroovieT7G) {
+ setVariable(varnum, _random.getRandomNumber(maxnum));
+ } else {
+ setVariable(varnum, _random.getRandomNumber(maxnum-1));
+ }
}
void Script::o_jmp() {
uint16 address = readScript16bits();
- debugC(1, kDebugScript, "JMP @0x%04X", address);
+ debugC(1, kDebugScript, "Groovie::Script: JMP @0x%04X", address);
// Set the current address
_currentInstruction = address;
@@ -938,7 +952,7 @@ void Script::o_jmp() {
void Script::o_loadstring() {
uint16 varnum = readScript8or16bits();
- debugCN(1, kDebugScript, "LOADSTRING var[0x%04X..] =", varnum);
+ debugCN(1, kDebugScript, "Groovie::Script: LOADSTRING var[0x%04X..] =", varnum);
do {
setVariable(varnum++, readScriptChar(true, true, true));
debugCN(1, kDebugScript, " 0x%02X", _variables[varnum - 1]);
@@ -949,7 +963,7 @@ void Script::o_loadstring() {
void Script::o_ret() {
uint8 val = readScript8bits();
- debugC(1, kDebugScript, "RET %d", val);
+ debugC(1, kDebugScript, "Groovie::Script: RET %d", val);
// Set the return value
setVariable(0x102, val);
@@ -959,14 +973,14 @@ void Script::o_ret() {
_stacktop--;
_currentInstruction = _stack[_stacktop];
} else {
- error("Return: Stack is empty");
+ error("Groovie::Script: Return: Stack is empty");
}
}
void Script::o_call() {
uint16 address = readScript16bits();
- debugC(1, kDebugScript, "CALL @0x%04X", address);
+ debugC(1, kDebugScript, "Groovie::Script: CALL @0x%04X", address);
// Save return address in the call stack
_stack[_stacktop] = _currentInstruction;
@@ -979,7 +993,7 @@ void Script::o_call() {
void Script::o_sleep() {
uint16 time = readScript16bits();
- debugC(1, kDebugScript, "SLEEP 0x%04X", time);
+ debugC(1, kDebugScript, "Groovie::Script: SLEEP 0x%04X (%d ms)", time, time*3);
_vm->_system->delayMillis(time * 3);
}
@@ -988,7 +1002,7 @@ void Script::o_strcmpnejmp() { // 0x1A
uint16 varnum = readScript8or16bits();
uint8 result = 1;
- debugCN(1, kDebugScript, "STRCMP-NEJMP: var[0x%04X..],", varnum);
+ debugCN(1, kDebugScript, "Groovie::Script: STRCMP-NEJMP: var[0x%04X..],", varnum);
do {
uint8 val = readScriptChar(true, true, true);
@@ -1012,7 +1026,7 @@ void Script::o_strcmpnejmp() { // 0x1A
void Script::o_xor_obfuscate() {
uint16 varnum = readScript8or16bits();
- debugCN(1, kDebugScript, "XOR OBFUSCATE: var[0x%04X..] = ", varnum);
+ debugCN(1, kDebugScript, "Groovie::Script: XOR OBFUSCATE: var[0x%04X..] = ", varnum);
do {
uint8 val = readScript8bits();
_firstbit = ((val & 0x80) != 0);
@@ -1031,8 +1045,8 @@ void Script::o_vdxtransition() { // 0x1C
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugC(1, kDebugScript, "VDX transition fileref = 0x%04X", fileref);
- debugC(1, kDebugVideo, "Playing video 0x%04X with transition", fileref);
+ debugC(1, kDebugScript, "Groovie::Script: VDX transition fileref = 0x%04X", fileref);
+ debugC(2, kDebugVideo, "\nGroovie::Script: @0x%04X: Playing video %d via 0x1C (VdxTransition)", _currentInstruction-3, fileref);
}
// Set bit 1
@@ -1057,7 +1071,7 @@ void Script::o_swap() {
uint16 varnum1 = readScript8or16bits();
uint16 varnum2 = readScript16bits();
- debugC(1, kDebugScript, "SWAP var[0x%04X] <-> var[0x%04X]", varnum1, varnum2);
+ debugC(1, kDebugScript, "Groovie::Script: SWAP var[0x%04X] <-> var[0x%04X]", varnum1, varnum2);
uint8 tmp = _variables[varnum1];
setVariable(varnum1, _variables[varnum2]);
@@ -1067,7 +1081,7 @@ void Script::o_swap() {
void Script::o_inc() {
uint16 varnum = readScript8or16bits();
- debugC(1, kDebugScript, "INC var[0x%04X]", varnum);
+ debugC(1, kDebugScript, "Groovie::Script: INC var[0x%04X]", varnum);
setVariable(varnum, _variables[varnum] + 1);
}
@@ -1075,7 +1089,7 @@ void Script::o_inc() {
void Script::o_dec() {
uint16 varnum = readScript8or16bits();
- debugC(1, kDebugScript, "DEC var[0x%04X]", varnum);
+ debugC(1, kDebugScript, "Groovie::Script: DEC var[0x%04X]", varnum);
setVariable(varnum, _variables[varnum] - 1);
}
@@ -1101,7 +1115,8 @@ void Script::o_strcmpnejmp_var() { // 0x21
}
void Script::o_copybgtofg() { // 0x22
- debugC(1, kDebugScript, "COPY_BG_TO_FG");
+ debugC(1, kDebugScript, "Groovie::Script: COPY_BG_TO_FG");
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_BG_TO_FG", _currentInstruction-1);
memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * _vm->_graphicsMan->_foreground.h);
}
@@ -1109,7 +1124,7 @@ void Script::o_strcmpeqjmp() { // 0x23
uint16 varnum = readScript8or16bits();
uint8 result = 1;
- debugCN(1, kDebugScript, "STRCMP-EQJMP: var[0x%04X..],", varnum);
+ debugCN(1, kDebugScript, "Groovie::Script: STRCMP-EQJMP: var[0x%04X..],", varnum);
do {
uint8 val = readScriptChar(true, true, true);
@@ -1133,7 +1148,7 @@ void Script::o_mov() {
uint16 varnum1 = readScript8or16bits();
uint16 varnum2 = readScript16bits();
- debugC(1, kDebugScript, "MOV var[0x%04X] = var[0x%04X]", varnum1, varnum2);
+ debugC(1, kDebugScript, "Groovie::Script: MOV var[0x%04X] = var[0x%04X]", varnum1, varnum2);
setVariable(varnum1, _variables[varnum2]);
}
@@ -1142,20 +1157,25 @@ void Script::o_add() {
uint16 varnum1 = readScript8or16bits();
uint16 varnum2 = readScript16bits();
- debugC(1, kDebugScript, "ADD var[0x%04X] += var[0x%04X]", varnum1, varnum2);
+ debugC(1, kDebugScript, "Groovie::Script: ADD var[0x%04X] += var[0x%04X]", varnum1, varnum2);
setVariable(varnum1, _variables[varnum1] + _variables[varnum2]);
}
void Script::o_videofromstring1() {
+ Common::String vidName;
uint16 instStart = _currentInstruction;
- uint32 fileref = getVideoRefString();
+ uint32 fileref = getVideoRefString(vidName);
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugC(0, kDebugScript, "VIDEOFROMSTRING1 0x%04X", fileref);
+ debugC(0, kDebugScript, "Groovie::Script: VIDEOFROMSTRING1 %d ('%s')", fileref, vidName.c_str());
+ debugC(2, kDebugVideo, "\nGroovie::Script: @0x%04X: Playing video %d ('%s') via 0x26 (VideoFromString1)", instStart-1, fileref, vidName.c_str());
}
+ // Clear bit 1
+ _bitflags &= ~(1 << 1);
+
// Play the video
if (!playvideofromref(fileref)) {
// Move _currentInstruction back
@@ -1164,12 +1184,14 @@ void Script::o_videofromstring1() {
}
void Script::o_videofromstring2() {
+ Common::String vidName;
uint16 instStart = _currentInstruction;
- uint32 fileref = getVideoRefString();
+ uint32 fileref = getVideoRefString(vidName);
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugC(0, kDebugScript, "VIDEOFROMSTRING2 0x%04X", fileref);
+ debugC(0, kDebugScript, "Groovie::Script: VIDEOFROMSTRING2 %d ('%s')", fileref, vidName.c_str());
+ debugC(2, kDebugVideo, "\nGroovie::Script: @0x%04X: Playing video %d ('%s') via 0x27 (VideoFromString2)", instStart-1, fileref, vidName.c_str());
}
// Set bit 1
@@ -1188,11 +1210,11 @@ void Script::o_videofromstring2() {
}
void Script::o_stopmidi() {
- debugC(1, kDebugScript, "STOPMIDI (TODO)");
+ debugC(1, kDebugScript, "Groovie::Script: STOPMIDI (TODO)");
}
void Script::o_endscript() {
- debugC(1, kDebugScript, "END OF SCRIPT");
+ debugC(1, kDebugScript, "Groovie::Script: END OF SCRIPT");
_vm->quitGame();
}
@@ -1200,7 +1222,7 @@ void Script::o_sethotspottop() {
uint16 address = readScript16bits();
uint8 cursor = readScript8bits();
- debugC(5, kDebugScript, "SETHOTSPOTTOP @0x%04X cursor=%d", address, cursor);
+ debugC(5, kDebugScript, "Groovie::Script: SETHOTSPOTTOP @0x%04X cursor=%d", address, cursor);
_hotspotTopAction = address;
_hotspotTopCursor = cursor;
@@ -1210,7 +1232,7 @@ void Script::o_sethotspotbottom() {
uint16 address = readScript16bits();
uint8 cursor = readScript8bits();
- debugC(5, kDebugScript, "SETHOTSPOTBOTTOM @0x%04X cursor=%d", address, cursor);
+ debugC(5, kDebugScript, "Groovie::Script: SETHOTSPOTBOTTOM @0x%04X cursor=%d", address, cursor);
_hotspotBottomAction = address;
_hotspotBottomCursor = cursor;
@@ -1220,7 +1242,7 @@ void Script::o_loadgame() {
uint16 varnum = readScript8or16bits();
uint8 slot = _variables[varnum];
- debugC(1, kDebugScript, "LOADGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot);
+ debugC(1, kDebugScript, "Groovie::Script: LOADGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot);
loadgame(slot);
if (_version == kGroovieT7G) {
@@ -1232,7 +1254,7 @@ void Script::o_savegame() {
uint16 varnum = readScript8or16bits();
uint8 slot = _variables[varnum];
- debugC(1, kDebugScript, "SAVEGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot);
+ debugC(1, kDebugScript, "Groovie::Script: SAVEGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot);
savegame(slot);
}
@@ -1240,7 +1262,7 @@ void Script::o_savegame() {
void Script::o_hotspotbottom_4() { //0x30
uint16 address = readScript16bits();
- debugC(5, kDebugScript, "HOTSPOT-BOTTOM @0x%04X", address);
+ debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-BOTTOM @0x%04X", address);
// Mark the 80 pixels under the game area
Common::Rect rect(0, 400, 640, 480);
@@ -1251,7 +1273,7 @@ void Script::o_midivolume() {
uint16 arg1 = readScript16bits();
uint16 arg2 = readScript16bits();
- debugC(1, kDebugScript, "MIDI volume: %d %d", arg1, arg2);
+ debugC(1, kDebugScript, "Groovie::Script: MIDI volume: %d %d", arg1, arg2);
_vm->_musicPlayer->setGameVolume(arg1, arg2);
}
@@ -1260,7 +1282,7 @@ void Script::o_jne() {
uint16 varnum2 = readScript16bits();
uint16 address = readScript16bits();
- debugCN(1, kDebugScript, "JNE: var[var[0x%04X] - 0x31] != var[0x%04X] @0x%04X", varnum1, varnum2, address);
+ debugCN(1, kDebugScript, "Groovie::Script: JNE: var[var[0x%04X] - 0x31] != var[0x%04X] @0x%04X", varnum1, varnum2, address);
if (_variables[_variables[varnum1] - 0x31] != _variables[varnum2]) {
_currentInstruction = address;
@@ -1274,7 +1296,7 @@ void Script::o_loadstringvar() {
uint16 varnum = readScript8or16bits();
varnum = _variables[varnum] - 0x31;
- debugCN(1, kDebugScript, "LOADSTRINGVAR var[0x%04X..] =", varnum);
+ debugCN(1, kDebugScript, "Groovie::Script: LOADSTRINGVAR var[0x%04X..] =", varnum);
do {
setVariable(varnum++, readScriptChar(true, true, true));
debugCN(1, kDebugScript, " 0x%02X", _variables[varnum - 1]);
@@ -1286,7 +1308,7 @@ void Script::o_chargreatjmp() {
uint16 varnum = readScript8or16bits();
uint8 result = 0;
- debugCN(1, kDebugScript, "CHARGREAT-JMP: var[0x%04X..],", varnum);
+ debugCN(1, kDebugScript, "Groovie::Script: CHARGREAT-JMP: var[0x%04X..],", varnum);
do {
uint8 val = readScriptChar(true, true, true);
@@ -1307,7 +1329,7 @@ void Script::o_chargreatjmp() {
}
void Script::o_bf7off() {
- debugC(1, kDebugScript, "BF7OFF: bitflag 7 turned off");
+ debugC(1, kDebugScript, "Groovie::Script: BF7OFF: bitflag 7 turned off");
_bitflags &= ~(1 << 7);
}
@@ -1315,7 +1337,7 @@ void Script::o_charlessjmp() {
uint16 varnum = readScript8or16bits();
uint8 result = 0;
- debugCN(1, kDebugScript, "CHARLESS-JMP: var[0x%04X..],", varnum);
+ debugCN(1, kDebugScript, "Groovie::Script: CHARLESS-JMP: var[0x%04X..],", varnum);
do {
uint8 val = readScriptChar(true, true, true);
@@ -1344,7 +1366,7 @@ void Script::o_copyrecttobg() { // 0x37
// Sanity checks to prevent bad pointer access crashes
if (left > right) {
- warning("COPYRECT left:%d > right:%d", left, right);
+ warning("Groovie::Script: COPYRECT left:%d > right:%d", left, right);
// swap over left and right parameters
uint16 j;
j = right;
@@ -1352,7 +1374,7 @@ void Script::o_copyrecttobg() { // 0x37
left = j;
}
if (top > bottom) {
- warning("COPYRECT top:%d > bottom:%d", top, bottom);
+ warning("Groovie::Script: COPYRECT top:%d > bottom:%d", top, bottom);
// swap over top and bottom parameters
uint16 j;
j = bottom;
@@ -1360,50 +1382,58 @@ void Script::o_copyrecttobg() { // 0x37
top = j;
}
if (top < baseTop) {
- warning("COPYRECT top < baseTop... clamping");
+ warning("Groovie::Script: COPYRECT top < baseTop... clamping");
top = baseTop;
}
if (top >= 480) {
- warning("COPYRECT top >= 480... clamping");
+ warning("Groovie::Script: COPYRECT top >= 480... clamping");
top = 480 - 1;
}
if (bottom >= 480) {
- warning("COPYRECT bottom >= 480... clamping");
+ warning("Groovie::Script: COPYRECT bottom >= 480... clamping");
bottom = 480 - 1;
}
if (left >= 640) {
- warning("COPYRECT left >= 640... clamping");
+ warning("Groovie::Script: COPYRECT left >= 640... clamping");
left = 640 - 1;
}
if (right >= 640) {
- warning("COPYRECT right >= 640... clamping");
+ warning("Groovie::Script: COPYRECT right >= 640... clamping");
right = 640 - 1;
}
uint16 i, width = right - left, height = bottom - top;
uint32 offset = 0;
byte *fg, *bg;
+ uint32 pitch = _vm->_graphicsMan->_foreground.pitch;
- debugC(1, kDebugScript, "COPYRECT((%d,%d)->(%d,%d))", left, top, right, bottom);
+ debugC(1, kDebugScript, "Groovie::Script: COPYRECT((%d,%d)->(%d,%d))", left, top, right, bottom);
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPYRECT((%d,%d)->(%d,%d))",_currentInstruction-9, left, top, right, bottom);
fg = (byte *)_vm->_graphicsMan->_foreground.getBasePtr(left, top - baseTop);
bg = (byte *)_vm->_graphicsMan->_background.getBasePtr(left, top - baseTop);
for (i = 0; i < height; i++) {
- memcpy(bg + offset, fg + offset, width);
- offset += 640;
+ memcpy(bg + offset, fg + offset, width * _vm->_graphicsMan->_foreground.format.bytesPerPixel);
+ offset += pitch;
}
- _vm->_system->copyRectToScreen(_vm->_graphicsMan->_background.getBasePtr(left, top - baseTop), 640, left, top, width, height);
+ // _vm->_graphicsMan->_background.copyFrom(_vm->_graphicsMan->_foreground);
+
+ //{
+ // Graphics::Surface *_bg = &_vm->_graphicsMan->_background;
+ // _vm->_system->copyRectToScreen(_bg->getPixels(), _bg->pitch, 0, (_vm->_system->getHeight() - _bg->h) / 2, _bg->w, _bg->h);
+ //}
+ _vm->_system->copyRectToScreen(_vm->_graphicsMan->_background.getBasePtr(left, top - baseTop), pitch, left, top, width, height);
_vm->_graphicsMan->change();
}
void Script::o_restorestkpnt() {
- debugC(1, kDebugScript, "Restore stack pointer from saved (TODO)");
+ debugC(1, kDebugScript, "Groovie::Script: Restore stack pointer from saved (TODO)");
}
void Script::o_obscureswap() {
uint16 var1, var2, tmp;
- debugC(1, kDebugScript, "OBSCSWAP");
+ debugC(1, kDebugScript, "Groovie::Script: OBSCSWAP");
// Read the first variable
var1 = readScriptChar(false, true, true) * 10;
@@ -1423,7 +1453,8 @@ void Script::o_printstring() {
char stringstorage[15];
uint8 counter = 0;
- debugC(1, kDebugScript, "PRINTSTRING");
+ debugC(1, kDebugScript, "Groovie::Script: PRINTSTRING");
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: PRINTSTRING", _currentInstruction-1);
memset(stringstorage, 0, 15);
do {
@@ -1461,7 +1492,22 @@ void Script::o_hotspot_slot() {
uint16 address = readScript16bits();
uint16 cursor = readScript8bits();
- debugC(1, kDebugScript, "HOTSPOT-SLOT %d (%d,%d,%d,%d) @0x%04X cursor=%d (TODO)", slot, left, top, right, bottom, address, cursor);
+ debugC(1, kDebugScript, "Groovie::Script: HOTSPOT-SLOT %d (%d,%d,%d,%d) @0x%04X cursor=%d (TODO)", slot, left, top, right, bottom, address, cursor);
+
+ // Set rectangle according to the used engine. To remove the previously written text an the screen.
+ Common::Rect removeText;
+ if (_version == kGroovieT7G) {
+ removeText.left = 0;
+ removeText.top = 0;
+ removeText.right = 640;
+ removeText.bottom = 80;
+ } else {
+ // Only tested for 11th hour. TLC does not use this command.
+ removeText.left = 120;
+ removeText.top = 185;
+ removeText.right = 400;
+ removeText.bottom = 215;
+ }
Common::Rect rect(left, top, right, bottom);
if (hotspot(rect, address, cursor)) {
@@ -1469,11 +1515,10 @@ void Script::o_hotspot_slot() {
return;
}
- Common::Rect topbar(640, 80);
Graphics::Surface *gamescreen = _vm->_system->lockScreen();
// Clear the top bar
- gamescreen->fillRect(topbar, 0);
+ gamescreen->fillRect(removeText, 0); // 0 works for both color formats (Groovie V1 and V2)
printString(gamescreen, _saveNames[slot].c_str());
@@ -1481,19 +1526,21 @@ void Script::o_hotspot_slot() {
// Save the currently highlighted slot
_hotspotSlot = slot;
+ _vm->_graphicsMan->change();
+
} else {
if (_hotspotSlot == slot) {
- Common::Rect topbar(640, 80);
-
Graphics::Surface *gamescreen;
gamescreen = _vm->_system->lockScreen();
- gamescreen->fillRect(topbar, 0);
+ gamescreen->fillRect(removeText, 0); // 0 works for both color formats (Groovie V1 and V2)
_vm->_system->unlockScreen();
// Removing the slot highlight
_hotspotSlot = (uint16)-1;
+
+ _vm->_graphicsMan->change();
}
}
}
@@ -1501,7 +1548,7 @@ void Script::o_hotspot_slot() {
// Checks valid save games. Even for TLC (uses only 4 user save games) the function
// checks for 10 save games.
void Script::o_checkvalidsaves() {
- debugC(1, kDebugScript, "CHECKVALIDSAVES");
+ debugC(1, kDebugScript, "Groovie::Script: CHECKVALIDSAVES");
// Reset the array of valid saves and the savegame names cache
for (int i = 0; i < MAX_SAVES; i++) {
@@ -1518,7 +1565,7 @@ void Script::o_checkvalidsaves() {
while (it != list.end()) {
int8 slot = it->getSaveSlot();
if (SaveLoad::isSlotValid(slot)) {
- debugC(2, kDebugScript, " Found valid savegame: %s", it->getDescription().encode().c_str());
+ debugC(2, kDebugScript, "Groovie::Script: Found valid savegame: %s", it->getDescription().encode().c_str());
// Mark this slot as used
setVariable(slot, 1);
@@ -1532,7 +1579,7 @@ void Script::o_checkvalidsaves() {
// Save the number of valid saves
setVariable(0x104, count);
- debugC(1, kDebugScript, " Found %d valid savegames", count);
+ debugC(1, kDebugScript, "Groovie::Script: Found %d valid savegames", count);
}
void Script::o_resetvars() {
@@ -1546,7 +1593,7 @@ void Script::o_mod() {
uint16 varnum = readScript8or16bits();
uint8 val = readScript8bits();
- debugC(1, kDebugScript, "MOD var[0x%04X] %%= %d", varnum, val);
+ debugC(1, kDebugScript, "Groovie::Script: MOD var[0x%04X] %%= %d", varnum, val);
setVariable(varnum, _variables[varnum] % val);
}
@@ -1558,11 +1605,11 @@ void Script::o_loadscript() {
while ((c = readScript8bits())) {
filename += c;
}
- debugC(1, kDebugScript, "LOADSCRIPT %s", filename.c_str());
+ debugC(1, kDebugScript, "Groovie::Script: LOADSCRIPT %s", filename.c_str());
// Just 1 level of sub-scripts are allowed
if (_savedCode) {
- error("Tried to load a level 2 sub-script");
+ error("Groovie::Script: Tried to load a level 2 sub-script");
}
// Save the current code
@@ -1575,7 +1622,7 @@ void Script::o_loadscript() {
// Load the sub-script
if (!loadScript(filename)) {
- error("Couldn't load sub-script %s", filename.c_str());
+ error("Groovie::Script: Couldn't load sub-script %s", filename.c_str());
}
// Save the current stack top
@@ -1593,7 +1640,7 @@ void Script::o_setvideoorigin() {
// Set bitflag 7
_bitflags |= 1 << 7;
- debugC(1, kDebugScript, "SetVideoOrigin(0x%04X,0x%04X) (%d, %d)", origX, origY, origX, origY);
+ debugC(1, kDebugScript, "Groovie::Script: SetVideoOrigin(0x%04X,0x%04X) (%d, %d)", origX, origY, origX, origY);
_vm->_videoPlayer->setOrigin(origX, origY);
}
@@ -1601,7 +1648,7 @@ void Script::o_sub() {
uint16 varnum1 = readScript8or16bits();
uint16 varnum2 = readScript16bits();
- debugC(1, kDebugScript, "SUB var[0x%04X] -= var[0x%04X]", varnum1, varnum2);
+ debugC(1, kDebugScript, "Groovie::Script: SUB var[0x%04X] -= var[0x%04X]", varnum1, varnum2);
setVariable(varnum1, _variables[varnum1] - _variables[varnum2]);
}
@@ -1611,7 +1658,7 @@ void Script::o_cellmove() {
byte *scriptBoard = &_variables[0x19];
byte startX, startY, endX, endY;
- debugC(1, kDebugScript, "CELL MOVE var[0x%02X]", depth);
+ debugC(1, kDebugScript, "Groovie::Script: CELL MOVE var[0x%02X]", depth);
if (!_staufsMove)
_staufsMove = new CellGame;
@@ -1634,11 +1681,11 @@ void Script::o_cellmove() {
void Script::o_returnscript() {
uint8 val = readScript8bits();
- debugC(1, kDebugScript, "RETURNSCRIPT @0x%02X", val);
+ debugC(1, kDebugScript, "Groovie::Script: RETURNSCRIPT @0x%02X", val);
// Are we returning from a sub-script?
if (!_savedCode) {
- error("Tried to return from the main script");
+ error("Groovie::Script: Tried to return from the main script");
}
// Set the return value
@@ -1667,7 +1714,7 @@ void Script::o_returnscript() {
void Script::o_sethotspotright() {
uint16 address = readScript16bits();
- debugC(1, kDebugScript, "SETHOTSPOTRIGHT @0x%04X", address);
+ debugC(1, kDebugScript, "Groovie::Script: SETHOTSPOTRIGHT @0x%04X", address);
_hotspotRightAction = address;
}
@@ -1675,13 +1722,13 @@ void Script::o_sethotspotright() {
void Script::o_sethotspotleft() {
uint16 address = readScript16bits();
- debugC(1, kDebugScript, "SETHOTSPOTLEFT @0x%04X", address);
+ debugC(1, kDebugScript, "Groovie::Script: SETHOTSPOTLEFT @0x%04X", address);
_hotspotLeftAction = address;
}
void Script::o_getcd() {
- debugC(1, kDebugScript, "GETCD");
+ debugC(1, kDebugScript, "Groovie::Script: GETCD");
// By default set it to no CD available
int8 cd = -1;
@@ -1708,7 +1755,7 @@ void Script::o_getcd() {
void Script::o_playcd() {
uint8 val = readScript8bits();
- debugC(1, kDebugScript, "PLAYCD %d", val);
+ debugC(1, kDebugScript, "Groovie::Script: PLAYCD %d", val);
if (val == 2) {
// TODO: Play the alternative logo
@@ -1720,7 +1767,7 @@ void Script::o_playcd() {
void Script::o_musicdelay() {
uint16 delay = readScript16bits();
- debugC(1, kDebugScript, "MUSICDELAY %d", delay);
+ debugC(1, kDebugScript, "Groovie::Script: MUSICDELAY %d", delay);
_vm->_musicPlayer->setBackgroundDelay(delay);
}
@@ -1732,7 +1779,7 @@ void Script::o_hotspot_outrect() {
uint16 bottom = readScript16bits();
uint16 address = readScript16bits();
- debugC(1, kDebugScript, "HOTSPOT-OUTRECT(%d,%d,%d,%d) @0x%04X (TODO)", left, top, right, bottom, address);
+ debugC(1, kDebugScript, "Groovie::Script: HOTSPOT-OUTRECT(%d,%d,%d,%d) @0x%04X (TODO)", left, top, right, bottom, address);
// Test if the current mouse position is outside the specified rectangle
Common::Rect rect(left, top, right, bottom);
@@ -1749,14 +1796,14 @@ void Script::o_stub56() {
uint8 val2 = readScript8bits();
uint8 val3 = readScript8bits();
- debugC(1, kDebugScript, "STUB56: 0x%08X 0x%02X 0x%02X", val1, val2, val3);
+ debugC(1, kDebugScript, "Groovie::Script: STUB56: 0x%08X 0x%02X 0x%02X", val1, val2, val3);
}
void Script::o_stub59() {
uint16 val1 = readScript8or16bits();
uint8 val2 = readScript8bits();
- debugC(1, kDebugScript, "STUB59: 0x%04X 0x%02X", val1, val2);
+ debugC(1, kDebugScript, "Groovie::Script: STUB59: 0x%04X 0x%02X", val1, val2);
}
void Script::o2_printstring() {
@@ -1766,35 +1813,57 @@ void Script::o2_printstring() {
uint8 colg = readScript8bits();
uint8 colb = readScript8bits();
uint32 col = _vm->_pixelFormat.RGBToColor(colr, colg, colb);
- char message[20];
- memset(message, 0, sizeof(message));
+ Common::String text;
- for (int i = 0; i < 19; i++) {
- if (_variables[i] > 0) {
- message[i] = _variables[i] + 0x30;
- }
- }
-
- debugC(1, kDebugScript, "PRINTSTRING (%d, %d): %s", posx, posy, message);
+ // Read string from Script
+ readScriptString(text);
+ debugC(1, kDebugScript, "Groovie::Script: PRINTSTRING (%d, %d): %s", posx, posy, text.c_str());
Graphics::Surface *gamescreen = _vm->_system->lockScreen();
- _vm->_font->drawString(gamescreen, message, posx, posy, 640, col, Graphics::kTextAlignLeft);
+ _vm->_font->drawString(gamescreen, text.c_str(), posx, posy, 640, col, Graphics::kTextAlignLeft);
_vm->_system->unlockScreen();
_vm->_graphicsMan->change(); // Force Update screen after step
-
- // 42 Bytes unknown
- _currentInstruction += 39;
}
void Script::o2_playsong() {
uint32 fileref = readScript32bits();
- debugC(1, kDebugScript, "PlaySong(0x%08X): Play xmidi file", fileref);
+ debugC(1, kDebugScript, "Groovie::Script: PlaySong(0x%08X): Play xmidi file", fileref);
_vm->_musicPlayer->playSong(fileref);
}
+void Script::o2_midicontrol() {
+ uint16 arg1 = readScript16bits();
+ uint16 arg2 = readScript16bits();
+
+ switch (arg1) {
+ case 0:
+ // Stop Playback
+ debugC(1, kDebugScript, "Groovie::Script: MIDI %d:Stop: %d", arg1, arg2);
+ _vm->_musicPlayer->setUserVolume(0);
+ // _vm->_musicPlayer->setBackgroundDelay(0);
+ break;
+
+ case 1:
+ // Play song from index
+ debugC(1, kDebugScript, "Groovie::Script: MIDI %d: Play song %d", arg1, arg2);
+ _vm->_musicPlayer->playSong(arg2);
+ _vm->_musicPlayer->setUserVolume(100);
+// _vm->_musicPlayer->setBackgroundSong(arg2);
+// _vm->_musicPlayer->startBackground();
+ break;
+
+ case 3:
+ // Set Volume? Or is it some kind of fade in / out
+ debugC(1, kDebugScript, "Groovie::Script: MIDI %d: Set volume/time: %d", arg1, arg2);
+ //_vm->_musicPlayer->setUserVolume(arg2);
+ break;
+ }
+
+ //_vm->_musicPlayer->setGameVolume(arg1, arg2);
+}
void Script::o2_setbackgroundsong() {
uint32 fileref = readScript32bits();
- debugC(1, kDebugScript, "SetBackgroundSong(0x%08X)", fileref);
+ debugC(1, kDebugScript, "Groovie::Script: SetBackgroundSong(0x%08X)", fileref);
_vm->_musicPlayer->setBackgroundSong(fileref);
}
@@ -1803,10 +1872,13 @@ void Script::o2_videofromref() {
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugC(1, kDebugScript, "VIDEOFROMREF(0x%08X) (Not fully imp): Play video file from ref", fileref);
- debugC(5, kDebugVideo, "Playing video 0x%08X via 0x09", fileref);
+ debugC(1, kDebugScript, "Groovie::Script: VIDEOFROMREF(0x%08X) (Not fully imp): Play video file from ref", fileref);
+ debugC(2, kDebugVideo, "\nGroovie::Script: @0x%04X: Playing video %d via 0x09", _currentInstruction-5, fileref);
}
+ // Clear bit 1
+ _bitflags &= ~(1 << 1);
+
// Play the video
if (!playvideofromref(fileref)) {
// Move _currentInstruction back
@@ -1819,8 +1891,8 @@ void Script::o2_vdxtransition() {
// Show the debug information just when starting the playback
if (fileref != _videoRef) {
- debugC(1, kDebugScript, "VDX transition fileref = 0x%08X", fileref);
- debugC(1, kDebugVideo, "Playing video 0x%08X with transition", fileref);
+ debugC(1, kDebugScript, "Groovie::Script: VDX transition fileref = 0x%08X", fileref);
+ debugC(2, kDebugVideo, "\nGroovie::Script: @0x%04X: Playing video %d with transition via 0x1C", _currentInstruction-5, fileref);
}
// Set bit 1
@@ -1843,13 +1915,14 @@ void Script::o2_copyscreentobg() {
// TODO: Parameter
if (val)
- warning("o2_copyscreentobg: Param is %d", val);
+ warning("Groovie::Script: o2_copyscreentobg: Param is %d", val);
Graphics::Surface *screen = _vm->_system->lockScreen();
_vm->_graphicsMan->_background.copyFrom(screen->getSubArea(Common::Rect(0, 80, 640, 320)));
_vm->_system->unlockScreen();
- debugC(1, kDebugScript, "CopyScreenToBG3: 0x%04X", val);
+ debugC(1, kDebugScript, "Groovie::Script: CopyScreenToBG3: 0x%04X", val);
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: CopyScreenToBG3: 0x%04X", _currentInstruction-3, val);
}
void Script::o2_copybgtoscreen() {
@@ -1857,18 +1930,19 @@ void Script::o2_copybgtoscreen() {
// TODO: Parameter
if (val)
- warning("o2_copybgtoscreen: Param is %d", val);
+ warning("Groovie::Script: o2_copybgtoscreen: Param is %d", val);
Graphics::Surface *screen = _vm->_system->lockScreen();
_vm->_graphicsMan->_background.copyRectToSurface(*screen, 0, 80, Common::Rect(0, 0, 640, 320 - 80));
_vm->_system->unlockScreen();
- debugC(1, kDebugScript, "CopyBG3ToScreen: 0x%04X", val);
+ debugC(1, kDebugScript, "Groovie::Script: CopyBG3ToScreen: 0x%04X", val);
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: CopyBG3ToScreen: 0x%04X", _currentInstruction-3, val);
}
void Script::o2_setvideoskip() {
_videoSkipAddress = readScript16bits();
- debugC(1, kDebugScript, "SetVideoSkip (0x%04X)", _videoSkipAddress);
+ debugC(1, kDebugScript, "Groovie::Script: SetVideoSkip (0x%04X)", _videoSkipAddress);
}
// This function depends on the actual game played. So it is different for
@@ -1884,44 +1958,49 @@ void Script::o2_stub42() {
}
switch (arg) {
case 0:
- debugC(1, kDebugScript, "Op42 (0x%02X): TLC Regions", arg);
+ debugC(1, kDebugScript, "Groovie::Script: Op42 (0x%02X): TLC Regions", arg);
_tlcGame->opRegions();
break;
case 1:
- debugC(1, kDebugScript, "Op42 (0x%02X): TLC Exit Polls", arg);
+ debugC(1, kDebugScript, "Groovie::Script: Op42 (0x%02X): TLC Exit Polls", arg);
_tlcGame->opExitPoll();
break;
case 2:
_tlcGame->opFlags();
- debugC(1, kDebugScript, "Op42 (0x%02X): TLC TATFlags", arg);
+ debugC(1, kDebugScript, "Groovie::Script: Op42 (0x%02X): TLC TATFlags", arg);
break;
case 3:
- debugC(1, kDebugScript, "Op42 (0x%02X): TLC TATs (TODO)", arg);
+ debugC(1, kDebugScript, "Groovie::Script: Op42 (0x%02X): TLC TATs (TODO)", arg);
_tlcGame->opTat();
break;
default:
- debugC(1, kDebugScript, "Op42 (0x%02X): TLC Invalid -> NOP", arg);
+ debugC(1, kDebugScript, "Groovie::Script: Op42 (0x%02X): TLC Invalid -> NOP", arg);
}
break;
default:
- debugC(1, kDebugScript, "STUB42 (0x%02X)", arg);
- warning("OpCode 0x42 for current game not implemented yet.");
+ debugC(1, kDebugScript, "Groovie::Script: STUB42 (0x%02X)", arg);
+ warning("Groovie::Script: OpCode 0x42 for current game not implemented yet.");
}
}
void Script::o2_stub52() {
uint8 arg = readScript8bits();
- debugC(1, kDebugScript, "STUB52 (0x%02X)", arg);
+ debugC(1, kDebugScript, "Groovie::Script: STUB52 (0x%02X)", arg);
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: STUB52 (0x%02X)", _currentInstruction-2, arg);
+ // return;
+
+ _vm->_graphicsMan->_background.copyFrom(_vm->_graphicsMan->_foreground);
+ _vm->_graphicsMan->updateScreen(&_vm->_graphicsMan->_background);
}
void Script::o2_setscriptend() {
uint16 arg = readScript16bits();
- debugC(1, kDebugScript, "SetScriptEnd (0x%04X)", arg);
+ debugC(1, kDebugScript, "Groovie::Script: SetScriptEnd (0x%04X)", arg);
}
Script::OpcodeFunc Script::_opcodesT7G[NUM_OPCODES] = {
@@ -2070,7 +2149,7 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {
&Script::o_loadgame,
&Script::o_savegame,
&Script::o_hotspotbottom_4, // 0x30
- &Script::o_midivolume,
+ &Script::o2_midicontrol,
&Script::o_jne,
&Script::o_loadstringvar,
&Script::o_chargreatjmp, // 0x34
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index a4b2e4a6e8..dac0b4434e 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -146,8 +146,9 @@ private:
uint32 readScript32bits();
uint16 readScript8or16bits();
uint8 readScriptChar(bool allow7C, bool limitVal, bool limitVar);
+ void readScriptString(Common::String &str);
uint8 readScriptVar();
- uint32 getVideoRefString();
+ uint32 getVideoRefString(Common::String &resName);
bool hotspot(Common::Rect rect, uint16 addr, uint8 cursor);
@@ -243,6 +244,7 @@ private:
void o2_printstring();
void o2_playsong();
+ void o2_midicontrol();
void o2_setbackgroundsong();
void o2_videofromref();
void o2_vdxtransition();
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
index 537f573914..f01cf5b96b 100644
--- a/engines/groovie/tlcgame.cpp
+++ b/engines/groovie/tlcgame.cpp
@@ -34,7 +34,7 @@
namespace Groovie {
// This a list of files for background music. These list is hard-coded in the TLC player.
-const Common::String kTlcMidiFiles[] = {"ep01epm.mpg", "ep01tatm.mpg", "amb_hs.mpg", "amb_mr.mpg", "amb_kr.mpg", "amb_mo.mpg", "music_rc.mpg", "amb_ds.mpg", "amb_ds3.mpg", "amb_jr.mpg", "amb_mr4.mpg", "amb_jr4.mpg", "amb_jr2.mpg", "amb_kr2.mpg", "amb_mr2.mpg", "amb_br.mpg", "amb_ds2.mpg", "amb_jr3.mpg", "amb_ds4.mpg", "amb_kr3.mpg", "amb_to1.mpg", "amb_to2.mpg", "ep02epm.mpg", "ep02tatm.mpg", "ep03epm.mpg", "ep03tatm.mpg", "ep04epm.mpg", "ep04tatm.mpg", "ep05epm.mpg", "ep05tatm.mpg", "ep06epm.mpg", "ep06tatm.mpg", "ep07epm.mpg", "ep07tatm.mpg", "ep08epm.mpg", "ep08tatm.mpg", "ep09epm.mpg", "ep09tatm.mpg", "ep10epm.mpg", "ep10tatm.mpg", "ep11epm.mpg", "ep11tatm.mpg", "ep12epm.mpg", "ep12tatm.mpg", "ep13epm.mpg", "ep13tatm.mpg", "ep14epm.mpg", "ep14tatm.mpg", "ep15epm.mpg", "ep15tatm.mpg" };
+const Common::String kTlcMusicFiles[] = {"ep01epm.mpg", "ep01tatm.mpg", "amb_hs.mpg", "amb_mr.mpg", "amb_kr.mpg", "amb_mo.mpg", "music_rc.mpg", "amb_ds.mpg", "amb_ds3.mpg", "amb_jr.mpg", "amb_mr4.mpg", "amb_jr4.mpg", "amb_jr2.mpg", "amb_kr2.mpg", "amb_mr2.mpg", "amb_br.mpg", "amb_ds2.mpg", "amb_jr3.mpg", "amb_ds4.mpg", "amb_kr3.mpg", "amb_to1.mpg", "amb_to2.mpg", "ep02epm.mpg", "ep02tatm.mpg", "ep03epm.mpg", "ep03tatm.mpg", "ep04epm.mpg", "ep04tatm.mpg", "ep05epm.mpg", "ep05tatm.mpg", "ep06epm.mpg", "ep06tatm.mpg", "ep07epm.mpg", "ep07tatm.mpg", "ep08epm.mpg", "ep08tatm.mpg", "ep09epm.mpg", "ep09tatm.mpg", "ep10epm.mpg", "ep10tatm.mpg", "ep11epm.mpg", "ep11tatm.mpg", "ep12epm.mpg", "ep12tatm.mpg", "ep13epm.mpg", "ep13tatm.mpg", "ep14epm.mpg", "ep14tatm.mpg", "ep15epm.mpg", "ep15tatm.mpg" };
const uint8 kTlcEpQuestToPlay[] = { 0x0E, 0x0F, 0x0B, 0x10, 0x11, 0x12, 0x0C, 0x0C, 0x09, 0x06, 0x0F, 0x0C, 0x0B, 0x0D, 0x0D };
@@ -78,6 +78,10 @@ uint16 inline TlcGame::getScriptVar16(uint16 var) {
return value;
}
+// Gets the filename of the background music file.
+Common::String TlcGame::getTlcMusicFilename(int musicId) {
+ return kTlcMusicFiles[musicId];
+}
void TlcGame::opRegions() {
if (_scriptVariables[0x1A] == 1) {
diff --git a/engines/groovie/tlcgame.h b/engines/groovie/tlcgame.h
index 3648c3fbcd..3fc1f56191 100644
--- a/engines/groovie/tlcgame.h
+++ b/engines/groovie/tlcgame.h
@@ -1,94 +1,96 @@
-/* ScummVM - Graphic Adventure Engine
-*
-* ScummVM is the legal property of its developers, whose names
-* are too numerous to list here. Please refer to the COPYRIGHT
-* file distributed with this source distribution.
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License
-* as published by the Free Software Foundation; either version 2
-* of the License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*
-*/
-
-#ifndef GROOVIE_TLCGAME_H
-#define GROOVIE_TLCGAME_H
-
-#include "common/textconsole.h"
-#include "common/random.h"
-
-#define GROOVIE_TLC_MAX_EPSIODES (15)
-#define GROOVIE_TLC_MAX_QUEST_EP (50)
-
-namespace Groovie {
-
-class GroovieEngine;
-
-// The regions.rle contains 898 entries. Round about 18 kByte in memory.
-struct TlcRegionsHeader {
- char name[12];
- int numAnswers;
- uint32 offset;
-};
-
-struct TlcRegion {
- uint16 left;
- uint16 top;
- uint16 right;
- uint16 bottom;
-};
-
-struct TlcEpQuestionData {
- bool questionUsed;
- uint32 questionScore;
-};
-
-struct TlcTatHeader {
- uint32 questionsNum;
- uint32 questionsOffset;
- uint8 binDividends[16];
-};
-
-struct TlcTatAnswer {
- uint8 binScore[8];
-};
-
-struct TlcTatQuestions {
- char name[6];
- int answerCount;
- TlcTatAnswer answerData[8];
-};
-
-class TlcGame
-{
-public:
- TlcGame();
- ~TlcGame();
-
- /**
- * Sets a pointer to the script variables. This makes it easier if we want
- * to debug write accesses to the script variables
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef GROOVIE_TLCGAME_H
+#define GROOVIE_TLCGAME_H
+
+#include "common/textconsole.h"
+#include "common/random.h"
+
+#define GROOVIE_TLC_MAX_EPSIODES (15)
+#define GROOVIE_TLC_MAX_QUEST_EP (50)
+
+namespace Groovie {
+
+class GroovieEngine;
+
+// The regions.rle contains 898 entries. Round about 18 kByte in memory.
+struct TlcRegionsHeader {
+ char name[12];
+ int numAnswers;
+ uint32 offset;
+};
+
+struct TlcRegion {
+ uint16 left;
+ uint16 top;
+ uint16 right;
+ uint16 bottom;
+};
+
+struct TlcEpQuestionData {
+ bool questionUsed;
+ uint32 questionScore;
+};
+
+struct TlcTatHeader {
+ uint32 questionsNum;
+ uint32 questionsOffset;
+ uint8 binDividends[16];
+};
+
+struct TlcTatAnswer {
+ uint8 binScore[8];
+};
+
+struct TlcTatQuestions {
+ char name[6];
+ int answerCount;
+ TlcTatAnswer answerData[8];
+};
+
+class TlcGame
+{
+public:
+ TlcGame();
+ ~TlcGame();
+
+ static Common::String getTlcMusicFilename(int musicId);
+
+ /**
+ * Sets a pointer to the script variables. This makes it easier if we want
+ * to debug write accesses to the script variables
* @param scriptVariables The current variables from the script.
- */
- void setVariables(byte *scriptVariables);
-
+ */
+ void setVariables(byte *scriptVariables);
+
/**
* Handle region commands. A region describes the coordinates of
* a rectangle as clickable area in the question dialogs. These regions
* are provided by a the extra file.
* screen coordinates.
- */
- void opRegions();
-
+ */
+ void opRegions();
+
/**
* Get the coordiantes of the region for the next answer. There are
* up to 8 answers possible for each question. In the script the
@@ -99,95 +101,95 @@ public:
* @param bottom Bottom value of the rectangle
* @return 0 if anwer was found. -1 in case no more answer
* available for this question
- */
- int getRegionNext(uint16 &left, uint16 &top, uint16 &right, uint16 &bottom);
-
+ */
+ int getRegionNext(uint16 &left, uint16 &top, uint16 &right, uint16 &bottom);
+
/**
* Rewinds the internal answer counter for the function
* getRegionNext()
- */
- void getRegionRewind();
-
-
- /**
- * Handles some flags which are used during a TAT. The game seems to
- * use this flags to skip some questions during a TAT.
- * OpCode_0x42(2)
- */
- void opFlags();
-
-
- /**
- * Handles all Exit Poll commands. The exit poll (EP) questions are
- * described in detail in the file EPAIDB.RLE.
- * OpCode_0x42(1)
- */
- void opExitPoll();
-
- /**
- * Handles all TAT commands. The TAT questions are described in detail
- * in the file TATAIDB.RLE
- */
- void opTat();
-
-private:
- Common::RandomSource _random;
-
- void inline setScriptVar(uint16 var, byte value);
- void inline setScriptVar16(uint16 var, uint16 value);
- uint16 inline getScriptVar16(uint16 var);
- byte *_scriptVariables;
-
+ */
+ void getRegionRewind();
+
+
+ /**
+ * Handles some flags which are used during a TAT. The game seems to
+ * use this flags to skip some questions during a TAT.
+ * OpCode_0x42(2)
+ */
+ void opFlags();
+
+
+ /**
+ * Handles all Exit Poll commands. The exit poll (EP) questions are
+ * described in detail in the file EPAIDB.RLE.
+ * OpCode_0x42(1)
+ */
+ void opExitPoll();
+
+ /**
+ * Handles all TAT commands. The TAT questions are described in detail
+ * in the file TATAIDB.RLE
+ */
+ void opTat();
+
+private:
+ Common::RandomSource _random;
+
+ void inline setScriptVar(uint16 var, byte value);
+ void inline setScriptVar16(uint16 var, uint16 value);
+ uint16 inline getScriptVar16(uint16 var);
+ byte *_scriptVariables;
+
/**
* Loads the description part of the regions.rle file into memory
* This makes it faster to search for the correct quesion.
- */
- void regionsInit();
- void regionsLoad();
-
- // Variables for region handling
- int _numRegionHeaders;
- int _curAnswerIndex;
- int _curQuestNumAnswers;
- TlcRegion _curQuestRegions[8];
- TlcRegionsHeader *_regionHeader;
-
- /**
- * Functions for Exit Poll Commands
- */
- void epInit();
- void epSelectNextQuestion();
- void epResultQuestion();
- void epResultEpisode();
-
- // Variables for Exit Poll handling
- int16 _epScoreBin[6];
- int _epEpisodeIdx; // 15 Episodes: 0..14
- int _epQuestionIdx; // 1..X (questions in current episode. counted up for every question)
- int _epQuestionNumOfPool; // 1..X (question number in the data base. The questions are played in random order)
- int _epQuestionsInEpisode;
- TlcEpQuestionData *_epQuestionsData;
-
- // Variables for flag handling
- byte _tatFlags[0x0E][0x09];
-
- /**
- * Functions for TAT Commands
- */
- void tatInitRegs();
- void tatLoadDB();
- void tatResultQuest();
- void tatResultEpisode();
- void tatGetProfile();
-
- // Variables for TAT handling
- int _tatCount;
- int _tatQuestCount;
- TlcTatHeader *_tatHeaders;
- TlcTatQuestions *_tatQuestions;
- uint8 _tatCoeffs[15][16];
-};
-
-} // End of Groovie namespace
-
-#endif // GROOVIE_TLCGAME_H
+ */
+ void regionsInit();
+ void regionsLoad();
+
+ // Variables for region handling
+ int _numRegionHeaders;
+ int _curAnswerIndex;
+ int _curQuestNumAnswers;
+ TlcRegion _curQuestRegions[8];
+ TlcRegionsHeader *_regionHeader;
+
+ /**
+ * Functions for Exit Poll Commands
+ */
+ void epInit();
+ void epSelectNextQuestion();
+ void epResultQuestion();
+ void epResultEpisode();
+
+ // Variables for Exit Poll handling
+ int16 _epScoreBin[6];
+ int _epEpisodeIdx; // 15 Episodes: 0..14
+ int _epQuestionIdx; // 1..X (questions in current episode. counted up for every question)
+ int _epQuestionNumOfPool; // 1..X (question number in the data base. The questions are played in random order)
+ int _epQuestionsInEpisode;
+ TlcEpQuestionData *_epQuestionsData;
+
+ // Variables for flag handling
+ byte _tatFlags[0x0E][0x09];
+
+ /**
+ * Functions for TAT Commands
+ */
+ void tatInitRegs();
+ void tatLoadDB();
+ void tatResultQuest();
+ void tatResultEpisode();
+ void tatGetProfile();
+
+ // Variables for TAT handling
+ int _tatCount;
+ int _tatQuestCount;
+ TlcTatHeader *_tatHeaders;
+ TlcTatQuestions *_tatQuestions;
+ uint8 _tatCoeffs[15][16];
+};
+
+} // End of Groovie namespace
+
+#endif // GROOVIE_TLCGAME_H
Commit: d3493f2352dcbd89a8385f56b5f4fe42c321ecd3
https://github.com/scummvm/scummvm/commit/d3493f2352dcbd89a8385f56b5f4fe42c321ecd3
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Bugfixes ROQ Player / Stubs for 11H Staufs moves
Changed paths:
A engines/groovie/t11hgame.cpp
A engines/groovie/t11hgame.h
engines/groovie/module.mk
engines/groovie/roq.cpp
engines/groovie/script.cpp
engines/groovie/script.h
diff --git a/engines/groovie/module.mk b/engines/groovie/module.mk
index dfe764a255..8ad3be1085 100644
--- a/engines/groovie/module.mk
+++ b/engines/groovie/module.mk
@@ -20,6 +20,7 @@ ifdef ENABLE_GROOVIE2
MODULE_OBJS += \
roq.o \
tlcgame.o
+ t11hgame.o
endif
# This module can be built as a plugin
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 5e3c93bd9a..6c1198ae62 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -249,13 +249,13 @@ void ROQPlayer::buildShowBuf() {
byte *out = (byte *)destBuf->getBasePtr(startX, line);
for (int x = startX; x < stopX; x++) {
- if (_alpha && destBuf != _overBuf) {
+ if (_alpha) {
copyPixelWithA(out, in);
} else {
- copyPixel(out, in);
+ copyPixelWithA(out, in);
}
- if (_alpha && in[kAIndex] && destBuf != _overBuf) {
+ if (_alpha && in[kAIndex] != 0 && destBuf != _overBuf) {
_restoreArea->top = MIN(line, (int)_restoreArea->top);
_restoreArea->left = MIN(x, (int)_restoreArea->left);
_restoreArea->bottom = MAX(line + 1, (int)_restoreArea->bottom);
@@ -317,6 +317,7 @@ bool ROQPlayer::playFrameInternal() {
}
if (_file->eos()) {
+ debugC(1, kDebugVideo, "Groovie::ROQ: Clear overlay buffer");
_overBuf->fillRect(Common::Rect(0, 0, _overBuf->w, _overBuf->h), _overBuf->format.ARGBToColor(0, 0, 0, 0));
}
@@ -463,7 +464,7 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
_vm->_graphicsMan->switchToFullScreen(false);
// Clear the buffers with black
- if (!_alpha) {
+ if (!_alpha && 0) {
_currBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
_prevBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
}
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index e81f12b74f..7cadd69f0c 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -31,6 +31,7 @@
#include "groovie/resource.h"
#include "groovie/saveload.h"
#include "groovie/tlcgame.h"
+#include "groovie/t11hgame.h"
#include "common/archive.h"
#include "common/config-manager.h"
@@ -69,7 +70,7 @@ const byte t7gMidiInitScript[] = {
Script::Script(GroovieEngine *vm, EngineVersion version) :
_code(NULL), _savedCode(NULL), _stacktop(0), _debugger(NULL), _vm(vm),
_videoFile(NULL), _videoRef(0), _staufsMove(NULL), _lastCursor(0xff),
- _version(version), _random("GroovieScripts"), _tlcGame(0) {
+ _version(version), _random("GroovieScripts"), _tlcGame(0), _t11hGame(0) {
// Initialize the opcode set depending on the engine version
if (version == kGroovieT7G) {
@@ -119,6 +120,7 @@ Script::~Script() {
delete _staufsMove;
delete _tlcGame;
+ delete _t11hGame;
}
void Script::setVariable(uint16 variablenum, byte value) {
@@ -1117,7 +1119,7 @@ void Script::o_strcmpnejmp_var() { // 0x21
void Script::o_copybgtofg() { // 0x22
debugC(1, kDebugScript, "Groovie::Script: COPY_BG_TO_FG");
debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_BG_TO_FG", _currentInstruction-1);
- memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * _vm->_graphicsMan->_foreground.h);
+ memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * _vm->_graphicsMan->_foreground.h * _vm->_graphicsMan->_foreground.format.bytesPerPixel);
}
void Script::o_strcmpeqjmp() { // 0x23
@@ -1641,6 +1643,7 @@ void Script::o_setvideoorigin() {
_bitflags |= 1 << 7;
debugC(1, kDebugScript, "Groovie::Script: SetVideoOrigin(0x%04X,0x%04X) (%d, %d)", origX, origY, origX, origY);
+ debugC(1, kDebugVideo, "Groovie::Script: SetVideoOrigin(0x % 04X, 0x % 04X) (%d, %d)", origX, origY, origX, origY);
_vm->_videoPlayer->setOrigin(origX, origY);
}
@@ -1947,7 +1950,7 @@ void Script::o2_setvideoskip() {
// This function depends on the actual game played. So it is different for
// T7G, 11H, TLC, ...
-void Script::o2_stub42() {
+void Script::o2_gamespecial() {
uint8 arg = readScript8bits();
switch (_version) {
@@ -1968,8 +1971,8 @@ void Script::o2_stub42() {
break;
case 2:
- _tlcGame->opFlags();
debugC(1, kDebugScript, "Groovie::Script: Op42 (0x%02X): TLC TATFlags", arg);
+ _tlcGame->opFlags();
break;
case 3:
@@ -1982,9 +1985,41 @@ void Script::o2_stub42() {
}
break;
+ case kGroovieT11H:
+ if (_t11hGame == NULL) {
+ _t11hGame = new T11hGame();
+ _t11hGame->setVariables(_variables);
+ }
+ switch (arg) {
+ case 1:
+ debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Connect four in the dining room. (tb.grv) TODO", arg);
+ break;
+
+ case 2:
+ debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Beehive Puzzle in the top room (hs.grv) TODO", arg);
+ break;
+
+ case 3:
+ debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Make last move on modern art picture in the gallery (bs.grv) TODO", arg);
+ _t11hGame->opGallery();
+ break;
+
+ case 4:
+ debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Triangle in the Chapel (tx.grv)", arg);
+ break;
+
+ case 5:
+ debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Mouse Trap in the lab (al.grv)", arg);
+ break;
+
+ default:
+ debugC(1, kDebugScript, "Groovie::Script: Op42 (0x%02X): T11H Invalid -> NOP", arg);
+ }
+ break;
+
default:
- debugC(1, kDebugScript, "Groovie::Script: STUB42 (0x%02X)", arg);
- warning("Groovie::Script: OpCode 0x42 for current game not implemented yet.");
+ debugC(1, kDebugScript, "Groovie::Script: GameSpecial (0x%02X)", arg);
+ warning("Groovie::Script: OpCode 0x42 for (GameSpecial) current game not implemented yet.");
}
}
@@ -2166,7 +2201,7 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {
&Script::o_loadscript,
&Script::o_setvideoorigin, // 0x40
&Script::o_sub,
- &Script::o2_stub42,
+ &Script::o2_gamespecial,
&Script::o_returnscript,
&Script::o_sethotspotright, // 0x44
&Script::o_sethotspotleft,
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index dac0b4434e..c3367e0da6 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -50,6 +50,7 @@ class CellGame;
class Debugger;
class GroovieEngine;
class TlcGame;
+class T11hGame;
class Script {
friend class Debugger;
@@ -138,6 +139,7 @@ private:
// Special classes depending on played game
CellGame *_staufsMove;
TlcGame *_tlcGame;
+ T11hGame *_t11hGame;
// Helper functions
uint8 getCodeByte(uint16 address);
@@ -251,7 +253,7 @@ private:
void o2_setvideoskip();
void o2_copyscreentobg();
void o2_copybgtoscreen();
- void o2_stub42();
+ void o2_gamespecial();
void o2_stub52();
void o2_setscriptend();
};
diff --git a/engines/groovie/t11hgame.cpp b/engines/groovie/t11hgame.cpp
new file mode 100644
index 0000000000..297ad0ab98
--- /dev/null
+++ b/engines/groovie/t11hgame.cpp
@@ -0,0 +1,121 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "groovie/t11hgame.h"
+#include "groovie/groovie.h"
+
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/macresman.h"
+#include "common/translation.h"
+
+namespace Groovie {
+
+ T11hGame::T11hGame() :
+ _random("GroovieT11hGame"), _scriptVariables(NULL) {
+ }
+
+
+ T11hGame::~T11hGame() {
+ }
+
+
+ void T11hGame::setVariables(byte *scriptVariables) {
+ _scriptVariables = scriptVariables;
+ }
+
+
+ /*
+ * Puzzle in the Gallery.
+ * The aim is to select the last part of the image. When selecting a part all surrounding parts are also selected
+ * +--------------------+--------------------------------+--------+
+ * | 1/1A | 2/1B | |
+ * | +--------------+--+--------------------------+-----+ |
+ * | | | | |
+ * +--+ 4/1D | 5/1E | 3/1C |
+ * | | | |
+ * +-----+--------+--+--------+-----------------+--+--------+ |
+ * | | | | | | |
+ * | | | | | | |
+ * | | | 8/21 | | | |
+ * | | | | +-----------+ | |
+ * | | | | | | | |
+ * | | +-----------+ | 10/23 | 9/22 | |
+ * | | | | | |
+ * | | 7/20 +-----+-----+ +-----+
+ * | | | | | | |
+ * | +--------------------------+ | | | |
+ * | 6/1F | | | |
+ * +-----------+-----------+-----+--+ | 11 | | 12 |
+ * | 13/26 | | | | | / | | / |
+ * | +-----+-----+ | | | | 24 +-----------+ 25 |
+ * | | | | | | | | | |
+ * +-----+ 17/2A | | |16| | | | |
+ * | | | | |/ | | | | |
+ * | +-----+-----+ | |29| | | +-----+
+ * | | | | | | | | |
+ * | | | | | +-----+ 18/2B | |
+ * | 19/2C | 14/27 | | | | | |
+ * | | | | +-----------+ | |
+ * | | | | | | | |
+ * | | | +--+ 15/28 | | |
+ * | | | | | |
+ * | +--------+--+--------------------+-----------+ |
+ * | | 20/2D | 21/2E |
+ * +-----------+--------+-----------------------------------------+
+ */
+ void T11hGame::opGallery() {
+ int selectedPart;
+
+ do {
+ selectedPart = _random.getRandomNumber(20) + 1;
+ } while (_scriptVariables[0x19 + selectedPart] != 1);
+
+ setScriptVar(0x2F, selectedPart / 10);
+ setScriptVar(0x30, selectedPart % 10);
+ }
+
+ // This function is mainly for debugging purpose
+ void inline T11hGame::setScriptVar(uint16 var, byte value) {
+ _scriptVariables[var] = value;
+ debugC(5, kDebugTlcGame, "script variable[0x%03X] = %d (0x%04X)", var, value, value);
+ }
+
+ void inline T11hGame::setScriptVar16(uint16 var, uint16 value) {
+ _scriptVariables[var] = value & 0xFF;
+ _scriptVariables[var + 1] = (value >> 8) & 0xFF;
+ debugC(5, kDebugTlcGame, "script variable[0x%03X, 0x%03X] = %d (0x%02X, 0x%02X)", var, var + 1, value, _scriptVariables[var], _scriptVariables[var + 1]);
+ }
+
+ uint16 inline T11hGame::getScriptVar16(uint16 var) {
+ uint16 value;
+
+ value = _scriptVariables[var];
+ value += _scriptVariables[var + 1] << 8;
+
+ return value;
+ }
+
+} // End of Namespace Groovie
diff --git a/engines/groovie/t11hgame.h b/engines/groovie/t11hgame.h
new file mode 100644
index 0000000000..0a56a513db
--- /dev/null
+++ b/engines/groovie/t11hgame.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef GROOVIE_T11HGAME_H
+#define GROOVIE_T11HGAME_H
+
+#include "common/textconsole.h"
+#include "common/random.h"
+
+namespace Groovie {
+
+ class GroovieEngine;
+
+ class T11hGame
+ {
+ public:
+ T11hGame();
+ ~T11hGame();
+
+ /**
+ * Sets a pointer to the script variables. This makes it easier if we want
+ * to debug write accesses to the script variables
+ * @param scriptVariables The current variables from the script.
+ */
+ void setVariables(byte *scriptVariables);
+
+ void opGallery();
+
+ private:
+ Common::RandomSource _random;
+
+ void inline setScriptVar(uint16 var, byte value);
+ void inline setScriptVar16(uint16 var, uint16 value);
+ uint16 inline getScriptVar16(uint16 var);
+ byte *_scriptVariables;
+
+ };
+
+} // End of Groovie namespace
+
+#endif // GROOVIE_T11HGAME_H
Commit: 9c68ffb79f797ba55fb7bd54fc1bf2d1795385e5
https://github.com/scummvm/scummvm/commit/9c68ffb79f797ba55fb7bd54fc1bf2d1795385e5
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Overlay corrections, some other bugfixes
Changed paths:
engines/groovie/graphics.cpp
engines/groovie/graphics.h
engines/groovie/player.cpp
engines/groovie/resource.cpp
engines/groovie/roq.cpp
engines/groovie/roq.h
engines/groovie/script.cpp
engines/groovie/script.h
engines/groovie/t11hgame.cpp
engines/groovie/tlcgame.cpp
diff --git a/engines/groovie/graphics.cpp b/engines/groovie/graphics.cpp
index 45956416cd..8a377371ef 100644
--- a/engines/groovie/graphics.cpp
+++ b/engines/groovie/graphics.cpp
@@ -35,12 +35,14 @@ GraphicsMan::GraphicsMan(GroovieEngine *vm) :
// Create the game surfaces
_foreground.create(640, 320, _vm->_pixelFormat);
_background.create(640, 320, _vm->_pixelFormat);
+ _savedground.create(640, 480, _vm->_pixelFormat);
}
GraphicsMan::~GraphicsMan() {
// Free the game surfaces
_foreground.free();
_background.free();
+ _savedground.free();
}
void GraphicsMan::update() {
@@ -82,7 +84,7 @@ void GraphicsMan::switchToFullScreen(bool fullScreen) {
_foreground.create(640, 480, _vm->_pixelFormat);
_background.create(640, 480, _vm->_pixelFormat);
} else {
- _vm->_system->fillScreen(0);
+ // _vm->_system->fillScreen(0);
_foreground.create(640, 320, _vm->_pixelFormat);
_background.create(640, 320, _vm->_pixelFormat);
}
@@ -117,6 +119,17 @@ void GraphicsMan::updateScreen(Graphics::Surface *source) {
change();
}
+void GraphicsMan::saveScreen() {
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ _vm->_graphicsMan->_savedground.copyFrom(screen->getSubArea(Common::Rect(0, 0, 640, 480)));
+ _vm->_system->unlockScreen();
+}
+
+void GraphicsMan::restoreScreen() {
+ _vm->_system->copyRectToScreen(_savedground.getPixels(), _savedground.pitch, 0, 0, 640, 480);
+ change();
+}
+
bool GraphicsMan::isFading() {
return _fading;
}
diff --git a/engines/groovie/graphics.h b/engines/groovie/graphics.h
index 69934f9d68..ab1f14b8e4 100644
--- a/engines/groovie/graphics.h
+++ b/engines/groovie/graphics.h
@@ -41,8 +41,11 @@ public:
void switchToFullScreen(bool fullScreen);
bool isFullScreen() { return (_foreground.h == 480); }
void updateScreen(Graphics::Surface *source);
+ void saveScreen();
+ void restoreScreen();
Graphics::Surface _foreground; // The main surface that most things are drawn to
Graphics::Surface _background; // Used occasionally, mostly (only?) in puzzles
+ Graphics::Surface _savedground; // Buffer to save and restore the current screen. Used when opening the gamebook in 11H
// Palette fading
bool isFading();
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index bbc8918902..f64666d314 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -25,6 +25,7 @@
#include "groovie/player.h"
#include "groovie/groovie.h"
+#include "audio/mixer.h"
namespace Groovie {
@@ -37,6 +38,9 @@ bool VideoPlayer::load(Common::SeekableReadStream *file, uint16 flags) {
_file = file;
_flags = flags;
_overrideSpeed = false;
+ if (_audioStream) {
+ g_system->getMixer()->stopAll();
+ }
_audioStream = NULL;
_fps = loadInternal();
diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp
index 8432ba143b..b92a0b5f57 100644
--- a/engines/groovie/resource.cpp
+++ b/engines/groovie/resource.cpp
@@ -227,6 +227,8 @@ uint32 ResMan_v2::getRef(Common::String name, Common::String scriptname) {
return false;
}
+ // resources are always in lowercase
+ name.toLowercase();
uint32 resNum;
bool found = false;
for (resNum = 0; !found && !rlFile.err() && !rlFile.eos(); resNum++) {
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 6c1198ae62..c2f3fc9210 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -61,6 +61,16 @@ static const int kRIndex = 0;
namespace Groovie {
// Overwrites one pixel of destination regardless of the alpha value
+static inline void copyPixelIfAlpha(byte *dst, byte *src) {
+ if (src[kAIndex] > 0) {
+ dst[kAIndex] = src[kAIndex];
+ dst[kRIndex] = src[kRIndex];
+ dst[kGIndex] = src[kGIndex];
+ dst[kBIndex] = src[kBIndex];
+ }
+}
+
+ // Overwrites one pixel of destination regardless of the alpha value
static inline void copyPixel(byte *dst, byte *src) {
dst[kAIndex] = src[kAIndex];
dst[kRIndex] = src[kRIndex];
@@ -74,7 +84,7 @@ static inline void copyPixelWithA(byte *dst, byte *src) {
copyPixel(dst, src);
} else {
if (src[kAIndex] > 0) {
- dst[kAIndex] = 255;
+ dst[kAIndex] = MAX(src[kAIndex], dst[kAIndex]);
dst[kRIndex] = ((src[kRIndex] * src[kAIndex]) + dst[kRIndex] * (255 - src[kAIndex])) >> 8;
dst[kGIndex] = ((src[kGIndex] * src[kAIndex]) + dst[kGIndex] * (255 - src[kAIndex])) >> 8;
dst[kBIndex] = ((src[kBIndex] * src[kAIndex]) + dst[kBIndex] * (255 - src[kAIndex])) >> 8;
@@ -86,15 +96,15 @@ static inline void copyPixelWithA(byte *dst, byte *src) {
ROQPlayer::ROQPlayer(GroovieEngine *vm) :
VideoPlayer(vm), _codingTypeCount(0),
- _fg(&_vm->_graphicsMan->_foreground),
- _bg(&_vm->_graphicsMan->_background),
+ _bg(&_vm->_graphicsMan->_foreground),
+ _screen(&_vm->_graphicsMan->_background),
_firstFrame(true),
_origX(0), _origY(0) {
// Create the work surfaces
_currBuf = new Graphics::Surface();
_prevBuf = new Graphics::Surface();
- _overBuf = new Graphics::Surface(); // Overlay buffer. Object move behind this layer
+ _overBuf = new Graphics::Surface(); // Overlay buffer. Objects move behind this layer
_restoreArea = new Common::Rect();
}
@@ -193,15 +203,22 @@ void ROQPlayer::calcStartStop(int &start, int &stop, int origin, int length) {
}
void ROQPlayer::buildShowBuf() {
+ // Calculate screen offset for normal / fullscreen videos and images
+ int screenOffset = 0;
+ if (_screen->h != 480) {
+ screenOffset = 80;
+ }
+
// Restore the background by data from the foreground. Only restore the area which was overwritten during the last frame
// Therefore we have the _restoreArea which reduces the area for restoring. We also use the _prevBuf to only overwrite the
// Pixels which have been written during the last frame. This means _restoreArea is just an optimization.
if (_alpha) {
if (!_restoreArea->isEmpty()) {
int width = _restoreArea->right - _restoreArea->left;
+ Graphics::Surface *screen = _vm->_system->lockScreen();
for (int line = _restoreArea->top; line < _restoreArea->bottom; line++) {
- byte *src = (byte *)_fg->getBasePtr(_restoreArea->left, line);
- byte *dst = (byte *)_bg->getBasePtr(_restoreArea->left, line);
+ byte *dst = (byte *)screen->getBasePtr(_restoreArea->left, line + screenOffset);
+ byte *src = (byte *)_bg->getBasePtr(_restoreArea->left, line);
byte *prv = (byte *)_prevBuf->getBasePtr((_restoreArea->left - _origX) / _scaleX, (line - _origY) / _scaleY);
byte *ovr = (byte *)_overBuf->getBasePtr(_restoreArea->left, line);
for (int i = 0; i < width; i++) {
@@ -209,12 +226,13 @@ void ROQPlayer::buildShowBuf() {
copyPixel(dst, src);
copyPixelWithA(dst, ovr);
}
- src += _fg->format.bytesPerPixel;
- dst += _fg->format.bytesPerPixel;
- prv += _fg->format.bytesPerPixel;
- ovr += _fg->format.bytesPerPixel;
+ src += _bg->format.bytesPerPixel;
+ dst += _bg->format.bytesPerPixel;
+ prv += _bg->format.bytesPerPixel;
+ ovr += _bg->format.bytesPerPixel;
}
}
+ _vm->_system->unlockScreen();
}
// Reset _restoreArea for the next frame
@@ -226,33 +244,40 @@ void ROQPlayer::buildShowBuf() {
// Select the destination buffer according to the given flags
+ int destOffset = 0;
Graphics::Surface *destBuf;
if (_flagOne) {
if (_flagTwo) {
destBuf = _overBuf;
} else {
- destBuf = _fg;
+ destBuf = _bg;
}
} else {
- destBuf = _bg;
+ destBuf = _vm->_system->lockScreen();
+ destOffset = screenOffset;
}
// _origY and _origX may be negative (11th hour uses this in the chapel puzzle against Stauf)
int startX, startY, stopX, stopY;
- calcStartStop(startX, stopX, _origX, _bg->w);
- calcStartStop(startY, stopY, _origY, _bg->h);
+ calcStartStop(startX, stopX, _origX, _screen->w);
+ calcStartStop(startY, stopY, _origY, _screen->h);
for (int line = startY; line < stopY; line++) {
byte *in = (byte *)_currBuf->getBasePtr(MAX(0, -_origX) / _scaleX, (line - _origY) / _scaleY);
byte *inOvr = (byte *)_overBuf->getBasePtr(startX, line);
- byte *out = (byte *)destBuf->getBasePtr(startX, line);
+ byte *out = (byte *)destBuf->getBasePtr(startX, line + destOffset);
for (int x = startX; x < stopX; x++) {
- if (_alpha) {
- copyPixelWithA(out, in);
+ if (destBuf == _overBuf) {
+ copyPixelIfAlpha(out, in);
} else {
- copyPixelWithA(out, in);
+ if (_interlacedVideo && (line % 2) && 0) {
+ byte blackPixel[4] = { 0, 0, 0, 0 };
+ copyPixel(out, blackPixel);
+ } else {
+ copyPixelWithA(out, in);
+ }
}
if (_alpha && in[kAIndex] != 0 && destBuf != _overBuf) {
@@ -265,13 +290,19 @@ void ROQPlayer::buildShowBuf() {
}
// Skip to the next pixel
- out += _bg->format.bytesPerPixel;
- inOvr += _bg->format.bytesPerPixel;
+ out += _screen->format.bytesPerPixel;
+ inOvr += _screen->format.bytesPerPixel;
if (!(x % _scaleX))
- in += _bg->format.bytesPerPixel;
+ in += _screen->format.bytesPerPixel;
}
}
+ if (!_flagOne) {
+ _vm->_system->unlockScreen();
+ _vm->_system->updateScreen();
+ }
+ _dirty = false;
+
// On the first frame, copy from the current buffer to the prev buffer
if (_firstFrame) {
_prevBuf->copyFrom(*_currBuf);
@@ -303,8 +334,8 @@ bool ROQPlayer::playFrameInternal() {
if (_dirty) {
// Update the screen
- void *src = (_alpha && 0) ? _fg->getPixels() : _bg->getPixels();
- _syst->copyRectToScreen(src, _bg->pitch, 0, (_syst->getHeight() - _bg->h) / 2, _bg->w, _bg->h);
+ void *src = (_alpha && 0) ? _bg->getPixels() : _screen->getPixels();
+ _syst->copyRectToScreen(src, _screen->pitch, 0, (_syst->getHeight() - _screen->h) / 2, _screen->w, _screen->h);
_syst->updateScreen();
// For overlay videos, set the background buffer when the video ends
@@ -452,15 +483,17 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
}
// Hack: Detect a video with interlaced black lines, by checking its height compared to width
+ _interlacedVideo = 0;
if (height <= width / 3) {
+ _interlacedVideo = 1;
_offScale = 2;
}
- debugC(2, kDebugVideo, "Groovie::ROQ: width=%d, height=%d, scaleX=%d, scaleY=%d, _offScale=%d, _alpha=%d", width, height, _scaleX, _scaleY, _offScale, _alpha);
+ debugC(2, kDebugVideo, "Groovie::ROQ: width=%d, height=%d, scaleX=%d, scaleY=%d, _offScale=%d, interl.=%d, _alpha=%d", width, height, _scaleX, _scaleY, _interlacedVideo, _offScale, _alpha);
// Switch from/to fullscreen, if needed
- if (_bg->h != 480 && height == 480)
+ if (_screen->h != 480 && height == 480)
_vm->_graphicsMan->switchToFullScreen(true);
- else if (_bg->h == 480 && height != 480)
+ else if (_screen->h == 480 && height != 480)
_vm->_graphicsMan->switchToFullScreen(false);
// Clear the buffers with black
diff --git a/engines/groovie/roq.h b/engines/groovie/roq.h
index bc1e01d721..84c9419163 100644
--- a/engines/groovie/roq.h
+++ b/engines/groovie/roq.h
@@ -67,6 +67,7 @@ private:
// Origin
int16 _origX, _origY;
+ int16 _screenOffset;
void calcStartStop(int &start, int &stop, int origin, int length);
// Block coding type
@@ -85,11 +86,12 @@ private:
bool _flagTwo; // If _flagOne is set. Copy frame to the foreground otherwise to the background
// Buffers
- Graphics::Surface *_fg, *_bg, *_overBuf;
+ Graphics::Surface *_bg, *_screen, *_overBuf;
Graphics::Surface *_currBuf, *_prevBuf;
void buildShowBuf();
byte _scaleX, _scaleY;
byte _offScale;
+ bool _interlacedVideo;
bool _dirty;
byte _alpha;
bool _firstFrame;
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 7cadd69f0c..ce99e5bdd2 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -381,8 +381,10 @@ void Script::readScriptString(Common::String &str) {
case 0x23:
c = readScript8bits();
c = _variables[c - 0x61] + 0x30;
- if (c >= 0x41 && c <= 0x5A) {
- c += 0x20;
+ if (_version == kGroovieT7G) {
+ if (c >= 0x41 && c <= 0x5A) {
+ c += 0x20;
+ }
}
break;
case 0x7C:
@@ -392,8 +394,10 @@ void Script::readScriptString(Common::String &str) {
c = _variables[0x0A * parta + partb + 0x19] + 0x30;
break;
default:
- if (c >= 0x41 && c <= 0x5A) {
- c += 0x20;
+ if (_version == kGroovieT7G) {
+ if (c >= 0x41 && c <= 0x5A) {
+ c += 0x20;
+ }
}
}
// Append the current character at the end of the string
@@ -1117,9 +1121,22 @@ void Script::o_strcmpnejmp_var() { // 0x21
}
void Script::o_copybgtofg() { // 0x22
- debugC(1, kDebugScript, "Groovie::Script: COPY_BG_TO_FG");
- debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_BG_TO_FG", _currentInstruction-1);
- memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * _vm->_graphicsMan->_foreground.h * _vm->_graphicsMan->_foreground.format.bytesPerPixel);
+ if (_version == kGroovieT7G) {
+ debugC(1, kDebugScript, "Groovie::Script: COPY_BG_TO_FG");
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_BG_TO_FG", _currentInstruction - 1);
+ memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * _vm->_graphicsMan->_foreground.h * _vm->_graphicsMan->_foreground.format.bytesPerPixel);
+ } else {
+ debugC(1, kDebugScript, "Groovie::Script: COPY_SCREEN_TO_BG");
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_SCREEN_TO_BG", _currentInstruction - 1);
+
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ if (_vm->_graphicsMan->isFullScreen()) {
+ _vm->_graphicsMan->_foreground.copyFrom(screen->getSubArea(Common::Rect(0, 0, 640, 480)));
+ } else {
+ _vm->_graphicsMan->_foreground.copyFrom(screen->getSubArea(Common::Rect(0, 80, 640, 400)));
+ }
+ _vm->_system->unlockScreen();
+ }
}
void Script::o_strcmpeqjmp() { // 0x23
@@ -1913,31 +1930,33 @@ void Script::o2_vdxtransition() {
}
}
-void Script::o2_copyscreentobg() {
+void Script::o2_savescreen() {
uint16 val = readScript16bits();
// TODO: Parameter
if (val)
warning("Groovie::Script: o2_copyscreentobg: Param is %d", val);
- Graphics::Surface *screen = _vm->_system->lockScreen();
- _vm->_graphicsMan->_background.copyFrom(screen->getSubArea(Common::Rect(0, 80, 640, 320)));
- _vm->_system->unlockScreen();
+ // Graphics::Surface *screen = _vm->_system->lockScreen();
+ // _vm->_graphicsMan->_background.copyFrom(screen->getSubArea(Common::Rect(0, 80, 640, 320)));
+ // _vm->_system->unlockScreen();
+ _vm->_graphicsMan->saveScreen();
debugC(1, kDebugScript, "Groovie::Script: CopyScreenToBG3: 0x%04X", val);
debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: CopyScreenToBG3: 0x%04X", _currentInstruction-3, val);
}
-void Script::o2_copybgtoscreen() {
+void Script::o2_restorescreen() {
uint16 val = readScript16bits();
// TODO: Parameter
if (val)
warning("Groovie::Script: o2_copybgtoscreen: Param is %d", val);
- Graphics::Surface *screen = _vm->_system->lockScreen();
- _vm->_graphicsMan->_background.copyRectToSurface(*screen, 0, 80, Common::Rect(0, 0, 640, 320 - 80));
- _vm->_system->unlockScreen();
+ // Graphics::Surface *screen = _vm->_system->lockScreen();
+ // _vm->_graphicsMan->_background.copyRectToSurface(*screen, 0, 80, Common::Rect(0, 0, 640, 320 - 80));
+ // _vm->_system->unlockScreen();
+ _vm->_graphicsMan->restoreScreen();
debugC(1, kDebugScript, "Groovie::Script: CopyBG3ToScreen: 0x%04X", val);
debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: CopyBG3ToScreen: 0x%04X", _currentInstruction-3, val);
@@ -2214,8 +2233,8 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {
&Script::o_invalid, // 0x4C
&Script::o_invalid,
&Script::o_invalid,
- &Script::o2_copyscreentobg,
- &Script::o2_copybgtoscreen, // 0x50
+ &Script::o2_savescreen,
+ &Script::o2_restorescreen, // 0x50
&Script::o2_setvideoskip,
&Script::o2_stub52,
&Script::o_hotspot_outrect,
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index c3367e0da6..dd5397ae0f 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -251,8 +251,8 @@ private:
void o2_videofromref();
void o2_vdxtransition();
void o2_setvideoskip();
- void o2_copyscreentobg();
- void o2_copybgtoscreen();
+ void o2_savescreen();
+ void o2_restorescreen();
void o2_gamespecial();
void o2_stub52();
void o2_setscriptend();
diff --git a/engines/groovie/t11hgame.cpp b/engines/groovie/t11hgame.cpp
index 297ad0ab98..417e13553e 100644
--- a/engines/groovie/t11hgame.cpp
+++ b/engines/groovie/t11hgame.cpp
@@ -1,55 +1,55 @@
-/* ScummVM - Graphic Adventure Engine
-*
-* ScummVM is the legal property of its developers, whose names
-* are too numerous to list here. Please refer to the COPYRIGHT
-* file distributed with this source distribution.
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License
-* as published by the Free Software Foundation; either version 2
-* of the License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*
-*/
-
-#include "groovie/t11hgame.h"
-#include "groovie/groovie.h"
-
-#include "common/archive.h"
-#include "common/config-manager.h"
-#include "common/debug-channels.h"
-#include "common/events.h"
-#include "common/file.h"
-#include "common/macresman.h"
-#include "common/translation.h"
-
-namespace Groovie {
-
- T11hGame::T11hGame() :
- _random("GroovieT11hGame"), _scriptVariables(NULL) {
- }
-
-
- T11hGame::~T11hGame() {
- }
-
-
- void T11hGame::setVariables(byte *scriptVariables) {
- _scriptVariables = scriptVariables;
- }
-
-
- /*
- * Puzzle in the Gallery.
- * The aim is to select the last part of the image. When selecting a part all surrounding parts are also selected
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "groovie/t11hgame.h"
+#include "groovie/groovie.h"
+
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/macresman.h"
+#include "common/translation.h"
+
+namespace Groovie {
+
+ T11hGame::T11hGame() :
+ _random("GroovieT11hGame"), _scriptVariables(NULL) {
+ }
+
+
+ T11hGame::~T11hGame() {
+ }
+
+
+ void T11hGame::setVariables(byte *scriptVariables) {
+ _scriptVariables = scriptVariables;
+ }
+
+
+ /*
+ * Puzzle in the Gallery.
+ * The aim is to select the last part of the image. When selecting a part all surrounding parts are also selected
* +--------------------+--------------------------------+--------+
* | 1/1A | 2/1B | |
* | +--------------+--+--------------------------+-----+ |
@@ -85,37 +85,37 @@ namespace Groovie {
* | +--------+--+--------------------+-----------+ |
* | | 20/2D | 21/2E |
* +-----------+--------+-----------------------------------------+
- */
- void T11hGame::opGallery() {
- int selectedPart;
-
- do {
- selectedPart = _random.getRandomNumber(20) + 1;
- } while (_scriptVariables[0x19 + selectedPart] != 1);
-
- setScriptVar(0x2F, selectedPart / 10);
- setScriptVar(0x30, selectedPart % 10);
- }
-
- // This function is mainly for debugging purpose
- void inline T11hGame::setScriptVar(uint16 var, byte value) {
- _scriptVariables[var] = value;
- debugC(5, kDebugTlcGame, "script variable[0x%03X] = %d (0x%04X)", var, value, value);
- }
-
- void inline T11hGame::setScriptVar16(uint16 var, uint16 value) {
- _scriptVariables[var] = value & 0xFF;
- _scriptVariables[var + 1] = (value >> 8) & 0xFF;
- debugC(5, kDebugTlcGame, "script variable[0x%03X, 0x%03X] = %d (0x%02X, 0x%02X)", var, var + 1, value, _scriptVariables[var], _scriptVariables[var + 1]);
- }
-
- uint16 inline T11hGame::getScriptVar16(uint16 var) {
- uint16 value;
-
- value = _scriptVariables[var];
- value += _scriptVariables[var + 1] << 8;
-
- return value;
- }
-
-} // End of Namespace Groovie
+ */
+ void T11hGame::opGallery() {
+ int selectedPart;
+
+ do {
+ selectedPart = _random.getRandomNumber(20) + 1;
+ } while (_scriptVariables[0x19 + selectedPart] != 1);
+
+ setScriptVar(0x2F, selectedPart / 10);
+ setScriptVar(0x30, selectedPart % 10);
+ }
+
+ // This function is mainly for debugging purpose
+ void inline T11hGame::setScriptVar(uint16 var, byte value) {
+ _scriptVariables[var] = value;
+ debugC(5, kDebugTlcGame, "script variable[0x%03X] = %d (0x%04X)", var, value, value);
+ }
+
+ void inline T11hGame::setScriptVar16(uint16 var, uint16 value) {
+ _scriptVariables[var] = value & 0xFF;
+ _scriptVariables[var + 1] = (value >> 8) & 0xFF;
+ debugC(5, kDebugTlcGame, "script variable[0x%03X, 0x%03X] = %d (0x%02X, 0x%02X)", var, var + 1, value, _scriptVariables[var], _scriptVariables[var + 1]);
+ }
+
+ uint16 inline T11hGame::getScriptVar16(uint16 var) {
+ uint16 value;
+
+ value = _scriptVariables[var];
+ value += _scriptVariables[var + 1] << 8;
+
+ return value;
+ }
+
+} // End of Namespace Groovie
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
index f01cf5b96b..a25bb41913 100644
--- a/engines/groovie/tlcgame.cpp
+++ b/engines/groovie/tlcgame.cpp
@@ -1192,6 +1192,7 @@ void TlcGame::tatGetProfile() {
getScriptVar16(0x5D + 2 * iBin);
}
+ error("GROOVIE: Function (tatGetProfile) not implemented yet.");
}
Commit: efcc882cc89f4f506c3c518eabfd210b06e373e5
https://github.com/scummvm/scummvm/commit/efcc882cc89f4f506c3c518eabfd210b06e373e5
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Added calc of final profile for TLC
Changed paths:
engines/groovie/tlcgame.cpp
engines/groovie/tlcgame.h
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
index a25bb41913..0823add1f8 100644
--- a/engines/groovie/tlcgame.cpp
+++ b/engines/groovie/tlcgame.cpp
@@ -309,7 +309,7 @@ void TlcGame::epInit() {
}
if (epaidbfile->eos()) {
- error("TLC:EpInit: Error reading scores from 'REGIONS.RLE'");
+ error("TLC:EpInit: Error reading scores from 'EPAIDB.RLE'");
}
// Close file
@@ -605,7 +605,7 @@ void TlcGame::epResultQuestion() {
* Processes the result of the questions for this episode.
* _epScoreBin[ 0]: Ignored. Used if this answer for a question has no influence. Reset with each new Exit Poll.
* _epScoreBin[1..3]: Seems to be used to select alternative video for this episode. Reset with each new Exit Poll.
- * _epScoreBin[4..5]: Seems to be used over the whole game. (Values are kept over the episodes in the script variables.
+ * _epScoreBin[4..5]: Seems to be used over the whole game. (Values are kept over the episodes in the script variables.)
*/
void TlcGame::epResultEpisode() {
@@ -663,6 +663,7 @@ void TlcGame::epResultEpisode() {
setScriptVar(0, 9);
}
+
void TlcGame::opFlags() {
int x;
int y;
@@ -758,6 +759,7 @@ void TlcGame::opTat() {
}
}
+
void TlcGame::tatInitRegs() {
int i;
@@ -770,40 +772,48 @@ void TlcGame::tatInitRegs() {
// memset(_tatUnkData0_14, 0, 15);
}
-void TlcGame::tatLoadDB() {
- Common::SeekableReadStream *tataidbfile = 0;
- int i, d;
- int episode;
- uint32 questOffset;
-
- for (i = 0; i < 0x10; i++) {
- setScriptVar(0x4D + i, 0);
- }
- // Open epaidb.rle
- tataidbfile = SearchMan.createReadStreamForMember("SYSTEM/TATAIDB.RLE");
- if (!tataidbfile) {
- error("TLC:TatLoadDB: Could not open 'SYSTEM/TATAIDB.RLE'");
- }
+void TlcGame::tatLoadDBHeaders() {
+ Common::SeekableReadStream *tataidbfile = 0;
+ int iEpisode, iBin;
// Load tat headers if not already done
if (_tatHeaders == NULL) {
- _tatCount = tataidbfile->readUint32LE();
- _tatHeaders = new TlcTatHeader[_tatCount];
-
- for (i = 0; i < _tatCount; i++) {
- _tatHeaders[i].questionsNum = tataidbfile->readUint32LE();
- _tatHeaders[i].questionsOffset = tataidbfile->readUint32LE();
- for (d = 0; d < 16; d++) {
- _tatHeaders[i].binDividends[d] = tataidbfile->readByte();
+ // Open tataidb.rle
+ tataidbfile = SearchMan.createReadStreamForMember("SYSTEM/TATAIDB.RLE");
+ if (!tataidbfile) {
+ error("TLC:TatLoadDB: Could not open 'SYSTEM/TATAIDB.RLE'");
+ }
+
+ _tatEpisodes = tataidbfile->readUint32LE();
+ _tatHeaders = new TlcTatHeader[_tatEpisodes];
+
+ for (iEpisode = 0; iEpisode < _tatEpisodes; iEpisode++) {
+ _tatHeaders[iEpisode].questionsNum = tataidbfile->readUint32LE();
+ _tatHeaders[iEpisode].questionsOffset = tataidbfile->readUint32LE();
+ for (iBin = 0; iBin < 16; iBin++) {
+ _tatHeaders[iEpisode].binDividends[iBin] = tataidbfile->readByte();
}
}
+ if (tataidbfile->eos()) {
+ error("TLC:TatLoadDB: Error reading headers from 'TATAIDB.RLE'");
+ }
}
+}
- if (tataidbfile->eos()) {
- error("TLC:TatLoadDB: Error reading headers from 'TATAIDB.RLE'");
+
+void TlcGame::tatLoadDB() {
+ Common::SeekableReadStream *tataidbfile = 0;
+ int episode;
+ uint32 questOffset;
+
+ for (int iBin = 0; iBin < 0x10; iBin++) {
+ setScriptVar(0x4D + iBin, 0);
}
+ // Load TAT headers
+ tatLoadDBHeaders();
+
// Load questions for the requested episode
episode = _scriptVariables[0x47] - 0x31; // -'1'
_tatQuestCount = _tatHeaders[episode].questionsNum;
@@ -811,6 +821,12 @@ void TlcGame::tatLoadDB() {
delete[] _tatQuestions;
_tatQuestions = new TlcTatQuestions[_tatQuestCount];
+
+ // Open tataidb.rle and seek correct position
+ tataidbfile = SearchMan.createReadStreamForMember("SYSTEM/TATAIDB.RLE");
+ if (!tataidbfile) {
+ error("TLC:TatLoadDB: Could not open 'SYSTEM/TATAIDB.RLE'");
+ }
tataidbfile->seek(questOffset, SEEK_SET);
for (int iQuest = 0; iQuest < _tatQuestCount; iQuest++) {
@@ -1175,25 +1191,52 @@ void TlcGame::tatResultEpisode() {
void TlcGame::tatGetProfile() {
- uint16 scoreTable[16];
+ uint16 sumBinDivs[16];
+ float binRatios[16];
int iBin, iEpisode;
for (iBin = 0; iBin < 16; iBin++) {
- scoreTable[iBin] = 0;
+ sumBinDivs[iBin] = 0;
}
- for (iEpisode = 0; iEpisode < 15; iEpisode++) {
+ // Load scoretable by summing all dividends for each episode
+ tatLoadDBHeaders();
+ for (iEpisode = 0; iEpisode < _tatEpisodes; iEpisode++) {
for (iBin = 0; iBin < 16; iBin++) {
- scoreTable[iBin] += _tatCoeffs[iEpisode][iBin];
+ sumBinDivs[iBin] += _tatHeaders[iEpisode].binDividends[iBin];
}
}
- for (iBin = 0; iBin <= 16; iBin++) {
- getScriptVar16(0x5D + 2 * iBin);
+ // Calculate ratio of each bin
+ for (iBin = 0; iBin < 16; iBin++) {
+ binRatios[iBin] = (float)getScriptVar16(0x5D + 2 * iBin) / (float)sumBinDivs[iBin];
}
- error("GROOVIE: Function (tatGetProfile) not implemented yet.");
+ // Select higher ratio of each pair (A=iBin and B=iBin+1) and 1 or 2 accoring to threshold
+ for (iBin = 0; iBin < 16; iBin += 2) {
+ if (binRatios[iBin] > binRatios[iBin + 1]) {
+ setScriptVar(0x4d + iBin, 'A' + iBin);
+ if (binRatios[iBin] > 0.5) {
+ setScriptVar(0x4e + iBin, '1');
+ } else {
+ setScriptVar(0x4e + iBin, '2');
+ }
+ } else {
+
+ setScriptVar(0x4d + iBin, 'B' + iBin);
+ if (binRatios[iBin + 1] > 0.5) {
+ setScriptVar(0x4e + iBin, '1');
+ } else {
+ setScriptVar(0x4e + iBin, '2');
+ }
+ }
+ }
+
+ // Adapt former set script variables (all -0x30)
+ for (iBin = 0; iBin < 16; iBin++) {
+ setScriptVar(0x4d + iBin, _scriptVariables[0x4d + iBin] - '0');
+ }
}
} // End of Namespace Groovie
diff --git a/engines/groovie/tlcgame.h b/engines/groovie/tlcgame.h
index 3fc1f56191..e937d12a7f 100644
--- a/engines/groovie/tlcgame.h
+++ b/engines/groovie/tlcgame.h
@@ -178,16 +178,17 @@ private:
*/
void tatInitRegs();
void tatLoadDB();
+ void tatLoadDBHeaders();
void tatResultQuest();
void tatResultEpisode();
void tatGetProfile();
// Variables for TAT handling
- int _tatCount;
+ int _tatEpisodes;
int _tatQuestCount;
TlcTatHeader *_tatHeaders;
TlcTatQuestions *_tatQuestions;
- uint8 _tatCoeffs[15][16];
+ // uint8 _tatCoeffs[15][16];
};
} // End of Groovie namespace
Commit: 3d8cb28b8cec0f26f154736983276acb3161ddf3
https://github.com/scummvm/scummvm/commit/3d8cb28b8cec0f26f154736983276acb3161ddf3
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Bugfix. Videos with ID0 were skipped
Changed paths:
engines/groovie/script.cpp
engines/groovie/script.h
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index ce99e5bdd2..f285e86bbc 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -69,7 +69,7 @@ const byte t7gMidiInitScript[] = {
Script::Script(GroovieEngine *vm, EngineVersion version) :
_code(NULL), _savedCode(NULL), _stacktop(0), _debugger(NULL), _vm(vm),
- _videoFile(NULL), _videoRef(0), _staufsMove(NULL), _lastCursor(0xff),
+ _videoFile(NULL), _videoRef(-1), _staufsMove(NULL), _lastCursor(0xff),
_version(version), _random("GroovieScripts"), _tlcGame(0), _t11hGame(0) {
// Initialize the opcode set depending on the engine version
@@ -685,7 +685,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
// Close the previous video file
if (_videoFile) {
- _videoRef = 0;
+ _videoRef = -1;
delete _videoFile;
}
@@ -741,7 +741,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
// Close the file
delete _videoFile;
_videoFile = NULL;
- _videoRef = 0;
+ _videoRef = -1;
// Clear the input events while playing the video
_eventMouseClicked = 0;
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index dd5397ae0f..b4cd47c1ab 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -127,7 +127,7 @@ private:
// Video
Common::SeekableReadStream *_videoFile;
- uint32 _videoRef;
+ int32 _videoRef;
uint16 _bitflags;
uint16 _videoSkipAddress;
Commit: 71e2e2654ab8061eea30a52eb89d028be45b9350
https://github.com/scummvm/scummvm/commit/71e2e2654ab8061eea30a52eb89d028be45b9350
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Added T11H Engish version available on Steam
Changed paths:
engines/groovie/detection.cpp
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 37d663b6f0..9c24a4006a 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -193,6 +193,20 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieT11H, 1
},
+ // The 11th Hour Windows English (Available on Steam)
+ {
+ {
+ "11h", "Installed",
+ {
+ { "disk.1", 0, "4c1d0549f544f052fba2b7a9aebd1077", 220},
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
+ GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ },
+ kGroovieT11H, 1
+ },
+
// The 11th Hour DOS Demo English
{
{
Commit: cc61104b98de3d5a0e5c50524c866beb3bc7720f
https://github.com/scummvm/scummvm/commit/cc61104b98de3d5a0e5c50524c866beb3bc7720f
Author: Christian Lindemann (Alphard at gmx.net)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Start implementation of gallery puzzle
Changed paths:
engines/groovie/script.cpp
engines/groovie/t11hgame.cpp
engines/groovie/t11hgame.h
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index f285e86bbc..b470668ef2 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -2031,6 +2031,11 @@ void Script::o2_gamespecial() {
debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Mouse Trap in the lab (al.grv)", arg);
break;
+ case 6:
+ debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Mouse Trap in the lab (al.grv)", arg);
+ break;
+
+
default:
debugC(1, kDebugScript, "Groovie::Script: Op42 (0x%02X): T11H Invalid -> NOP", arg);
}
diff --git a/engines/groovie/t11hgame.cpp b/engines/groovie/t11hgame.cpp
index 417e13553e..3c45804a11 100644
--- a/engines/groovie/t11hgame.cpp
+++ b/engines/groovie/t11hgame.cpp
@@ -33,89 +33,178 @@
namespace Groovie {
- T11hGame::T11hGame() :
- _random("GroovieT11hGame"), _scriptVariables(NULL) {
- }
+/* Links between the pieces in the Gallery challenge */
+byte kGalleryLinks[21][10] = {
+ { 2, 4, 5, 0, 0, 0, 0, 0, 0, 0 }, // 1
+ { 1, 5, 3, 0, 0, 0, 0, 0, 0, 0 }, // 2
+ { 2, 5, 9, 12, 0, 0, 0, 0, 0, 0 }, // 3
+ { 1, 5, 6, 7, 8, 0, 0, 0, 0, 0 }, // 4
+ { 1, 2, 3, 4, 7, 8, 9, 0, 0, 0 }, // 5
+ { 4, 7, 10, 11, 13, 14, 15, 16, 18, 0 }, // 6
+ { 4, 5, 6, 8, 9, 10, 0, 0, 0, 0 }, // 7
+ { 4, 5, 7, 0, 0, 0, 0, 0, 0, 0 }, // 8
+ { 3, 5, 7, 10, 11, 12, 18, 0, 0, 0 }, // 9
+ { 6, 7, 9, 11, 0, 0, 0, 0, 0, 0 }, // 10
+ { 6, 9, 10, 18, 0, 0, 0, 0, 0, 0 }, // 11
+ { 3, 9, 18, 21, 0, 0, 0, 0, 0, 0 }, // 12
+ { 6, 14, 17, 19, 0, 0, 0, 0, 0, 0 }, // 13
+ { 6, 13, 15, 17, 19, 20, 21, 0, 0, 0 }, // 14
+ { 6, 14, 16, 18, 21, 0, 0, 0, 0, 0 }, // 15
+ { 6, 15, 0, 0, 0, 0, 0, 0, 0, 0 }, // 16
+ {13, 14, 19, 0, 0, 0, 0, 0, 0, 0 }, // 17
+ { 6, 9, 11, 12, 15, 21, 0, 0, 0, 0 }, // 18
+ {13, 14, 17, 20, 0, 0, 0, 0, 0, 0 }, // 19
+ {14, 19, 21, 0, 0, 0, 0, 0, 0, 0 }, // 20
+ {12, 14, 15, 18, 20, 0, 0, 0, 0, 0 } // 21
+};
+
+T11hGame::T11hGame() :
+ _random("GroovieT11hGame"), _scriptVariables(NULL) {
+}
+
+
+T11hGame::~T11hGame() {
+}
+
+
+void T11hGame::setVariables(byte *scriptVariables) {
+ _scriptVariables = scriptVariables;
+}
+
+
+/*
+* Puzzle in the Gallery.
+* The aim is to select the last part of the image. When selecting a part all surrounding parts are also selected
+* +--------------------+--------------------------------+--------+
+* | 1/1A | 2/1B | |
+* | +--------------+--+--------------------------+-----+ |
+* | | | | |
+* +--+ 4/1D | 5/1E | 3/1C |
+* | | | |
+* +-----+--------+--+--------+-----------------+--+--------+ |
+* | | | | | | |
+* | | | | | | |
+* | | | 8/21 | | | |
+* | | | | +-----------+ | |
+* | | | | | | | |
+* | | +-----------+ | 10/23 | 9/22 | |
+* | | | | | |
+* | | 7/20 +-----+-----+ +-----+
+* | | | | | | |
+* | +--------------------------+ | | | |
+* | 6/1F | | | |
+* +-----------+-----------+-----+--+ | 11 | | 12 |
+* | 13/26 | | | | | / | | / |
+* | +-----+-----+ | | | | 24 +-----------+ 25 |
+* | | | | | | | | | |
+* +-----+ 17/2A | | |16| | | | |
+* | | | | |/ | | | | |
+* | +-----+-----+ | |29| | | +-----+
+* | | | | | | | | |
+* | | | | | +-----+ 18/2B | |
+* | 19/2C | 14/27 | | | | | |
+* | | | | +-----------+ | |
+* | | | | | | | |
+* | | | +--+ 15/28 | | |
+* | | | | | |
+* | +--------+--+--------------------+-----------+ |
+* | | 20/2D | 21/2E |
+* +-----------+--------+-----------------------------------------+
+*/
+void T11hGame::opGallery() {
+ byte field1[21];
+ byte field2[21];
+ byte var_18[21];
+ int var_1c, eax, edx, ecx, esi;
- T11hGame::~T11hGame() {
+ // Copy RegMem to Field1
+ for (int i = 0; i < 21; i++) {
+ field1[i] = _scriptVariables[0x1A + i];
}
-
- void T11hGame::setVariables(byte *scriptVariables) {
- _scriptVariables = scriptVariables;
+ var_1c = 0;
+ for (int ebx = 0; ebx < 21; ebx++) {
+ var_18[ebx] = 0;
+ if (field1[ebx] != 0) {
+ memcpy(field2, field1, 21);
+
+ field2[ebx] = 0;
+ edx = kGalleryLinks[0][ebx];
+ eax = 1;
+ ecx = 0;
+ while (edx != 0) {
+ eax++;
+ field2[edx - 1] = ecx;
+ edx = kGalleryLinks[eax - 1][ebx];
+ }
+ var_18[ebx] = opGallerySub(1, field2);
+ if (var_18[ebx] == 1) {
+ var_1c++;
+ }
+ }
}
-
- /*
- * Puzzle in the Gallery.
- * The aim is to select the last part of the image. When selecting a part all surrounding parts are also selected
- * +--------------------+--------------------------------+--------+
- * | 1/1A | 2/1B | |
- * | +--------------+--+--------------------------+-----+ |
- * | | | | |
- * +--+ 4/1D | 5/1E | 3/1C |
- * | | | |
- * +-----+--------+--+--------+-----------------+--+--------+ |
- * | | | | | | |
- * | | | | | | |
- * | | | 8/21 | | | |
- * | | | | +-----------+ | |
- * | | | | | | | |
- * | | +-----------+ | 10/23 | 9/22 | |
- * | | | | | |
- * | | 7/20 +-----+-----+ +-----+
- * | | | | | | |
- * | +--------------------------+ | | | |
- * | 6/1F | | | |
- * +-----------+-----------+-----+--+ | 11 | | 12 |
- * | 13/26 | | | | | / | | / |
- * | +-----+-----+ | | | | 24 +-----------+ 25 |
- * | | | | | | | | | |
- * +-----+ 17/2A | | |16| | | | |
- * | | | | |/ | | | | |
- * | +-----+-----+ | |29| | | +-----+
- * | | | | | | | | |
- * | | | | | +-----+ 18/2B | |
- * | 19/2C | 14/27 | | | | | |
- * | | | | +-----------+ | |
- * | | | | | | | |
- * | | | +--+ 15/28 | | |
- * | | | | | |
- * | +--------+--+--------------------+-----------+ |
- * | | 20/2D | 21/2E |
- * +-----------+--------+-----------------------------------------+
- */
- void T11hGame::opGallery() {
- int selectedPart;
-
- do {
- selectedPart = _random.getRandomNumber(20) + 1;
- } while (_scriptVariables[0x19 + selectedPart] != 1);
-
- setScriptVar(0x2F, selectedPart / 10);
- setScriptVar(0x30, selectedPart % 10);
+ if (var_1c == 0) {
+ esi = 0;
+ for (eax = 0; eax < 21; eax++) {
+ if (var_18[eax] > esi) {
+ esi = var_18[eax];
+ }
+ }
+
+ if (esi == 2) {
+ esi = 1;
+ } else {
+ if (esi <= 20) {
+ esi = 2;
+ } else {
+ esi -= 12;
+ }
+ }
+
+ for (eax = 0; eax < 21; eax++) {
+ if (var_18[eax] <= esi) {
+ var_18[eax] = 1;
+ var_1c++;
+ }
+ }
}
- // This function is mainly for debugging purpose
- void inline T11hGame::setScriptVar(uint16 var, byte value) {
- _scriptVariables[var] = value;
- debugC(5, kDebugTlcGame, "script variable[0x%03X] = %d (0x%04X)", var, value, value);
- }
- void inline T11hGame::setScriptVar16(uint16 var, uint16 value) {
- _scriptVariables[var] = value & 0xFF;
- _scriptVariables[var + 1] = (value >> 8) & 0xFF;
- debugC(5, kDebugTlcGame, "script variable[0x%03X, 0x%03X] = %d (0x%02X, 0x%02X)", var, var + 1, value, _scriptVariables[var], _scriptVariables[var + 1]);
- }
- uint16 inline T11hGame::getScriptVar16(uint16 var) {
- uint16 value;
- value = _scriptVariables[var];
- value += _scriptVariables[var + 1] << 8;
- return value;
- }
+
+ int selectedPart;
+
+ do {
+ selectedPart = _random.getRandomNumber(20) + 1;
+ } while (_scriptVariables[0x19 + selectedPart] != 1);
+
+ setScriptVar(0x2F, selectedPart / 10);
+ setScriptVar(0x30, selectedPart % 10);
+}
+
+// This function is mainly for debugging purpose
+void inline T11hGame::setScriptVar(uint16 var, byte value) {
+ _scriptVariables[var] = value;
+ debugC(5, kDebugTlcGame, "script variable[0x%03X] = %d (0x%04X)", var, value, value);
+}
+
+void inline T11hGame::setScriptVar16(uint16 var, uint16 value) {
+ _scriptVariables[var] = value & 0xFF;
+ _scriptVariables[var + 1] = (value >> 8) & 0xFF;
+ debugC(5, kDebugTlcGame, "script variable[0x%03X, 0x%03X] = %d (0x%02X, 0x%02X)", var, var + 1, value, _scriptVariables[var], _scriptVariables[var + 1]);
+}
+
+uint16 inline T11hGame::getScriptVar16(uint16 var) {
+ uint16 value;
+
+ value = _scriptVariables[var];
+ value += _scriptVariables[var + 1] << 8;
+
+ return value;
+}
} // End of Namespace Groovie
diff --git a/engines/groovie/t11hgame.h b/engines/groovie/t11hgame.h
index 0a56a513db..cec28278fd 100644
--- a/engines/groovie/t11hgame.h
+++ b/engines/groovie/t11hgame.h
@@ -28,32 +28,32 @@
namespace Groovie {
- class GroovieEngine;
-
- class T11hGame
- {
- public:
- T11hGame();
- ~T11hGame();
-
- /**
- * Sets a pointer to the script variables. This makes it easier if we want
- * to debug write accesses to the script variables
- * @param scriptVariables The current variables from the script.
- */
- void setVariables(byte *scriptVariables);
-
- void opGallery();
-
- private:
- Common::RandomSource _random;
-
- void inline setScriptVar(uint16 var, byte value);
- void inline setScriptVar16(uint16 var, uint16 value);
- uint16 inline getScriptVar16(uint16 var);
- byte *_scriptVariables;
-
- };
+class GroovieEngine;
+
+class T11hGame
+{
+public:
+ T11hGame();
+ ~T11hGame();
+ /**
+ * Sets a pointer to the script variables. This makes it easier if we want
+ * to debug write accesses to the script variables
+ * @param scriptVariables The current variables from the script.
+ */
+ void setVariables(byte *scriptVariables);
+
+ void opGallery();
+ byte opGallerySub(int one, byte *field);
+
+private:
+ Common::RandomSource _random;
+
+ void inline setScriptVar(uint16 var, byte value);
+ void inline setScriptVar16(uint16 var, uint16 value);
+ uint16 inline getScriptVar16(uint16 var);
+ byte *_scriptVariables;
+
+};
} // End of Groovie namespace
Commit: ee91abb26a650ce6c7c0cee6a4e607259232206f
https://github.com/scummvm/scummvm/commit/ee91abb26a650ce6c7c0cee6a4e607259232206f
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix compiler errors
Changed paths:
engines/groovie/detection.cpp
engines/groovie/detection.h
engines/groovie/module.mk
engines/groovie/script.cpp
engines/groovie/script.h
engines/groovie/t11hgame.cpp
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 9c24a4006a..706211f73a 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -155,7 +155,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieT11H, 1
+ kGroovieT11H, 1
},
// The 11th Hour Macintosh English
@@ -166,7 +166,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
},
- kGroovieV2, 1
+ kGroovieT11H, 1
},
// The 11th Hour Macintosh English
diff --git a/engines/groovie/detection.h b/engines/groovie/detection.h
index dc13950aa9..16efa4af30 100644
--- a/engines/groovie/detection.h
+++ b/engines/groovie/detection.h
@@ -29,7 +29,10 @@ namespace Groovie {
enum EngineVersion {
kGroovieT7G,
- kGroovieV2
+ kGroovieT11H,
+ kGroovieCDY,
+ kGroovieUHP,
+ kGroovieTLC
};
struct GroovieGameDescription {
diff --git a/engines/groovie/module.mk b/engines/groovie/module.mk
index 8ad3be1085..8ab9f77c10 100644
--- a/engines/groovie/module.mk
+++ b/engines/groovie/module.mk
@@ -19,7 +19,7 @@ MODULE_OBJS := \
ifdef ENABLE_GROOVIE2
MODULE_OBJS += \
roq.o \
- tlcgame.o
+ tlcgame.o \
t11hgame.o
endif
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index b470668ef2..5f5c40832f 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -77,10 +77,6 @@ Script::Script(GroovieEngine *vm, EngineVersion version) :
_opcodes = _opcodesT7G;
} else {
_opcodes = _opcodesV2;
- break;
- default:
- _opcodes = nullptr;
- break;
}
// Prepare the variables
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index b4cd47c1ab..43bd364ae4 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -38,14 +38,6 @@ struct Surface;
namespace Groovie {
-enum EngineVersion {
- kGroovieT7G,
- kGroovieT11H,
- kGroovieCDY,
- kGroovieUHP,
- kGroovieTLC
-};
-
class CellGame;
class Debugger;
class GroovieEngine;
diff --git a/engines/groovie/t11hgame.cpp b/engines/groovie/t11hgame.cpp
index 3c45804a11..a75568f4ed 100644
--- a/engines/groovie/t11hgame.cpp
+++ b/engines/groovie/t11hgame.cpp
@@ -171,11 +171,6 @@ void T11hGame::opGallery() {
}
}
-
-
-
-
-
int selectedPart;
do {
@@ -186,6 +181,10 @@ void T11hGame::opGallery() {
setScriptVar(0x30, selectedPart % 10);
}
+byte T11hGame::opGallerySub(int one, byte* field) {
+ return 0;
+}
+
// This function is mainly for debugging purpose
void inline T11hGame::setScriptVar(uint16 var, byte value) {
_scriptVariables[var] = value;
Commit: 21449e3e5a284037d64ecb81e5fdab2aef375535
https://github.com/scummvm/scummvm/commit/21449e3e5a284037d64ecb81e5fdab2aef375535
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix duplicated debug channels
Changed paths:
engines/groovie/groovie.cpp
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 3c80c1f16b..162e5bd90d 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -54,19 +54,6 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) :
_graphicsMan(NULL), _macResFork(NULL), _waitingForInput(false), _font(NULL),
_spookyMode(false) {
- // Initialize the custom debug levels
- DebugMan.addDebugChannel(kDebugVideo, "Video", "Debug video and audio playback");
- DebugMan.addDebugChannel(kDebugResource, "Resource", "Debug resource management");
- DebugMan.addDebugChannel(kDebugScript, "Script", "Debug the scripts");
- DebugMan.addDebugChannel(kDebugUnknown, "Unknown", "Report values of unknown data in files");
- DebugMan.addDebugChannel(kDebugHotspots, "Hotspots", "Show the hotspots");
- DebugMan.addDebugChannel(kDebugCursor, "Cursor", "Debug cursor decompression / switching");
- DebugMan.addDebugChannel(kDebugMIDI, "MIDI", "Debug MIDI / XMIDI files");
- DebugMan.addDebugChannel(kDebugScriptvars, "Scriptvars", "Print out any change to script variables");
- DebugMan.addDebugChannel(kDebugCell, "Cell", "Debug the cell game (in the microscope)");
- DebugMan.addDebugChannel(kDebugFast, "Fast", "Play videos quickly, with no sound (unstable)");
- DebugMan.addDebugChannel(kDebugTlcGame, "TlcGame", "Debug special TLC commands");
-
// Adding the default directories
const Common::FSNode gameDataDir(ConfMan.get("path"));
SearchMan.addSubDirectoryMatching(gameDataDir, "groovie");
Commit: 5fbf8bd14691b8a2e20403ee08cac03a00cd0d5b
https://github.com/scummvm/scummvm/commit/5fbf8bd14691b8a2e20403ee08cac03a00cd0d5b
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix accidental o2 in _opcodesT7G
Changed paths:
engines/groovie/script.cpp
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 5f5c40832f..f77f080e3f 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -2117,7 +2117,7 @@ Script::OpcodeFunc Script::_opcodesT7G[NUM_OPCODES] = {
&Script::o_copyrecttobg,
&Script::o_restorestkpnt, // 0x38
&Script::o_obscureswap,
- &Script::o2_printstring,
+ &Script::o_printstring,
&Script::o_hotspot_slot,
&Script::o_checkvalidsaves, // 0x3C
&Script::o_resetvars,
Commit: 7465118de609e3e3056ff63a32b8abc7d71080a3
https://github.com/scummvm/scummvm/commit/7465118de609e3e3056ff63a32b8abc7d71080a3
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix T7G regression with intro and outro songs (track2.ogg)
Changed paths:
engines/groovie/groovie.cpp
engines/groovie/groovie.h
engines/groovie/player.cpp
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 162e5bd90d..592a81d6db 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -366,6 +366,10 @@ Common::Platform GroovieEngine::getPlatform() const {
return _gameDescription->desc.platform;
}
+EngineVersion GroovieEngine::getEngineVersion() const {
+ return _gameDescription->version;
+}
+
bool GroovieEngine::hasFeature(EngineFeature f) const {
return
(f == kSupportsReturnToLauncher) ||
diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h
index 0737305580..7d4f802a12 100644
--- a/engines/groovie/groovie.h
+++ b/engines/groovie/groovie.h
@@ -96,6 +96,7 @@ public:
~GroovieEngine() override;
Common::Platform getPlatform() const;
+ EngineVersion getEngineVersion() const;
protected:
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index f64666d314..5c525be4c3 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -38,7 +38,7 @@ bool VideoPlayer::load(Common::SeekableReadStream *file, uint16 flags) {
_file = file;
_flags = flags;
_overrideSpeed = false;
- if (_audioStream) {
+ if ( _vm->getEngineVersion() != kGroovieT7G && _audioStream ) {
g_system->getMixer()->stopAll();
}
_audioStream = NULL;
Commit: e7a406657f91de51405fe54d7a9e6da0bc3c6ce3
https://github.com/scummvm/scummvm/commit/e7a406657f91de51405fe54d7a9e6da0bc3c6ce3
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE:Grooovie2 clearer names for different versions of The 11th Hour
Changed paths:
engines/groovie/detection.cpp
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 706211f73a..f880d25042 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -140,7 +140,7 @@ static const GroovieGameDescription gameDescriptions[] = {
// The 11th Hour DOS English
{
{
- "11h", "",
+ "11h", "CD-ROM",
AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
@@ -196,7 +196,7 @@ static const GroovieGameDescription gameDescriptions[] = {
// The 11th Hour Windows English (Available on Steam)
{
{
- "11h", "Installed",
+ "11h", "Digital",
{
{ "disk.1", 0, "4c1d0549f544f052fba2b7a9aebd1077", 220},
{ 0, 0, 0, 0 }
Commit: 3494ce638cec8cb7d81ec7781110da41f30f3d1f
https://github.com/scummvm/scummvm/commit/3494ce638cec8cb7d81ec7781110da41f30f3d1f
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: add o2_copybgtofg and fix o_videofromstring1
Changed paths:
engines/groovie/script.cpp
engines/groovie/script.h
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index f77f080e3f..228b54fb61 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -1116,23 +1116,23 @@ void Script::o_strcmpnejmp_var() { // 0x21
}
}
-void Script::o_copybgtofg() { // 0x22
- if (_version == kGroovieT7G) {
- debugC(1, kDebugScript, "Groovie::Script: COPY_BG_TO_FG");
- debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_BG_TO_FG", _currentInstruction - 1);
- memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * _vm->_graphicsMan->_foreground.h * _vm->_graphicsMan->_foreground.format.bytesPerPixel);
- } else {
- debugC(1, kDebugScript, "Groovie::Script: COPY_SCREEN_TO_BG");
- debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_SCREEN_TO_BG", _currentInstruction - 1);
+void Script::o_copybgtofg() { // 0x22
+ debugC(1, kDebugScript, "Groovie::Script: COPY_BG_TO_FG");
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_BG_TO_FG", _currentInstruction - 1);
+ memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * _vm->_graphicsMan->_foreground.h * _vm->_graphicsMan->_foreground.format.bytesPerPixel);
+}
- Graphics::Surface *screen = _vm->_system->lockScreen();
- if (_vm->_graphicsMan->isFullScreen()) {
- _vm->_graphicsMan->_foreground.copyFrom(screen->getSubArea(Common::Rect(0, 0, 640, 480)));
- } else {
- _vm->_graphicsMan->_foreground.copyFrom(screen->getSubArea(Common::Rect(0, 80, 640, 400)));
- }
- _vm->_system->unlockScreen();
+void Script::o2_copybgtofg() { // 0x22
+ debugC(1, kDebugScript, "Groovie::Script: COPY_SCREEN_TO_BG");
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_SCREEN_TO_BG", _currentInstruction - 1);
+
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ if (_vm->_graphicsMan->isFullScreen()) {
+ _vm->_graphicsMan->_foreground.copyFrom(screen->getSubArea(Common::Rect(0, 0, 640, 480)));
+ } else {
+ _vm->_graphicsMan->_foreground.copyFrom(screen->getSubArea(Common::Rect(0, 80, 640, 400)));
}
+ _vm->_system->unlockScreen();
}
void Script::o_strcmpeqjmp() { // 0x23
@@ -1188,8 +1188,10 @@ void Script::o_videofromstring1() {
debugC(2, kDebugVideo, "\nGroovie::Script: @0x%04X: Playing video %d ('%s') via 0x26 (VideoFromString1)", instStart-1, fileref, vidName.c_str());
}
- // Clear bit 1
- _bitflags &= ~(1 << 1);
+ if (_version != kGroovieT7G) {
+ // Clear bit 1
+ _bitflags &= ~(1 << 1);
+ }
// Play the video
if (!playvideofromref(fileref)) {
@@ -2189,7 +2191,7 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {
&Script::o_inc,
&Script::o_dec, // 0x20
&Script::o_strcmpnejmp_var,
- &Script::o_copybgtofg,
+ &Script::o2_copybgtofg,
&Script::o_strcmpeqjmp,
&Script::o_mov, // 0x24
&Script::o_add,
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index 43bd364ae4..0eb0091588 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -236,6 +236,7 @@ private:
void o_stub56();
void o_stub59();
+ void o2_copybgtofg();
void o2_printstring();
void o2_playsong();
void o2_midicontrol();
Commit: 7e53331044e4428f32564498db7f5a11b7743eae
https://github.com/scummvm/scummvm/commit/7e53331044e4428f32564498db7f5a11b7743eae
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Codacy and formatting
Changed paths:
engines/groovie/groovie.cpp
engines/groovie/roq.cpp
engines/groovie/script.cpp
engines/groovie/t11hgame.cpp
engines/groovie/tlcgame.cpp
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 592a81d6db..353c756082 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -214,7 +214,7 @@ Common::Error GroovieEngine::run() {
filename = "demo.grv";
else if (getPlatform() == Common::kPlatformMacintosh)
filename = "script.grv"; // Stored inside the executable's resource fork
- } else if (_gameDescription->version != kGroovieT7G) {
+ } else {
// Open the disk index
Common::File disk;
if (!disk.open(filename)) {
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index c2f3fc9210..d7bd6e6a08 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -339,7 +339,7 @@ bool ROQPlayer::playFrameInternal() {
_syst->updateScreen();
// For overlay videos, set the background buffer when the video ends
- if (_alpha && (!_flagTwo || (_flagTwo && _file->eos()))) {
+ if (_alpha && (!_flagTwo || _file->eos())) {
//_bg->copyFrom(*_fg);
}
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 228b54fb61..5243cc5f8f 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -938,7 +938,7 @@ void Script::o_random() {
if (_version == kGroovieT7G) {
setVariable(varnum, _random.getRandomNumber(maxnum));
} else {
- setVariable(varnum, _random.getRandomNumber(maxnum-1));
+ setVariable(varnum, _random.getRandomNumber(maxnum - 1));
}
}
@@ -1471,7 +1471,7 @@ void Script::o_printstring() {
uint8 counter = 0;
debugC(1, kDebugScript, "Groovie::Script: PRINTSTRING");
- debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: PRINTSTRING", _currentInstruction-1);
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: PRINTSTRING", _currentInstruction - 1);
memset(stringstorage, 0, 15);
do {
diff --git a/engines/groovie/t11hgame.cpp b/engines/groovie/t11hgame.cpp
index a75568f4ed..a383e0e470 100644
--- a/engines/groovie/t11hgame.cpp
+++ b/engines/groovie/t11hgame.cpp
@@ -116,7 +116,7 @@ void T11hGame::opGallery() {
byte field1[21];
byte field2[21];
byte var_18[21];
- int var_1c, eax, edx, ecx, esi;
+ int var_1c, eax, edx, ecx;
// Copy RegMem to Field1
for (int i = 0; i < 21; i++) {
@@ -146,7 +146,7 @@ void T11hGame::opGallery() {
}
if (var_1c == 0) {
- esi = 0;
+ int esi = 0;
for (eax = 0; eax < 21; eax++) {
if (var_18[eax] > esi) {
esi = var_18[eax];
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
index 0823add1f8..3642d08b2b 100644
--- a/engines/groovie/tlcgame.cpp
+++ b/engines/groovie/tlcgame.cpp
@@ -121,7 +121,7 @@ void TlcGame::regionsInit() {
// Read header for each question entry
_regionHeader = new TlcRegionsHeader[_numRegionHeaders];
for (int i = 0; i < _numRegionHeaders; i++) {
- regionsfile->read(&_regionHeader[i].name, sizeof(TlcRegionsHeader::name));
+ regionsfile->read(_regionHeader[i].name, sizeof(TlcRegionsHeader::name));
regionsfile->seek(25 - sizeof(TlcRegionsHeader::name), SEEK_CUR);
_regionHeader[i].numAnswers = regionsfile->readUint32LE();
_regionHeader[i].offset = regionsfile->readUint32LE();
@@ -774,13 +774,10 @@ void TlcGame::tatInitRegs() {
void TlcGame::tatLoadDBHeaders() {
- Common::SeekableReadStream *tataidbfile = 0;
- int iEpisode, iBin;
-
// Load tat headers if not already done
if (_tatHeaders == NULL) {
// Open tataidb.rle
- tataidbfile = SearchMan.createReadStreamForMember("SYSTEM/TATAIDB.RLE");
+ Common::SeekableReadStream *tataidbfile = SearchMan.createReadStreamForMember("SYSTEM/TATAIDB.RLE");
if (!tataidbfile) {
error("TLC:TatLoadDB: Could not open 'SYSTEM/TATAIDB.RLE'");
}
@@ -788,10 +785,10 @@ void TlcGame::tatLoadDBHeaders() {
_tatEpisodes = tataidbfile->readUint32LE();
_tatHeaders = new TlcTatHeader[_tatEpisodes];
- for (iEpisode = 0; iEpisode < _tatEpisodes; iEpisode++) {
+ for (int iEpisode = 0; iEpisode < _tatEpisodes; iEpisode++) {
_tatHeaders[iEpisode].questionsNum = tataidbfile->readUint32LE();
_tatHeaders[iEpisode].questionsOffset = tataidbfile->readUint32LE();
- for (iBin = 0; iBin < 16; iBin++) {
+ for (int iBin = 0; iBin < 16; iBin++) {
_tatHeaders[iEpisode].binDividends[iBin] = tataidbfile->readByte();
}
}
Commit: c7e4c851f6ec648bcc71d3634e85f998f2a4d7c2
https://github.com/scummvm/scummvm/commit/c7e4c851f6ec648bcc71d3634e85f998f2a4d7c2
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: some cleanup
Changed paths:
engines/groovie/cursor.cpp
engines/groovie/detection.cpp
engines/groovie/groovie.cpp
engines/groovie/music.cpp
engines/groovie/roq.cpp
engines/groovie/script.cpp
engines/groovie/t11hgame.h
diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp
index 31222fce58..114d8c570b 100644
--- a/engines/groovie/cursor.cpp
+++ b/engines/groovie/cursor.cpp
@@ -345,10 +345,10 @@ void Cursor_v2::decodeFrame(byte *pal, byte *data, byte *dest) {
// Decode pixel
if (alpha) {
- *ptr = alpha;
- *(ptr + 1) = r;
- *(ptr + 2) = g;
- *(ptr + 3) = b;
+ ptr[0] = alpha;
+ ptr[1] = r;
+ ptr[2] = g;
+ ptr[3] = b;
}
ptr += 4;
}
@@ -359,7 +359,7 @@ void Cursor_v2::decodeFrame(byte *pal, byte *data, byte *dest) {
ptr = tmp;
for (int y = 0; y < _height; y++) {
for (int x = 0; x < _width; x++) {
- *(uint32 *)dest = _format.ARGBToColor(*ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3));
+ *(uint32 *)dest = _format.ARGBToColor(ptr[0], ptr[1], ptr[2], ptr[3]);
dest += 4;
ptr += 4;
}
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index f880d25042..67399f8363 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -42,6 +42,7 @@ static const DebugChannelDef debugFlagList[] = {
{Groovie::kDebugScriptvars, "Scriptvars", "Print out any change to script variables"},
{Groovie::kDebugCell, "Cell", "Debug the cell game (in the microscope)"},
{Groovie::kDebugFast, "Fast", "Play videos quickly, with no sound (unstable)"},
+ {Groovie::kDebugTlcGame, "TLCGame", "Debug the questionnaires in TLC"},
DEBUG_CHANNEL_END
};
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 353c756082..81d20ffd54 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -170,30 +170,29 @@ Common::Error GroovieEngine::run() {
switch (_gameDescription->version) {
case kGroovieT7G:
- case kGroovieT11H:
- case kGroovieCDY:
- case kGroovieUHP:
// Detect ScummVM Music Enhancement Project presence (T7G only)
- if (Common::File::exists("gu16.ogg") && _gameDescription->version == kGroovieT7G) {
+ if (Common::File::exists("gu16.ogg")) {
// Load player for external files
_musicPlayer = new MusicPlayerIOS(this);
+ break;
}
- else {
- // Create the music player
- switch (getPlatform()) {
- case Common::kPlatformMacintosh:
- if (_gameDescription->version == kGroovieT7G)
- _musicPlayer = new MusicPlayerMac_t7g(this);
- else
- _musicPlayer = new MusicPlayerMac_v2(this);
- break;
- case Common::kPlatformIOS:
- _musicPlayer = new MusicPlayerIOS(this);
- break;
- default:
- _musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample");
- break;
- }
+ case kGroovieT11H:
+ case kGroovieCDY:
+ case kGroovieUHP:
+ // Create the music player
+ switch (getPlatform()) {
+ case Common::kPlatformMacintosh:
+ if (_gameDescription->version == kGroovieT7G)
+ _musicPlayer = new MusicPlayerMac_t7g(this);
+ else
+ _musicPlayer = new MusicPlayerMac_v2(this);
+ break;
+ case Common::kPlatformIOS:
+ _musicPlayer = new MusicPlayerIOS(this);
+ break;
+ default:
+ _musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample");
+ break;
}
break;
@@ -202,7 +201,6 @@ Common::Error GroovieEngine::run() {
break;
}
-
// Load volume levels
syncSoundSettings();
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 5e53b92ccf..ba231ba86f 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -790,7 +790,7 @@ bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
Audio::AudioStream *audStream = seekStream;
- // Loop if requested
+ // TODO: Loop if requested
if (loop || 1)
audStream = Audio::makeLoopingAudioStream(seekStream, 0);
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index d7bd6e6a08..228f0af755 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -333,12 +333,12 @@ bool ROQPlayer::playFrameInternal() {
waitFrame();
if (_dirty) {
- // Update the screen
+ // TODO: Update the screen
void *src = (_alpha && 0) ? _bg->getPixels() : _screen->getPixels();
_syst->copyRectToScreen(src, _screen->pitch, 0, (_syst->getHeight() - _screen->h) / 2, _screen->w, _screen->h);
_syst->updateScreen();
- // For overlay videos, set the background buffer when the video ends
+ // TODO: For overlay videos, set the background buffer when the video ends
if (_alpha && (!_flagTwo || _file->eos())) {
//_bg->copyFrom(*_fg);
}
@@ -496,7 +496,7 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
else if (_screen->h == 480 && height != 480)
_vm->_graphicsMan->switchToFullScreen(false);
- // Clear the buffers with black
+ // TODO: Clear the buffers with black
if (!_alpha && 0) {
_currBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
_prevBuf->fillRect(Common::Rect(width, height), _vm->_pixelFormat.RGBToColor(0, 0, 0));
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 5243cc5f8f..3ec85370cf 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -1871,7 +1871,7 @@ void Script::o2_midicontrol() {
break;
case 3:
- // Set Volume? Or is it some kind of fade in / out
+ // TODO: Set Volume? Or is it some kind of fade in / out
debugC(1, kDebugScript, "Groovie::Script: MIDI %d: Set volume/time: %d", arg1, arg2);
//_vm->_musicPlayer->setUserVolume(arg2);
break;
diff --git a/engines/groovie/t11hgame.h b/engines/groovie/t11hgame.h
index cec28278fd..5bb4bd9595 100644
--- a/engines/groovie/t11hgame.h
+++ b/engines/groovie/t11hgame.h
@@ -43,11 +43,11 @@ public:
void setVariables(byte *scriptVariables);
void opGallery();
- byte opGallerySub(int one, byte *field);
private:
Common::RandomSource _random;
+ byte opGallerySub(int one, byte *field);
void inline setScriptVar(uint16 var, byte value);
void inline setScriptVar16(uint16 var, uint16 value);
uint16 inline getScriptVar16(uint16 var);
Commit: 454dbff26499ce8e6ecb6257605f0072c014728b
https://github.com/scummvm/scummvm/commit/454dbff26499ce8e6ecb6257605f0072c014728b
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: v2 use o2_printstring opcode
Changed paths:
engines/groovie/script.cpp
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 3ec85370cf..0413aa54d4 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -2215,7 +2215,7 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {
&Script::o_copyrecttobg,
&Script::o_restorestkpnt, // 0x38
&Script::o_obscureswap,
- &Script::o_printstring,
+ &Script::o2_printstring,
&Script::o_hotspot_slot,
&Script::o_checkvalidsaves, // 0x3C
&Script::o_resetvars,
Commit: 7a09ae0a15dd3134c3a7ae2634bc9dbd413b6649
https://github.com/scummvm/scummvm/commit/7a09ae0a15dd3134c3a7ae2634bc9dbd413b6649
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: T11H fix mouse trap crash
Changed paths:
engines/groovie/script.cpp
engines/groovie/t11hgame.cpp
engines/groovie/t11hgame.h
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 0413aa54d4..fa69af3a33 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -2027,10 +2027,11 @@ void Script::o2_gamespecial() {
case 5:
debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Mouse Trap in the lab (al.grv)", arg);
+ _t11hGame->opMouseTrap();
break;
case 6:
- debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Mouse Trap in the lab (al.grv)", arg);
+ debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Pente (pt.grv)", arg);
break;
diff --git a/engines/groovie/t11hgame.cpp b/engines/groovie/t11hgame.cpp
index a383e0e470..2500e7b454 100644
--- a/engines/groovie/t11hgame.cpp
+++ b/engines/groovie/t11hgame.cpp
@@ -72,6 +72,31 @@ void T11hGame::setVariables(byte *scriptVariables) {
}
+/*
+* Mouse Trap puzzle in the Lab.
+*
+* Stauf's Goal is space 1, counting up as you go north east towards the north corner which is space 5 and the moveable space to the left of that is space 4
+* South east from Stauf's goal is the next line starting with space 6, counting up as you go north east where the moveable space to the right of the north corner is space 10
+* Next line is 11 (unmovable) to 15 (unmoveable), this line contains the center space which is space 13
+* Next line is 16 (moveable) to 20 (moveable)
+* Next line is 21 (unmovable) to 25 (unmovable), with 25 being the player's goal door
+*
+* Space -2 is the next piece, outside of the box
+*/
+void T11hGame::opMouseTrap() {
+ // TODO: properly implement mouse trap game
+ // variable 24 is the mouse?
+ //_scriptVariables[24] = 2;
+
+ // value of 0 is V, 1 is <, 2 is ^, 3 is >
+ // variable 23 is the outside piece
+ _scriptVariables[23] = 1;
+ // variable slot is the space number + 25, the left corner (Stauf's goal) is space 1, above that is space 2, the center is 13, and the right corner (goal) is space 25
+ for(int i=27; i<=49; i++)
+ _scriptVariables[i] = 3;
+}
+
+
/*
* Puzzle in the Gallery.
* The aim is to select the last part of the image. When selecting a part all surrounding parts are also selected
diff --git a/engines/groovie/t11hgame.h b/engines/groovie/t11hgame.h
index 5bb4bd9595..4d3448cee5 100644
--- a/engines/groovie/t11hgame.h
+++ b/engines/groovie/t11hgame.h
@@ -42,6 +42,7 @@ public:
*/
void setVariables(byte *scriptVariables);
+ void opMouseTrap();
void opGallery();
private:
Commit: 87e98d1e868a80470058b318b15b1504eb0504af
https://github.com/scummvm/scummvm/commit/87e98d1e868a80470058b318b15b1504eb0504af
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: stubs for T11H AI puzzles
This is enough to get through the whole game, although you have to use the GameBook to solve mouse trap, chapel, and cake. Modern art has rudimentary AI. Beehive and Pente both auto-solve. Updated o2_stub49 so the player can choose an ending.
Changed paths:
engines/groovie/groovie.cpp
engines/groovie/script.cpp
engines/groovie/script.h
engines/groovie/t11hgame.cpp
engines/groovie/t11hgame.h
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 81d20ffd54..8cb5a4398d 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -176,6 +176,7 @@ Common::Error GroovieEngine::run() {
_musicPlayer = new MusicPlayerIOS(this);
break;
}
+ // else, fall through
case kGroovieT11H:
case kGroovieCDY:
case kGroovieUHP:
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index fa69af3a33..2b5ea796d7 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -2014,6 +2014,7 @@ void Script::o2_gamespecial() {
case 2:
debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Beehive Puzzle in the top room (hs.grv) TODO", arg);
+ _t11hGame->opBeehive();
break;
case 3:
@@ -2032,6 +2033,7 @@ void Script::o2_gamespecial() {
case 6:
debugC(1, kDebugScript, "Groovie::Script Op42 (0x%02X): T11H Pente (pt.grv)", arg);
+ _t11hGame->opPente();
break;
@@ -2061,6 +2063,21 @@ void Script::o2_setscriptend() {
debugC(1, kDebugScript, "Groovie::Script: SetScriptEnd (0x%04X)", arg);
}
+void Script::o2_stub59() {
+ uint16 val1 = readScript8or16bits();
+ uint8 val2 = readScript8bits();
+
+ debugC(1, kDebugScript, "Groovie::Script: STUB59: 0x%04X 0x%02X", val1, val2);
+
+ // FIXME: bitflag 1 is set by o2_vdxtransition
+ // I believe bitflag 3 is supposed to be set by background sounds (clock chimes, wind, heart, drip in the kitchen)
+ // Currently background sounds don't work so the flag is never set
+ // Which causes the end of the game to not work properly because it's supposed to give you until the clock chimes are finished before rolling the credits
+ //_variables[val1] = char(bool(_bitflags & 5));
+ // For now, just set to 1 so the player can choose an ending
+ _variables[val1] = 1;
+}
+
Script::OpcodeFunc Script::_opcodesT7G[NUM_OPCODES] = {
&Script::o_nop, // 0x00
&Script::o_nop,
@@ -2247,7 +2264,7 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {
&Script::o_stub56,
&Script::o_invalid,
&Script::o_invalid, // 0x58
- &Script::o_stub59
+ &Script::o2_stub59
};
} // End of Groovie namespace
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index 0eb0091588..01fa20938d 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -249,6 +249,7 @@ private:
void o2_gamespecial();
void o2_stub52();
void o2_setscriptend();
+ void o2_stub59();
};
} // End of Groovie namespace
diff --git a/engines/groovie/t11hgame.cpp b/engines/groovie/t11hgame.cpp
index 2500e7b454..4cce464673 100644
--- a/engines/groovie/t11hgame.cpp
+++ b/engines/groovie/t11hgame.cpp
@@ -84,7 +84,7 @@ void T11hGame::setVariables(byte *scriptVariables) {
* Space -2 is the next piece, outside of the box
*/
void T11hGame::opMouseTrap() {
- // TODO: properly implement mouse trap game
+ // FIXME: properly implement mouse trap game
// variable 24 is the mouse?
//_scriptVariables[24] = 2;
@@ -92,8 +92,23 @@ void T11hGame::opMouseTrap() {
// variable 23 is the outside piece
_scriptVariables[23] = 1;
// variable slot is the space number + 25, the left corner (Stauf's goal) is space 1, above that is space 2, the center is 13, and the right corner (goal) is space 25
- for(int i=27; i<=49; i++)
+ for (int i = 27; i <= 49; i++) {
_scriptVariables[i] = 3;
+ }
+}
+
+
+void T11hGame::opBeehive() {
+ // FIXME: properly implement Beehive game
+ // for now just auto-solve the puzzle so the player can continue
+ _scriptVariables[13] = 5;
+}
+
+
+void T11hGame::opPente() {
+ // FIXME: properly implement Pente game (the final puzzle)
+ // for now just auto-solve the puzzle so the player can continue
+ _scriptVariables[5] = 4;
}
@@ -197,7 +212,8 @@ void T11hGame::opGallery() {
}
int selectedPart;
-
+
+ // TODO: copy the AI from the game
do {
selectedPart = _random.getRandomNumber(20) + 1;
} while (_scriptVariables[0x19 + selectedPart] != 1);
@@ -207,6 +223,7 @@ void T11hGame::opGallery() {
}
byte T11hGame::opGallerySub(int one, byte* field) {
+ // TODO
return 0;
}
diff --git a/engines/groovie/t11hgame.h b/engines/groovie/t11hgame.h
index 4d3448cee5..e930dab634 100644
--- a/engines/groovie/t11hgame.h
+++ b/engines/groovie/t11hgame.h
@@ -43,6 +43,8 @@ public:
void setVariables(byte *scriptVariables);
void opMouseTrap();
+ void opBeehive();
+ void opPente();
void opGallery();
private:
Commit: 132ac84bdbec8c383e127212d74fd0a1ea6a4547
https://github.com/scummvm/scummvm/commit/132ac84bdbec8c383e127212d74fd0a1ea6a4547
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: replace strcmpi with scumm_stricmp
tlcgame.cpp was using the Windows-specific strcmpi
Changed paths:
engines/groovie/tlcgame.cpp
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
index 3642d08b2b..916a95f8af 100644
--- a/engines/groovie/tlcgame.cpp
+++ b/engines/groovie/tlcgame.cpp
@@ -868,7 +868,7 @@ void TlcGame::tatResultQuest() {
if (questIdx >= _tatQuestCount) {
error("TLC:ResultQuest: Could not find question '%s' in TATAIDB. Count: %d", questName, _tatQuestCount);
}
- } while (strcmpi(questName, _tatQuestions[questIdx].name) != 0);
+ } while (scumm_stricmp(questName, _tatQuestions[questIdx].name) != 0);
// Get selected answer. Range: 0..7
selectedAns = _scriptVariables[0x46];
Commit: 6fb5822f98dbc837c5c6011cb5365f7ab403e4f8
https://github.com/scummvm/scummvm/commit/6fb5822f98dbc837c5c6011cb5365f7ab403e4f8
Author: Die4Ever (die4ever2006 at hotmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix video frame pacing
Integer math in the waitFrame function was causing drift over time, remembering how many milliseconds we rounded off fixes it.
Changed paths:
engines/groovie/player.cpp
engines/groovie/player.h
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index 5c525be4c3..f5481da1d5 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -59,9 +59,9 @@ void VideoPlayer::setOverrideSpeed(bool isOverride) {
_overrideSpeed = isOverride;
if (_fps != 0) {
if (isOverride)
- _millisBetweenFrames = 1000 / 26;
+ _millisBetweenFrames = 1000.0f / 26.0f;
else
- _millisBetweenFrames = 1000 / _fps;
+ _millisBetweenFrames = 1000.0f / float(_fps);
}
}
@@ -97,16 +97,26 @@ void VideoPlayer::waitFrame() {
if (!_begunPlaying) {
_begunPlaying = true;
_lastFrameTime = currTime;
+ _frameTimeDrift = 0.0f;
} else {
uint32 millisDiff = currTime - _lastFrameTime;
- if (millisDiff < _millisBetweenFrames) {
- debugC(7, kDebugVideo, "Groovie::Player: Delaying %d (currTime=%d, _lastFrameTime=%d, millisDiff=%d, _millisBetweenFrame=%d)",
- _millisBetweenFrames - millisDiff, currTime, _lastFrameTime, millisDiff, _millisBetweenFrames);
- _syst->delayMillis(_millisBetweenFrames - millisDiff);
+ float fMillis = _millisBetweenFrames + _frameTimeDrift;
+ // use floorf instead of roundf, because delayMillis often slightly over-sleeps
+ uint32 millisSleep = fmaxf( 0.0f, floorf(fMillis) - float(millisDiff));
+
+ if (millisSleep > 0) {
+ debugC(7, kDebugVideo, "Groovie::Player: Delaying %d (currTime=%d, _lastFrameTime=%d, millisDiff=%d, _millisBetweenFrame=%.2f, _frameTimeDrift=%.2f)",
+ millisSleep, currTime, _lastFrameTime, millisDiff, _millisBetweenFrames, _frameTimeDrift);
+ _syst->delayMillis(millisSleep);
currTime = _syst->getMillis();
debugC(7, kDebugVideo, "Groovie::Player: Finished delay at %d", currTime);
}
- debugC(6, kDebugVideo, "Groovie::Player: Frame displayed at %d (%f FPS)", currTime, 1000.0 / (currTime - _lastFrameTime));
+
+ _frameTimeDrift = fMillis - float(currTime - _lastFrameTime);
+ if (abs(_frameTimeDrift) >= _millisBetweenFrames) {
+ _frameTimeDrift = 0;
+ }
+ debugC(6, kDebugVideo, "Groovie::Player: Frame displayed at %d (%f FPS), _frameTimeDrift=%.2f", currTime, 1000.0 / (currTime - _lastFrameTime), _frameTimeDrift);
_lastFrameTime = currTime;
}
}
diff --git a/engines/groovie/player.h b/engines/groovie/player.h
index 952d3ac208..9a1d52a5ab 100644
--- a/engines/groovie/player.h
+++ b/engines/groovie/player.h
@@ -63,8 +63,9 @@ private:
bool _begunPlaying;
bool _overrideSpeed;
uint16 _fps;
- uint16 _millisBetweenFrames;
+ float _millisBetweenFrames;
uint32 _lastFrameTime;
+ float _frameTimeDrift;
protected:
void waitFrame();
Commit: 8da84fdda9c09c36512d0df3af1c460927f035f3
https://github.com/scummvm/scummvm/commit/8da84fdda9c09c36512d0df3af1c460927f035f3
Author: Die4Ever (30947252+Die4Ever at users.noreply.github.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: added background sound effects
For The 11th Hour, this means things like clock chimes and wind sounds. This also fixes the end of the game where you have until the clock chimes 12 to choose a door.
- also renamed the stub ops functions
- sound effect volume setting for Groovie 2 games
- stop sound effects when playing an FMV (an interlaced video)
Changed paths:
engines/groovie/detection.cpp
engines/groovie/groovie.cpp
engines/groovie/groovie.h
engines/groovie/player.cpp
engines/groovie/player.h
engines/groovie/roq.cpp
engines/groovie/roq.h
engines/groovie/script.cpp
engines/groovie/script.h
engines/groovie/vdx.cpp
engines/groovie/vdx.h
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 67399f8363..943d6b4d4f 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -65,7 +65,7 @@ static const GroovieGameDescription gameDescriptions[] = {
"t7g", "",
AD_ENTRY1s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659),
Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS,
- GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
+ GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
kGroovieT7G, 0
},
@@ -76,7 +76,7 @@ static const GroovieGameDescription gameDescriptions[] = {
"t7g", "",
AD_ENTRY1s("T7GMac", "acdc4a58dd3f007f65e99b99d78e0bce", 1814029),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK,
- GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
+ GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
kGroovieT7G, 0
},
@@ -92,7 +92,7 @@ static const GroovieGameDescription gameDescriptions[] = {
"t7g", "",
AD_ENTRY1s("T7GMac", "6bdee8d0f9eef6d58d02fcd7deec3fb2", 1830783),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK,
- GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
+ GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
kGroovieT7G, 0
},
@@ -103,7 +103,7 @@ static const GroovieGameDescription gameDescriptions[] = {
"t7g", "",
AD_ENTRY1s("T7GMac", "0d595d4b44ae1814082938d051e5174e", 1830783),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK,
- GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
+ GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
kGroovieT7G, 0
},
@@ -119,7 +119,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_LISTEND
},
Common::RU_RUS, Common::kPlatformDOS, ADGF_NO_FLAGS,
- GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
+ GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
kGroovieT7G, 0
},
@@ -133,7 +133,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_LISTEND
},
Common::EN_ANY, Common::kPlatformIOS, ADGF_NO_FLAGS,
- GUIO3(GUIO_NOMIDI, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
+ GUIO4(GUIO_NOMIDI, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
kGroovieT7G, 0
},
@@ -367,7 +367,7 @@ public:
// to the detection entries. In the latter case, this TODO should be
// replaced with an according explanation.
_flags = kADFlagUseExtraAsHint;
- _guiOptions = GUIO3(GUIO_NOSUBTITLES, GUIO_NOSFX, GUIO_NOASPECT);
+ _guiOptions = GUIO2(GUIO_NOSUBTITLES, GUIO_NOASPECT);
// Need MIDI directory to detect 11H Mac Installed
_maxScanDepth = 2;
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 8cb5a4398d..f2797ef7fa 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -160,6 +160,7 @@ Common::Error GroovieEngine::run() {
_grvCursorMan = new GrvCursorMan_v2(_system);
#ifdef ENABLE_GROOVIE2
_videoPlayer = new ROQPlayer(this);
+ _soundQueue.setVM(this);
#endif
break;
@@ -350,6 +351,7 @@ Common::Error GroovieEngine::run() {
// Update the screen if required
_graphicsMan->update();
+ _soundQueue.tick();
}
return Common::kNoError;
@@ -427,4 +429,71 @@ void GroovieEngine::waitForInput() {
_waitingForInput = true;
}
+SoundEffectQueue::SoundEffectQueue() {
+ _vm = NULL;
+ _player = NULL;
+ _file = NULL;
+}
+
+void SoundEffectQueue::setVM(GroovieEngine *vm) {
+ _vm = vm;
+#ifdef ENABLE_GROOVIE2
+ _player = new ROQSoundPlayer(vm);
+#endif
+}
+
+void SoundEffectQueue::queue(Common::SeekableReadStream *soundfile, uint32 loops) {
+ if (_queue.size() > 20) {
+ stopAll();
+ }
+ _queue.push({soundfile, loops});
+ for (int i = 1; i < loops; i++) {
+ _queue.push({soundfile, loops});
+ }
+ tick();
+}
+
+void SoundEffectQueue::tick() {
+#ifdef ENABLE_GROOVIE2
+ if (_file && !_player->playFrame()) {
+ _vm->_script->setBitFlag(0, true);
+ return;
+ }
+ if (_queue.size() == 0) {
+ deleteFile();
+ return;
+ }
+
+ SoundQueueEntry entry = _queue.front();
+ if (entry._loops != 0 || _queue.size() > 1) {
+ _queue.pop();
+ }
+ if (_file != entry._file) {
+ deleteFile();
+ }
+ _file = entry._file;
+
+ _vm->_script->setBitFlag(0, true);
+ _file->seek(0);
+ _player->load(_file, 0);
+ _player->playFrame();
+#endif
+}
+
+void SoundEffectQueue::deleteFile() {
+ if (_file) {
+ delete _file;
+ _file = NULL;
+ _vm->_script->setBitFlag(0, false);
+ }
+}
+
+void SoundEffectQueue::stopAll() {
+ if (_file && _player) {
+ _player->stopAudioStream();
+ }
+ _queue.clear();
+ deleteFile();
+}
+
} // End of namespace Groovie
diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h
index 7d4f802a12..1171abcf5d 100644
--- a/engines/groovie/groovie.h
+++ b/engines/groovie/groovie.h
@@ -90,6 +90,27 @@ enum GameSpeed {
struct GroovieGameDescription;
+struct SoundQueueEntry {
+ Common::SeekableReadStream *_file;
+ uint32 _loops;
+};
+
+class SoundEffectQueue {
+public:
+ SoundEffectQueue();
+ void setVM(GroovieEngine *vm);
+ void queue(Common::SeekableReadStream *soundfile, uint32 loops);
+ void tick();
+ void stopAll();
+
+protected:
+ void deleteFile();
+ VideoPlayer *_player;
+ GroovieEngine *_vm;
+ Common::Queue<SoundQueueEntry> _queue;
+ Common::SeekableReadStream *_file;
+};
+
class GroovieEngine : public Engine {
public:
GroovieEngine(OSystem *syst, const GroovieGameDescription *gd);
@@ -122,6 +143,7 @@ public:
ResMan *_resMan;
GrvCursorMan *_grvCursorMan;
VideoPlayer *_videoPlayer;
+ SoundEffectQueue _soundQueue;
MusicPlayer *_musicPlayer;
GraphicsMan *_graphicsMan;
const Graphics::Font *_font;
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index f5481da1d5..6ee0c6738e 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -31,18 +31,15 @@ namespace Groovie {
VideoPlayer::VideoPlayer(GroovieEngine *vm) :
_vm(vm), _syst(vm->_system), _file(NULL), _audioStream(NULL), _fps(0), _overrideSpeed(false), _flags(0),
- _begunPlaying(false), _millisBetweenFrames(0), _lastFrameTime(0) {
+ _begunPlaying(false), _millisBetweenFrames(0), _lastFrameTime(0), _frameTimeDrift(0) {
}
bool VideoPlayer::load(Common::SeekableReadStream *file, uint16 flags) {
_file = file;
_flags = flags;
_overrideSpeed = false;
- if ( _vm->getEngineVersion() != kGroovieT7G && _audioStream ) {
- g_system->getMixer()->stopAll();
- }
- _audioStream = NULL;
+ stopAudioStream();
_fps = loadInternal();
if (_fps != 0) {
diff --git a/engines/groovie/player.h b/engines/groovie/player.h
index 9a1d52a5ab..ff1b49971f 100644
--- a/engines/groovie/player.h
+++ b/engines/groovie/player.h
@@ -42,6 +42,7 @@ public:
bool playFrame();
virtual void resetFlags() {}
virtual void setOrigin(int16 x, int16 y) {}
+ virtual void stopAudioStream() = 0;
protected:
// To be implemented by subclasses
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 228f0af755..372c432278 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -124,6 +124,13 @@ void ROQPlayer::setOrigin(int16 x, int16 y) {
_origY = y;
}
+void ROQPlayer::stopAudioStream() {
+ if (_audioStream) {
+ g_system->getMixer()->stopHandle(_soundHandle);
+ }
+ _audioStream = NULL;
+}
+
uint16 ROQPlayer::loadInternal() {
if (DebugMan.isDebugChannelEnabled(kDebugVideo)) {
int8 i;
@@ -487,6 +494,8 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
if (height <= width / 3) {
_interlacedVideo = 1;
_offScale = 2;
+ // HACK: kill the sound queue so people can hear dialog during FMVs
+ _vm->_soundQueue.stopAll();
}
debugC(2, kDebugVideo, "Groovie::ROQ: width=%d, height=%d, scaleX=%d, scaleY=%d, _offScale=%d, interl.=%d, _alpha=%d", width, height, _scaleX, _scaleY, _interlacedVideo, _offScale, _alpha);
@@ -677,9 +686,7 @@ bool ROQPlayer::processBlockSoundMono(ROQBlockHeader &blockHeader) {
// Initialize the audio stream if needed
if (!_audioStream && !playFirstFrame()) {
- _audioStream = Audio::makeQueuingAudioStream(22050, false);
- Audio::SoundHandle sound_handle;
- g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &sound_handle, _audioStream);
+ createAudioStream(false);
}
// Create the audio buffer
@@ -723,9 +730,7 @@ bool ROQPlayer::processBlockSoundStereo(ROQBlockHeader &blockHeader) {
// Initialize the audio stream if needed
if (!_audioStream && !playFirstFrame()) {
- _audioStream = Audio::makeQueuingAudioStream(22050, true);
- Audio::SoundHandle sound_handle;
- g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &sound_handle, _audioStream);
+ createAudioStream(true);
}
// Create the audio buffer
@@ -857,4 +862,24 @@ void ROQPlayer::copy(byte size, int destx, int desty, int offx, int offy) {
}
}
+void ROQPlayer::createAudioStream(bool stereo) {
+ _audioStream = Audio::makeQueuingAudioStream(22050, stereo);
+ g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle, _audioStream);
+}
+
+ROQSoundPlayer::ROQSoundPlayer(GroovieEngine *vm) : ROQPlayer(vm) {
+ // HACK: we set the pixel format here to prevent a crash because this never plays any videos
+ // maybe we should just pre-create these buffers no matter what
+ _overBuf->free();
+ _overBuf->create(640, 480, _vm->_pixelFormat);
+}
+
+ROQSoundPlayer::~ROQSoundPlayer() {
+}
+
+void ROQSoundPlayer::createAudioStream(bool stereo) {
+ _audioStream = Audio::makeQueuingAudioStream(22050, stereo);
+ g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream);
+}
+
} // End of Groovie namespace
diff --git a/engines/groovie/roq.h b/engines/groovie/roq.h
index 84c9419163..895ec996f0 100644
--- a/engines/groovie/roq.h
+++ b/engines/groovie/roq.h
@@ -24,6 +24,7 @@
#define GROOVIE_ROQ_H
#include "groovie/player.h"
+#include "audio/mixer.h"
namespace Groovie {
@@ -41,9 +42,19 @@ public:
~ROQPlayer();
void setOrigin(int16 x, int16 y);
+ Audio::SoundHandle getSoundHandle() {
+ return _soundHandle;
+ }
+
protected:
uint16 loadInternal() override;
bool playFrameInternal() override;
+ void stopAudioStream() override;
+ virtual void createAudioStream(bool stereo);
+
+ Audio::SoundHandle _soundHandle;
+ Graphics::Surface *_bg, *_screen, *_overBuf;
+ Graphics::Surface *_currBuf, *_prevBuf;
private:
bool readBlockHeader(ROQBlockHeader &blockHeader);
@@ -86,8 +97,6 @@ private:
bool _flagTwo; // If _flagOne is set. Copy frame to the foreground otherwise to the background
// Buffers
- Graphics::Surface *_bg, *_screen, *_overBuf;
- Graphics::Surface *_currBuf, *_prevBuf;
void buildShowBuf();
byte _scaleX, _scaleY;
byte _offScale;
@@ -98,6 +107,13 @@ private:
Common::Rect *_restoreArea; // Area to be repainted by foreground
};
+class ROQSoundPlayer : public ROQPlayer {
+public:
+ ROQSoundPlayer(GroovieEngine *vm);
+ ~ROQSoundPlayer();
+ void createAudioStream(bool stereo) override;
+};
+
} // End of Groovie namespace
#endif // GROOVIE_ROQ_H
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 2b5ea796d7..19a2a5b385 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -111,9 +111,7 @@ Script::Script(GroovieEngine *vm, EngineVersion version) :
Script::~Script() {
delete[] _code;
delete[] _savedCode;
-
delete _videoFile;
-
delete _staufsMove;
delete _tlcGame;
delete _t11hGame;
@@ -124,6 +122,18 @@ void Script::setVariable(uint16 variablenum, byte value) {
debugC(1, kDebugScriptvars, "script variable[0x%03X] = %d (0x%04X)", variablenum, value, value);
}
+void Script::setBitFlag(int bitnum, bool value) {
+ if (value) {
+ _bitflags |= (1 << bitnum);
+ } else {
+ _bitflags &= ~(1 << bitnum);
+ }
+}
+
+bool Script::getBitFlag(int bitnum) {
+ return _bitflags & (1 << bitnum);
+}
+
void Script::setDebugger(Debugger *debugger) {
_debugger = debugger;
}
@@ -761,6 +771,24 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
return true;
}
+bool Script::playBackgroundSound(uint32 fileref, uint32 loops) {
+ if (fileref == -1) {
+ return false;
+ }
+
+ // Try to open the new file
+ Common::SeekableReadStream *_soundFile = _vm->_resMan->open(fileref);
+
+ if (_soundFile) {
+ _vm->_soundQueue.queue(_soundFile, loops);
+ } else {
+ error("Groovie::Script: Couldn't open file");
+ return false;
+ }
+
+ return true;
+}
+
void Script::o_bf5on() { // 0x0A
debugC(1, kDebugScript, "Groovie::Script: BF5ON: bitflag 5 turned on");
_bitflags |= 1 << 5;
@@ -2048,10 +2076,10 @@ void Script::o2_gamespecial() {
}
}
-void Script::o2_stub52() {
+void Script::o2_copyfgtobg() {
uint8 arg = readScript8bits();
- debugC(1, kDebugScript, "Groovie::Script: STUB52 (0x%02X)", arg);
- debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: STUB52 (0x%02X)", _currentInstruction-2, arg);
+ debugC(1, kDebugScript, "Groovie::Script: o2_copyfgtobg (0x%02X)", arg);
+ debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: o2_copyfgtobg (0x%02X)", _currentInstruction-2, arg);
// return;
_vm->_graphicsMan->_background.copyFrom(_vm->_graphicsMan->_foreground);
@@ -2063,19 +2091,31 @@ void Script::o2_setscriptend() {
debugC(1, kDebugScript, "Groovie::Script: SetScriptEnd (0x%04X)", arg);
}
-void Script::o2_stub59() {
+void Script::o2_playsound() {
+ uint32 fileref = readScript32bits();
+ uint8 loops = readScript8bits();// 0 means loop forever, 1 means play once
+ uint8 val3 = readScript8bits();
+
+ debugC(1, kDebugScript, "Groovie::Script: o2_playsound: 0x%08X 0x%02X 0x%02X", fileref, loops, val3);
+
+ if (fileref == 0 && loops == 0) {
+ _vm->_soundQueue.stopAll();
+ return;
+ }
+
+ playBackgroundSound(fileref, loops);
+}
+
+void Script::o2_check_sounds_overlays() {
uint16 val1 = readScript8or16bits();
uint8 val2 = readScript8bits();
debugC(1, kDebugScript, "Groovie::Script: STUB59: 0x%04X 0x%02X", val1, val2);
- // FIXME: bitflag 1 is set by o2_vdxtransition
- // I believe bitflag 3 is supposed to be set by background sounds (clock chimes, wind, heart, drip in the kitchen)
- // Currently background sounds don't work so the flag is never set
- // Which causes the end of the game to not work properly because it's supposed to give you until the clock chimes are finished before rolling the credits
- //_variables[val1] = char(bool(_bitflags & 5));
- // For now, just set to 1 so the player can choose an ending
- _variables[val1] = 1;
+ // bitflag 0 is set by background sounds (clock chimes, wind, heart, drip in the kitchen)
+ // bitflag 2 is set by overlay videos
+ // this instruction is notably used at the end of the game when you have until midnight to choose a door
+ _variables[val1] = getBitFlag(0) || getBitFlag(2);
}
Script::OpcodeFunc Script::_opcodesT7G[NUM_OPCODES] = {
@@ -2257,14 +2297,14 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {
&Script::o2_savescreen,
&Script::o2_restorescreen, // 0x50
&Script::o2_setvideoskip,
- &Script::o2_stub52,
+ &Script::o2_copyfgtobg,
&Script::o_hotspot_outrect,
&Script::o_invalid, // 0x54
&Script::o2_setscriptend,
- &Script::o_stub56,
+ &Script::o2_playsound,
&Script::o_invalid,
&Script::o_invalid, // 0x58
- &Script::o2_stub59
+ &Script::o2_check_sounds_overlays
};
} // End of Groovie namespace
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index 01fa20938d..302a8506b7 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -65,6 +65,9 @@ public:
void setMouseClick(uint8 button);
void setKbdChar(uint8 c);
+ void setBitFlag(int bitnum, bool value);
+ bool getBitFlag(int bitnum);
+
Common::String &getContext();
private:
@@ -149,6 +152,7 @@ private:
void loadgame(uint slot);
void savegame(uint slot);
bool playvideofromref(uint32 fileref, bool loopUntilAudioDone = false);
+ bool playBackgroundSound(uint32 fileref, uint32 loops);
void printString(Graphics::Surface *surface, const char *str);
// Opcodes
@@ -247,9 +251,10 @@ private:
void o2_savescreen();
void o2_restorescreen();
void o2_gamespecial();
- void o2_stub52();
+ void o2_copyfgtobg();
void o2_setscriptend();
- void o2_stub59();
+ void o2_playsound();
+ void o2_check_sounds_overlays();
};
} // End of Groovie namespace
diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp
index 5ebcfc70dd..b668dca4ee 100644
--- a/engines/groovie/vdx.cpp
+++ b/engines/groovie/vdx.cpp
@@ -56,6 +56,10 @@ void VDXPlayer::setOrigin(int16 x, int16 y) {
_origY = y;
}
+void VDXPlayer::stopAudioStream() {
+ _audioStream = NULL;
+}
+
uint16 VDXPlayer::loadInternal() {
if (DebugMan.isDebugChannelEnabled(kDebugVideo)) {
int8 i;
diff --git a/engines/groovie/vdx.h b/engines/groovie/vdx.h
index 219bd96270..27f84745de 100644
--- a/engines/groovie/vdx.h
+++ b/engines/groovie/vdx.h
@@ -41,6 +41,7 @@ public:
protected:
uint16 loadInternal() override;
bool playFrameInternal() override;
+ void stopAudioStream() override;
private:
Graphics::Surface *_fg, *_bg;
Commit: 038758a7f2d96295ff4b73da646c8c6c232f5c67
https://github.com/scummvm/scummvm/commit/038758a7f2d96295ff4b73da646c8c6c232f5c67
Author: Die4Ever (30947252+Die4Ever at users.noreply.github.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: Clandestiny music
Clandestiny uses a hardcoded lookup table for song filenames
Changed paths:
A engines/groovie/clangame.cpp
A engines/groovie/clangame.h
engines/groovie/groovie.cpp
engines/groovie/module.mk
engines/groovie/music.cpp
engines/groovie/music.h
diff --git a/engines/groovie/clangame.cpp b/engines/groovie/clangame.cpp
new file mode 100644
index 0000000000..408ed0e766
--- /dev/null
+++ b/engines/groovie/clangame.cpp
@@ -0,0 +1,43 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "clangame.h"
+
+namespace Groovie {
+
+// This a list of files for background music. These list is hard-coded in the TLC player.
+const Common::String kClanMusicFiles[] = {"mbf_arb1.mpg", "mbf_arm1.mpg", "mbf_bal1.mpg", "mbf_c2p2.mpg", "act18mus.mpg", "act15mus.mpg", "act21mus.mpg",
+ "act05mus.mpg", "act04mus.mpg", "act23mus.mpg", "act17mus.mpg", "act03mus.mpg", "act06mus.mpg", "act19mus.mpg",
+ "act07mus.mpg", "mbf_mne1.mpg", "act24mus.mpg", "act24mus.mpg", "act14mus.mpg", "act20mus.mpg", "act15mus.mpg",
+ "act13mus.mpg", "act08mus.mpg", "mbf_uph1.mpg", "mbf_uph1.mpg", "act19mus.mpg", "mbf_bol1.mpg", "mbf_cbk1.mpg",
+ "mbf_glf1.mpg", "mbf_bro1.mpg", "mbf_c1r1.mpg", "mbf_c1r1.mpg", "mbf_c1r1.mpg", "mbf_c1r1.mpg", "mbf_c2r1.mpg",
+ "mbf_c2r1.mpg", "mbf_c2r1.mpg", "mbf_c2r1.mpg", "mbf_c3r1.mpg", "mbf_c3r1.mpg", "mbf_c3r1.mpg", "mbf_c4r1.mpg",
+ "mbf_c4r1.mpg", "mbf_c1p2.mpg", "mbf_c3p3.mpg", "mbf_c1p3.mpg", "mbf_bro1.mpg", "mbf_c1p1.mpg", "act17mus.mpg",
+ "mbf_c2p2.mpg", "mbf_c2p1.mpg", "act10mus.mpg", "mbf_c1p1.mpg", "mbf_mne1.mpg", "mbf_c3p3.mpg", "act17mus.mpg",
+ "mbf_c3p2.mpg", "mbf_c3p1.mpg", "act25mus.mpg", "mbf_c4p2.mpg", "mbf_c4p1.mpg"};
+
+// Gets the filename of the background music file.
+Common::String ClanGame::getClanMusicFilename(int musicId) {
+ return kClanMusicFiles[musicId];
+}
+
+} // namespace Groovie
diff --git a/engines/groovie/clangame.h b/engines/groovie/clangame.h
new file mode 100644
index 0000000000..42fba84950
--- /dev/null
+++ b/engines/groovie/clangame.h
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef GROOVIE_CLANGAME_H
+#define GROOVIE_CLANGAME_H
+
+#include "common/str.h"
+
+namespace Groovie {
+
+class ClanGame {
+public:
+ static Common::String getClanMusicFilename(int musicId);
+};
+
+} // namespace Groovie
+
+#endif // GROOVIE_CLANGAME_H
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index f2797ef7fa..b99896fabf 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -179,7 +179,6 @@ Common::Error GroovieEngine::run() {
}
// else, fall through
case kGroovieT11H:
- case kGroovieCDY:
case kGroovieUHP:
// Create the music player
switch (getPlatform()) {
@@ -198,6 +197,10 @@ Common::Error GroovieEngine::run() {
}
break;
+ case kGroovieCDY:
+ _musicPlayer = new MusicPlayerClan(this);
+ break;
+
case kGroovieTLC:
_musicPlayer = new MusicPlayerTlc(this);
break;
diff --git a/engines/groovie/module.mk b/engines/groovie/module.mk
index 8ab9f77c10..a56e6bac57 100644
--- a/engines/groovie/module.mk
+++ b/engines/groovie/module.mk
@@ -20,7 +20,8 @@ ifdef ENABLE_GROOVIE2
MODULE_OBJS += \
roq.o \
tlcgame.o \
- t11hgame.o
+ t11hgame.o \
+ clangame.o
endif
# This module can be built as a plugin
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index ba231ba86f..53042d0676 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -27,6 +27,7 @@
#include "groovie/groovie.h"
#include "groovie/resource.h"
#include "groovie/tlcgame.h"
+#include "groovie/clangame.h"
#include "backends/audiocd/audiocd.h"
#include "common/config-manager.h"
@@ -768,6 +769,10 @@ void MusicPlayerTlc::unload() {
_vm->_system->getMixer()->stopHandle(_handle);
}
+Common::String MusicPlayerTlc::getFilename(uint32 fileref) {
+ return TlcGame::getTlcMusicFilename(fileref);
+}
+
bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
// Find correct filename
Common::String filename;
@@ -775,7 +780,7 @@ bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
Audio::SeekableAudioStream *seekStream = NULL;
// Create the audio stream from fileref
- filename = TlcGame::getTlcMusicFilename(fileref);
+ filename = getFilename(fileref);
fileHandle->open(filename);
if (fileHandle->isOpen()) {
seekStream = Audio::makeMP3Stream(fileHandle, DisposeAfterUse::YES);
@@ -802,5 +807,9 @@ bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
return true;
}
+Common::String MusicPlayerClan::getFilename(uint32 fileref) {
+ return ClanGame::getClanMusicFilename(fileref);
+}
+
} // End of Groovie namespace
diff --git a/engines/groovie/music.h b/engines/groovie/music.h
index 06d1408fc5..b75ad56af1 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -211,6 +211,7 @@ public:
~MusicPlayerTlc();
protected:
+ virtual Common::String getFilename(uint32 fileref);
void updateVolume();
bool load(uint32 fileref, bool loop);
void unload();
@@ -219,6 +220,14 @@ private:
Audio::SoundHandle _handle;
};
+class MusicPlayerClan : public MusicPlayerTlc {
+public:
+ MusicPlayerClan(GroovieEngine *vm) : MusicPlayerTlc(vm) {}
+
+protected:
+ Common::String getFilename(uint32 fileref) override;
+};
+
} // End of Groovie namespace
#endif // GROOVIE_MUSIC_H
Commit: a72ac69b4e22ea7f4a3b0b58f026f96815ea2293
https://github.com/scummvm/scummvm/commit/a72ac69b4e22ea7f4a3b0b58f026f96815ea2293
Author: Die4Ever (30947252+Die4Ever at users.noreply.github.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: right click to fast forward
For videos that don't have a _videoSkipAddress this allows you to fast forward through them. Also allows you to skip audio files like in T11H the riddles and hints.
Changed paths:
engines/groovie/groovie.cpp
engines/groovie/player.cpp
engines/groovie/player.h
engines/groovie/roq.cpp
engines/groovie/script.cpp
engines/groovie/vdx.cpp
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index b99896fabf..db3ec6545b 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -480,6 +480,9 @@ void SoundEffectQueue::tick() {
_file->seek(0);
_player->load(_file, 0);
_player->playFrame();
+ if (_player->isFastForwarding()) {
+ stopAll();
+ }
#endif
}
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index 6ee0c6738e..833f1d85f9 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -26,6 +26,7 @@
#include "groovie/player.h"
#include "groovie/groovie.h"
#include "audio/mixer.h"
+#include "common/debug-channels.h"
namespace Groovie {
@@ -62,6 +63,15 @@ void VideoPlayer::setOverrideSpeed(bool isOverride) {
}
}
+void VideoPlayer::fastForward() {
+ _millisBetweenFrames = 0;
+ _frameTimeDrift = 0;
+}
+
+bool VideoPlayer::isFastForwarding() {
+ return DebugMan.isDebugChannelEnabled(kDebugFast) || _millisBetweenFrames <= 0;
+}
+
bool VideoPlayer::playFrame() {
bool end = true;
@@ -76,9 +86,10 @@ bool VideoPlayer::playFrame() {
// Wait for pending audio
if (_audioStream) {
- if (_audioStream->endOfData()) {
+ if (_audioStream->endOfData() || isFastForwarding()) {
// Mark the audio stream as finished (no more data will be appended)
_audioStream->finish();
+ _audioStream = NULL;
} else {
// Don't end if there's still audio playing
end = false;
@@ -90,6 +101,9 @@ bool VideoPlayer::playFrame() {
}
void VideoPlayer::waitFrame() {
+ if (isFastForwarding()) {
+ return;
+ }
uint32 currTime = _syst->getMillis();
if (!_begunPlaying) {
_begunPlaying = true;
diff --git a/engines/groovie/player.h b/engines/groovie/player.h
index ff1b49971f..6181d94e5f 100644
--- a/engines/groovie/player.h
+++ b/engines/groovie/player.h
@@ -43,6 +43,8 @@ public:
virtual void resetFlags() {}
virtual void setOrigin(int16 x, int16 y) {}
virtual void stopAudioStream() = 0;
+ void fastForward();
+ bool isFastForwarding();
protected:
// To be implemented by subclasses
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 372c432278..7dfe1860ad 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -712,7 +712,7 @@ bool ROQPlayer::processBlockSoundMono(ROQBlockHeader &blockHeader) {
#ifdef SCUMM_LITTLE_ENDIAN
flags |= Audio::FLAG_LITTLE_ENDIAN;
#endif
- if (!playFirstFrame())
+ if (!playFirstFrame() && !isFastForwarding())
_audioStream->queueBuffer((byte *)buffer, blockHeader.size * 2, DisposeAfterUse::YES, flags);
else
free(buffer);
@@ -769,7 +769,7 @@ bool ROQPlayer::processBlockSoundStereo(ROQBlockHeader &blockHeader) {
#ifdef SCUMM_LITTLE_ENDIAN
flags |= Audio::FLAG_LITTLE_ENDIAN;
#endif
- if (!playFirstFrame())
+ if (!playFirstFrame() && !isFastForwarding())
_audioStream->queueBuffer((byte *)buffer, blockHeader.size * 2, DisposeAfterUse::YES, flags);
else
free(buffer);
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 19a2a5b385..28985edd4c 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -726,6 +726,8 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
// End the playback
return true;
+ } else if (_eventMouseClicked == 2) {
+ _vm->_videoPlayer->fastForward();
}
// Video available, play one frame
diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp
index b668dca4ee..c224bb47aa 100644
--- a/engines/groovie/vdx.cpp
+++ b/engines/groovie/vdx.cpp
@@ -185,10 +185,8 @@ bool VDXPlayer::playFrameInternal() {
}
// Wait until the current frame can be shown
+ waitFrame();
- if (!DebugMan.isDebugChannelEnabled(kDebugFast)) {
- waitFrame();
- }
// TODO: Move it to a better place
// Update the screen
if (currRes == 0x25) {
@@ -534,7 +532,7 @@ void VDXPlayer::chunkSound(Common::ReadStream *in) {
if (getOverrideSpeed())
setOverrideSpeed(false);
- if (!_audioStream) {
+ if (!_audioStream && !isFastForwarding()) {
_audioStream = Audio::makeQueuingAudioStream(22050, false);
Audio::SoundHandle sound_handle;
g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &sound_handle, _audioStream);
@@ -542,8 +540,10 @@ void VDXPlayer::chunkSound(Common::ReadStream *in) {
byte *data = (byte *)malloc(60000);
int chunksize = in->read(data, 60000);
- if (!DebugMan.isDebugChannelEnabled(kDebugFast)) {
+ if (!isFastForwarding()) {
_audioStream->queueBuffer(data, chunksize, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED);
+ } else {
+ free(data);
}
}
Commit: 58a795c02210262131e09269ae60c355491ceb2e
https://github.com/scummvm/scummvm/commit/58a795c02210262131e09269ae60c355491ceb2e
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: stop audio when fast forwarding
Changed paths:
engines/groovie/player.cpp
engines/groovie/script.cpp
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index 833f1d85f9..048be82457 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -66,6 +66,7 @@ void VideoPlayer::setOverrideSpeed(bool isOverride) {
void VideoPlayer::fastForward() {
_millisBetweenFrames = 0;
_frameTimeDrift = 0;
+ stopAudioStream();
}
bool VideoPlayer::isFastForwarding() {
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 28985edd4c..5ceb3e44e6 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -728,6 +728,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
return true;
} else if (_eventMouseClicked == 2) {
_vm->_videoPlayer->fastForward();
+ _eventMouseClicked = 0;
}
// Video available, play one frame
Commit: c0f489fe09da9fc75ec89539e1de5854f5edaeef
https://github.com/scummvm/scummvm/commit/c0f489fe09da9fc75ec89539e1de5854f5edaeef
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix op 0x0A o2_bf0on
Changed paths:
engines/groovie/script.cpp
engines/groovie/script.h
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 5ceb3e44e6..61271f2403 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -610,6 +610,11 @@ void Script::o_bf7on() { // 0x07
_bitflags |= 1 << 7;
}
+void Script::o2_bf0on() { // v2 0x0A
+ debugC(1, kDebugScript, "Groovie::Script: BF0ON: bitflag 0 turned on");
+ _bitflags |= 1;
+}
+
void Script::o_setbackgroundsong() { // 0x08
uint16 fileref = readScript16bits();
debugC(1, kDebugScript, "Groovie::Script: SetBackgroundSong(0x%04X)", fileref);
@@ -2228,7 +2233,7 @@ Script::OpcodeFunc Script::_opcodesV2[NUM_OPCODES] = {
&Script::o_nop,
&Script::o2_setbackgroundsong, // 0x08
&Script::o2_videofromref,
- &Script::o_bf5on,
+ &Script::o2_bf0on,
&Script::o_inputloopstart,
&Script::o_keyboardaction, // 0x0C
&Script::o_hotspot_rect,
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index 302a8506b7..f7a9079bb9 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -240,6 +240,7 @@ private:
void o_stub56();
void o_stub59();
+ void o2_bf0on();
void o2_copybgtofg();
void o2_printstring();
void o2_playsong();
Commit: f1890553edda729a1ec716150334de3dcae68454
https://github.com/scummvm/scummvm/commit/f1890553edda729a1ec716150334de3dcae68454
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix o2_midicontrol stop command
Changed paths:
engines/groovie/roq.cpp
engines/groovie/script.cpp
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 7dfe1860ad..881bb15696 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -494,8 +494,6 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) {
if (height <= width / 3) {
_interlacedVideo = 1;
_offScale = 2;
- // HACK: kill the sound queue so people can hear dialog during FMVs
- _vm->_soundQueue.stopAll();
}
debugC(2, kDebugVideo, "Groovie::ROQ: width=%d, height=%d, scaleX=%d, scaleY=%d, _offScale=%d, interl.=%d, _alpha=%d", width, height, _scaleX, _scaleY, _interlacedVideo, _offScale, _alpha);
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 61271f2403..11410f541a 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -1893,8 +1893,9 @@ void Script::o2_midicontrol() {
case 0:
// Stop Playback
debugC(1, kDebugScript, "Groovie::Script: MIDI %d:Stop: %d", arg1, arg2);
- _vm->_musicPlayer->setUserVolume(0);
- // _vm->_musicPlayer->setBackgroundDelay(0);
+ _vm->_musicPlayer->stop();
+ _vm->_soundQueue.stopAll();
+ //_vm->_musicPlayer->setBackgroundDelay(0);
break;
case 1:
@@ -1902,8 +1903,8 @@ void Script::o2_midicontrol() {
debugC(1, kDebugScript, "Groovie::Script: MIDI %d: Play song %d", arg1, arg2);
_vm->_musicPlayer->playSong(arg2);
_vm->_musicPlayer->setUserVolume(100);
-// _vm->_musicPlayer->setBackgroundSong(arg2);
-// _vm->_musicPlayer->startBackground();
+ //_vm->_musicPlayer->setBackgroundSong(arg2);
+ //_vm->_musicPlayer->startBackground();
break;
case 3:
Commit: 1dd7a5f66a147c5e41099bb59275713f9cb4f728
https://github.com/scummvm/scummvm/commit/1dd7a5f66a147c5e41099bb59275713f9cb4f728
Author: Die4Ever (30947252+Die4Ever at users.noreply.github.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: code review feedback
fixes for MusicPlayerTlc
optimizations and cleanup in roq.cpp
lots of cleanup in tlcgame.cpp
Changed paths:
engines/groovie/clangame.cpp
engines/groovie/clangame.h
engines/groovie/module.mk
engines/groovie/music.cpp
engines/groovie/music.h
engines/groovie/player.cpp
engines/groovie/roq.cpp
engines/groovie/script.cpp
engines/groovie/t11hgame.cpp
engines/groovie/t11hgame.h
engines/groovie/tlcgame.cpp
engines/groovie/tlcgame.h
diff --git a/engines/groovie/clangame.cpp b/engines/groovie/clangame.cpp
index 408ed0e766..451d345cdb 100644
--- a/engines/groovie/clangame.cpp
+++ b/engines/groovie/clangame.cpp
@@ -20,12 +20,12 @@
*
*/
-#include "clangame.h"
+#include "groovie/clangame.h"
namespace Groovie {
// This a list of files for background music. These list is hard-coded in the TLC player.
-const Common::String kClanMusicFiles[] = {"mbf_arb1.mpg", "mbf_arm1.mpg", "mbf_bal1.mpg", "mbf_c2p2.mpg", "act18mus.mpg", "act15mus.mpg", "act21mus.mpg",
+const char * kClanMusicFiles[] = {"mbf_arb1.mpg", "mbf_arm1.mpg", "mbf_bal1.mpg", "mbf_c2p2.mpg", "act18mus.mpg", "act15mus.mpg", "act21mus.mpg",
"act05mus.mpg", "act04mus.mpg", "act23mus.mpg", "act17mus.mpg", "act03mus.mpg", "act06mus.mpg", "act19mus.mpg",
"act07mus.mpg", "mbf_mne1.mpg", "act24mus.mpg", "act24mus.mpg", "act14mus.mpg", "act20mus.mpg", "act15mus.mpg",
"act13mus.mpg", "act08mus.mpg", "mbf_uph1.mpg", "mbf_uph1.mpg", "act19mus.mpg", "mbf_bol1.mpg", "mbf_cbk1.mpg",
@@ -36,7 +36,7 @@ const Common::String kClanMusicFiles[] = {"mbf_arb1.mpg", "mbf_arm1.mpg", "mbf_b
"mbf_c3p2.mpg", "mbf_c3p1.mpg", "act25mus.mpg", "mbf_c4p2.mpg", "mbf_c4p1.mpg"};
// Gets the filename of the background music file.
-Common::String ClanGame::getClanMusicFilename(int musicId) {
+const char* ClanGame::getClanMusicFilename(int musicId) {
return kClanMusicFiles[musicId];
}
diff --git a/engines/groovie/clangame.h b/engines/groovie/clangame.h
index 42fba84950..64b131cb65 100644
--- a/engines/groovie/clangame.h
+++ b/engines/groovie/clangame.h
@@ -23,13 +23,11 @@
#ifndef GROOVIE_CLANGAME_H
#define GROOVIE_CLANGAME_H
-#include "common/str.h"
-
namespace Groovie {
class ClanGame {
public:
- static Common::String getClanMusicFilename(int musicId);
+ static const char* getClanMusicFilename(int musicId);
};
} // namespace Groovie
diff --git a/engines/groovie/module.mk b/engines/groovie/module.mk
index a56e6bac57..a3cda1ea29 100644
--- a/engines/groovie/module.mk
+++ b/engines/groovie/module.mk
@@ -18,10 +18,10 @@ MODULE_OBJS := \
ifdef ENABLE_GROOVIE2
MODULE_OBJS += \
+ clangame.o \
roq.o \
- tlcgame.o \
t11hgame.o \
- clangame.o
+ tlcgame.o
endif
# This module can be built as a plugin
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 53042d0676..bb10ec760f 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -751,6 +751,7 @@ bool MusicPlayerIOS::load(uint32 fileref, bool loop) {
MusicPlayerTlc::MusicPlayerTlc(GroovieEngine *vm) : MusicPlayer(vm) {
+ _file = NULL;
vm->getTimerManager()->installTimerProc(&onTimer, 50 * 1000, this, "groovieMusic");
}
@@ -767,6 +768,10 @@ void MusicPlayerTlc::unload() {
MusicPlayer::unload();
_vm->_system->getMixer()->stopHandle(_handle);
+ if (_file) {
+ delete _file;
+ }
+ _file = NULL;
}
Common::String MusicPlayerTlc::getFilename(uint32 fileref) {
@@ -774,18 +779,18 @@ Common::String MusicPlayerTlc::getFilename(uint32 fileref) {
}
bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
- // Find correct filename
- Common::String filename;
- Common::File *fileHandle = new Common::File();
- Audio::SeekableAudioStream *seekStream = NULL;
+ unload();
+ _file = new Common::File();
// Create the audio stream from fileref
- filename = getFilename(fileref);
- fileHandle->open(filename);
- if (fileHandle->isOpen()) {
- seekStream = Audio::makeMP3Stream(fileHandle, DisposeAfterUse::YES);
+ Common::String filename = getFilename(fileref);
+ _file->open(filename);
+ Audio::SeekableAudioStream *seekStream = NULL;
+ if (_file->isOpen()) {
+ seekStream = Audio::makeMP3Stream(_file, DisposeAfterUse::NO);
} else {
- delete fileHandle;
+ delete _file;
+ _file = NULL;
}
if (!seekStream) {
@@ -796,6 +801,9 @@ bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
Audio::AudioStream *audStream = seekStream;
// TODO: Loop if requested
+ if (!loop)
+ warning("TODO: MusicPlayerTlc::load with loop == false");
+
if (loop || 1)
audStream = Audio::makeLoopingAudioStream(seekStream, 0);
diff --git a/engines/groovie/music.h b/engines/groovie/music.h
index b75ad56af1..6c161ae8f3 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -25,6 +25,7 @@
#include "common/array.h"
#include "common/mutex.h"
+#include "common/file.h"
#include "audio/mididrv.h"
#include "audio/mididrv_ms.h"
#include "audio/mixer.h"
@@ -218,6 +219,7 @@ protected:
private:
Audio::SoundHandle _handle;
+ Common::File *_file;
};
class MusicPlayerClan : public MusicPlayerTlc {
diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp
index 048be82457..1f6a0cde11 100644
--- a/engines/groovie/player.cpp
+++ b/engines/groovie/player.cpp
@@ -114,7 +114,7 @@ void VideoPlayer::waitFrame() {
uint32 millisDiff = currTime - _lastFrameTime;
float fMillis = _millisBetweenFrames + _frameTimeDrift;
// use floorf instead of roundf, because delayMillis often slightly over-sleeps
- uint32 millisSleep = fmaxf( 0.0f, floorf(fMillis) - float(millisDiff));
+ uint32 millisSleep = fmaxf(0.0f, floorf(fMillis) - float(millisDiff));
if (millisSleep > 0) {
debugC(7, kDebugVideo, "Groovie::Player: Delaying %d (currTime=%d, _lastFrameTime=%d, millisDiff=%d, _millisBetweenFrame=%.2f, _frameTimeDrift=%.2f)",
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 881bb15696..1e34aad9ee 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -61,25 +61,19 @@ static const int kRIndex = 0;
namespace Groovie {
// Overwrites one pixel of destination regardless of the alpha value
-static inline void copyPixelIfAlpha(byte *dst, byte *src) {
- if (src[kAIndex] > 0) {
- dst[kAIndex] = src[kAIndex];
- dst[kRIndex] = src[kRIndex];
- dst[kGIndex] = src[kGIndex];
- dst[kBIndex] = src[kBIndex];
- }
+static inline void copyPixel(byte *dst, const byte *src) {
+ *(uint32 *)dst = *(const uint32 *)src;
}
- // Overwrites one pixel of destination regardless of the alpha value
-static inline void copyPixel(byte *dst, byte *src) {
- dst[kAIndex] = src[kAIndex];
- dst[kRIndex] = src[kRIndex];
- dst[kGIndex] = src[kGIndex];
- dst[kBIndex] = src[kBIndex];
+// Overwrites one pixel of destination regardless of the alpha value
+static inline void copyPixelIfAlpha(byte *dst, const byte *src) {
+ if (src[kAIndex] > 0) {
+ copyPixel(dst, src);
+ }
}
// Copies one pixel to destination but respects the alpha value of the source
-static inline void copyPixelWithA(byte *dst, byte *src) {
+static inline void copyPixelWithA(byte *dst, const byte *src) {
if (src[kAIndex] == 255) {
copyPixel(dst, src);
} else {
@@ -223,11 +217,15 @@ void ROQPlayer::buildShowBuf() {
if (!_restoreArea->isEmpty()) {
int width = _restoreArea->right - _restoreArea->left;
Graphics::Surface *screen = _vm->_system->lockScreen();
+ assert(screen->format == _bg->format);
+ assert(screen->format.bytesPerPixel == 4);
for (int line = _restoreArea->top; line < _restoreArea->bottom; line++) {
byte *dst = (byte *)screen->getBasePtr(_restoreArea->left, line + screenOffset);
byte *src = (byte *)_bg->getBasePtr(_restoreArea->left, line);
byte *prv = (byte *)_prevBuf->getBasePtr((_restoreArea->left - _origX) / _scaleX, (line - _origY) / _scaleY);
byte *ovr = (byte *)_overBuf->getBasePtr(_restoreArea->left, line);
+
+ //memcpy(dst, src, width * _bg->format.bytesPerPixel);
for (int i = 0; i < width; i++) {
if (prv[kAIndex] != 0) {
copyPixel(dst, src);
@@ -274,17 +272,14 @@ void ROQPlayer::buildShowBuf() {
byte *in = (byte *)_currBuf->getBasePtr(MAX(0, -_origX) / _scaleX, (line - _origY) / _scaleY);
byte *inOvr = (byte *)_overBuf->getBasePtr(startX, line);
byte *out = (byte *)destBuf->getBasePtr(startX, line + destOffset);
+ assert(destBuf->format == _currBuf->format);
+ assert(destBuf->format.bytesPerPixel == 4);
for (int x = startX; x < stopX; x++) {
if (destBuf == _overBuf) {
copyPixelIfAlpha(out, in);
} else {
- if (_interlacedVideo && (line % 2) && 0) {
- byte blackPixel[4] = { 0, 0, 0, 0 };
- copyPixel(out, blackPixel);
- } else {
- copyPixelWithA(out, in);
- }
+ copyPixelWithA(out, in);
}
if (_alpha && in[kAIndex] != 0 && destBuf != _overBuf) {
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 11410f541a..36b8d14103 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -790,7 +790,7 @@ bool Script::playBackgroundSound(uint32 fileref, uint32 loops) {
if (_soundFile) {
_vm->_soundQueue.queue(_soundFile, loops);
} else {
- error("Groovie::Script: Couldn't open file");
+ warning("Groovie::Script: Couldn't open file");
return false;
}
@@ -1155,7 +1155,8 @@ void Script::o_strcmpnejmp_var() { // 0x21
void Script::o_copybgtofg() { // 0x22
debugC(1, kDebugScript, "Groovie::Script: COPY_BG_TO_FG");
debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPY_BG_TO_FG", _currentInstruction - 1);
- memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * _vm->_graphicsMan->_foreground.h * _vm->_graphicsMan->_foreground.format.bytesPerPixel);
+ size_t len = _vm->_graphicsMan->_foreground.pitch * _vm->_graphicsMan->_foreground.h;
+ memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), len);
}
void Script::o2_copybgtofg() { // 0x22
@@ -1889,6 +1890,7 @@ void Script::o2_midicontrol() {
uint16 arg1 = readScript16bits();
uint16 arg2 = readScript16bits();
+ // TODO: see if we need to revisit the commented code here, maybe @Alphard-o can help
switch (arg1) {
case 0:
// Stop Playback
diff --git a/engines/groovie/t11hgame.cpp b/engines/groovie/t11hgame.cpp
index 4cce464673..f2b4c0cc54 100644
--- a/engines/groovie/t11hgame.cpp
+++ b/engines/groovie/t11hgame.cpp
@@ -33,31 +33,6 @@
namespace Groovie {
-/* Links between the pieces in the Gallery challenge */
-byte kGalleryLinks[21][10] = {
- { 2, 4, 5, 0, 0, 0, 0, 0, 0, 0 }, // 1
- { 1, 5, 3, 0, 0, 0, 0, 0, 0, 0 }, // 2
- { 2, 5, 9, 12, 0, 0, 0, 0, 0, 0 }, // 3
- { 1, 5, 6, 7, 8, 0, 0, 0, 0, 0 }, // 4
- { 1, 2, 3, 4, 7, 8, 9, 0, 0, 0 }, // 5
- { 4, 7, 10, 11, 13, 14, 15, 16, 18, 0 }, // 6
- { 4, 5, 6, 8, 9, 10, 0, 0, 0, 0 }, // 7
- { 4, 5, 7, 0, 0, 0, 0, 0, 0, 0 }, // 8
- { 3, 5, 7, 10, 11, 12, 18, 0, 0, 0 }, // 9
- { 6, 7, 9, 11, 0, 0, 0, 0, 0, 0 }, // 10
- { 6, 9, 10, 18, 0, 0, 0, 0, 0, 0 }, // 11
- { 3, 9, 18, 21, 0, 0, 0, 0, 0, 0 }, // 12
- { 6, 14, 17, 19, 0, 0, 0, 0, 0, 0 }, // 13
- { 6, 13, 15, 17, 19, 20, 21, 0, 0, 0 }, // 14
- { 6, 14, 16, 18, 21, 0, 0, 0, 0, 0 }, // 15
- { 6, 15, 0, 0, 0, 0, 0, 0, 0, 0 }, // 16
- {13, 14, 19, 0, 0, 0, 0, 0, 0, 0 }, // 17
- { 6, 9, 11, 12, 15, 21, 0, 0, 0, 0 }, // 18
- {13, 14, 17, 20, 0, 0, 0, 0, 0, 0 }, // 19
- {14, 19, 21, 0, 0, 0, 0, 0, 0, 0 }, // 20
- {12, 14, 15, 18, 20, 0, 0, 0, 0, 0 } // 21
-};
-
T11hGame::T11hGame() :
_random("GroovieT11hGame"), _scriptVariables(NULL) {
}
@@ -151,6 +126,32 @@ void T11hGame::opPente() {
* | | 20/2D | 21/2E |
* +-----------+--------+-----------------------------------------+
*/
+
+/* Links between the pieces in the Gallery challenge */
+const byte T11hGame::kGalleryLinks[21][10] = {
+ { 2, 4, 5, 0, 0, 0, 0, 0, 0, 0 }, // 1
+ { 1, 5, 3, 0, 0, 0, 0, 0, 0, 0 }, // 2
+ { 2, 5, 9, 12, 0, 0, 0, 0, 0, 0 }, // 3
+ { 1, 5, 6, 7, 8, 0, 0, 0, 0, 0 }, // 4
+ { 1, 2, 3, 4, 7, 8, 9, 0, 0, 0 }, // 5
+ { 4, 7, 10, 11, 13, 14, 15, 16, 18, 0 }, // 6
+ { 4, 5, 6, 8, 9, 10, 0, 0, 0, 0 }, // 7
+ { 4, 5, 7, 0, 0, 0, 0, 0, 0, 0 }, // 8
+ { 3, 5, 7, 10, 11, 12, 18, 0, 0, 0 }, // 9
+ { 6, 7, 9, 11, 0, 0, 0, 0, 0, 0 }, // 10
+ { 6, 9, 10, 18, 0, 0, 0, 0, 0, 0 }, // 11
+ { 3, 9, 18, 21, 0, 0, 0, 0, 0, 0 }, // 12
+ { 6, 14, 17, 19, 0, 0, 0, 0, 0, 0 }, // 13
+ { 6, 13, 15, 17, 19, 20, 21, 0, 0, 0 }, // 14
+ { 6, 14, 16, 18, 21, 0, 0, 0, 0, 0 }, // 15
+ { 6, 15, 0, 0, 0, 0, 0, 0, 0, 0 }, // 16
+ {13, 14, 19, 0, 0, 0, 0, 0, 0, 0 }, // 17
+ { 6, 9, 11, 12, 15, 21, 0, 0, 0, 0 }, // 18
+ {13, 14, 17, 20, 0, 0, 0, 0, 0, 0 }, // 19
+ {14, 19, 21, 0, 0, 0, 0, 0, 0, 0 }, // 20
+ {12, 14, 15, 18, 20, 0, 0, 0, 0, 0 } // 21
+};
+
void T11hGame::opGallery() {
byte field1[21];
@@ -224,6 +225,7 @@ void T11hGame::opGallery() {
byte T11hGame::opGallerySub(int one, byte* field) {
// TODO
+ warning("STUB: T11hGame::opGallerySub()");
return 0;
}
diff --git a/engines/groovie/t11hgame.h b/engines/groovie/t11hgame.h
index e930dab634..897cda2486 100644
--- a/engines/groovie/t11hgame.h
+++ b/engines/groovie/t11hgame.h
@@ -30,8 +30,7 @@ namespace Groovie {
class GroovieEngine;
-class T11hGame
-{
+class T11hGame {
public:
T11hGame();
~T11hGame();
@@ -55,7 +54,7 @@ private:
void inline setScriptVar16(uint16 var, uint16 value);
uint16 inline getScriptVar16(uint16 var);
byte *_scriptVariables;
-
+ static const byte kGalleryLinks[21][10];
};
} // End of Groovie namespace
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
index 916a95f8af..d2a241595b 100644
--- a/engines/groovie/tlcgame.cpp
+++ b/engines/groovie/tlcgame.cpp
@@ -34,7 +34,12 @@
namespace Groovie {
// This a list of files for background music. These list is hard-coded in the TLC player.
-const Common::String kTlcMusicFiles[] = {"ep01epm.mpg", "ep01tatm.mpg", "amb_hs.mpg", "amb_mr.mpg", "amb_kr.mpg", "amb_mo.mpg", "music_rc.mpg", "amb_ds.mpg", "amb_ds3.mpg", "amb_jr.mpg", "amb_mr4.mpg", "amb_jr4.mpg", "amb_jr2.mpg", "amb_kr2.mpg", "amb_mr2.mpg", "amb_br.mpg", "amb_ds2.mpg", "amb_jr3.mpg", "amb_ds4.mpg", "amb_kr3.mpg", "amb_to1.mpg", "amb_to2.mpg", "ep02epm.mpg", "ep02tatm.mpg", "ep03epm.mpg", "ep03tatm.mpg", "ep04epm.mpg", "ep04tatm.mpg", "ep05epm.mpg", "ep05tatm.mpg", "ep06epm.mpg", "ep06tatm.mpg", "ep07epm.mpg", "ep07tatm.mpg", "ep08epm.mpg", "ep08tatm.mpg", "ep09epm.mpg", "ep09tatm.mpg", "ep10epm.mpg", "ep10tatm.mpg", "ep11epm.mpg", "ep11tatm.mpg", "ep12epm.mpg", "ep12tatm.mpg", "ep13epm.mpg", "ep13tatm.mpg", "ep14epm.mpg", "ep14tatm.mpg", "ep15epm.mpg", "ep15tatm.mpg" };
+const char * kTlcMusicFiles[] = {"ep01epm.mpg", "ep01tatm.mpg", "amb_hs.mpg", "amb_mr.mpg", "amb_kr.mpg", "amb_mo.mpg", "music_rc.mpg", "amb_ds.mpg", "amb_ds3.mpg",
+ "amb_jr.mpg", "amb_mr4.mpg", "amb_jr4.mpg", "amb_jr2.mpg", "amb_kr2.mpg", "amb_mr2.mpg", "amb_br.mpg", "amb_ds2.mpg", "amb_jr3.mpg",
+ "amb_ds4.mpg", "amb_kr3.mpg", "amb_to1.mpg", "amb_to2.mpg", "ep02epm.mpg", "ep02tatm.mpg", "ep03epm.mpg", "ep03tatm.mpg", "ep04epm.mpg",
+ "ep04tatm.mpg", "ep05epm.mpg", "ep05tatm.mpg", "ep06epm.mpg", "ep06tatm.mpg", "ep07epm.mpg", "ep07tatm.mpg", "ep08epm.mpg", "ep08tatm.mpg",
+ "ep09epm.mpg", "ep09tatm.mpg", "ep10epm.mpg", "ep10tatm.mpg", "ep11epm.mpg", "ep11tatm.mpg", "ep12epm.mpg", "ep12tatm.mpg", "ep13epm.mpg",
+ "ep13tatm.mpg", "ep14epm.mpg", "ep14tatm.mpg", "ep15epm.mpg", "ep15tatm.mpg" };
const uint8 kTlcEpQuestToPlay[] = { 0x0E, 0x0F, 0x0B, 0x10, 0x11, 0x12, 0x0C, 0x0C, 0x09, 0x06, 0x0F, 0x0C, 0x0B, 0x0D, 0x0D };
@@ -79,7 +84,7 @@ uint16 inline TlcGame::getScriptVar16(uint16 var) {
}
// Gets the filename of the background music file.
-Common::String TlcGame::getTlcMusicFilename(int musicId) {
+const char* TlcGame::getTlcMusicFilename(int musicId) {
return kTlcMusicFiles[musicId];
}
@@ -139,37 +144,33 @@ void TlcGame::regionsInit() {
// Loads the specific regions for one questions.
void TlcGame::regionsLoad() {
- Common::SeekableReadStream *regionsfile = 0;
- int nameLen;
- int i;
- char questName[sizeof(TlcRegionsHeader::name)];
-
// Check if initRegions was called before
if (_regionHeader == NULL) {
error("TLC:RegionsLoad: initRegions was not called.");
}
// Open regions.rle
- regionsfile = SearchMan.createReadStreamForMember("SYSTEM/REGIONS.RLE");
+ Common::SeekableReadStream *regionsfile = SearchMan.createReadStreamForMember("SYSTEM/REGIONS.RLE");
if (!regionsfile) {
error("TLC:RegionsLoad: Could not open 'SYSTEM/REGIONS.RLE'");
}
// Get length of question name from variables
- nameLen = _scriptVariables[0x1B] * 10 + _scriptVariables[0x1C];
+ int nameLen = _scriptVariables[0x1B] * 10 + _scriptVariables[0x1C];
if (nameLen >= sizeof(TlcRegionsHeader::name)) {
error("TLC:RegionsLoad: Name to long for loadRegions!");
}
// Decoded and copy name from variables
- for (i = 0; i < nameLen; i++) {
+ char questName[sizeof(TlcRegionsHeader::name)];
+ for (int i = 0; i < nameLen; i++) {
setScriptVar(0x1D + i, _scriptVariables[0x1D + i] + 0x30);
questName[i] = _scriptVariables[0x1D + i];
}
- questName[i] = '\0';
+ questName[nameLen] = '\0';
// Search for the question entry
- for (i = 0; i <= _numRegionHeaders; i++) {
+ for (int i = 0; i <= _numRegionHeaders; i++) {
if (strcmp(questName, _regionHeader[i].name) == 0) {
// move to coordinates for this question
@@ -630,28 +631,21 @@ void TlcGame::epResultEpisode() {
/* Select next stream according to which bin(s) are still >0. */
if (_epScoreBin[1] != 0 && _epScoreBin[2] == 0 && _epScoreBin[3] == 0) {
setScriptVar(3, 1);
- }
- else if (_epScoreBin[1] == 0 && _epScoreBin[2] != 0 && _epScoreBin[3] == 0) {
+ } else if (_epScoreBin[1] == 0 && _epScoreBin[2] != 0 && _epScoreBin[3] == 0) {
setScriptVar(3, 2);
- }
- else if (_epScoreBin[1] == 0 && _epScoreBin[2] == 0 && _epScoreBin[3] != 0) {
+ } else if (_epScoreBin[1] == 0 && _epScoreBin[2] == 0 && _epScoreBin[3] != 0) {
setScriptVar(3, 3);
- }
- else if (_epScoreBin[1] != 0 && _epScoreBin[2] != 0 && _epScoreBin[3] == 0) {
+ } else if (_epScoreBin[1] != 0 && _epScoreBin[2] != 0 && _epScoreBin[3] == 0) {
setScriptVar(3, _random.getRandomNumberRng(1, 2));
- }
- else if (_epScoreBin[1] != 0 && _epScoreBin[2] == 0 && _epScoreBin[3] != 0) {
+ } else if (_epScoreBin[1] != 0 && _epScoreBin[2] == 0 && _epScoreBin[3] != 0) {
setScriptVar(3, (_random.getRandomNumberRng(0, 1) * 2) + 1);
- }
- else if (_epScoreBin[1] == 0 && _epScoreBin[2] != 0 && _epScoreBin[3] != 0) {
+ } else if (_epScoreBin[1] == 0 && _epScoreBin[2] != 0 && _epScoreBin[3] != 0) {
setScriptVar(3, _random.getRandomNumberRng(2, 3));
- }
- else if (_epScoreBin[1] != 0 && _epScoreBin[2] != 0 && _epScoreBin[3] != 0) {
+ } else if (_epScoreBin[1] != 0 && _epScoreBin[2] != 0 && _epScoreBin[3] != 0) {
setScriptVar(3, _random.getRandomNumberRng(1, 3));
- }
- else {
+ } else {
error("Tlc:EpResultEpisode: Stream selection failed. bins[0..5] = %d, %d, %d, %d, %d, %d",
- _epScoreBin[0], _epScoreBin[1], _epScoreBin[2], _epScoreBin[3], _epScoreBin[4], _epScoreBin[5]);
+ _epScoreBin[0], _epScoreBin[1], _epScoreBin[2], _epScoreBin[3], _epScoreBin[4], _epScoreBin[5]);
}
debugC(1, kDebugTlcGame, "Selected stream [1..3] = %d ", _scriptVariables[3]);
@@ -701,26 +695,11 @@ void TlcGame::opFlags() {
_tatFlags[x][y] = 1;
debugC(1, kDebugTlcGame, "Tlc:TatFlags: Set x=%d, y=%d to 1", x, y);
- debugC(5, kDebugTlcGame, "Tlc:TatFlags: %d%d%d%d%d%d%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d%d%d%d%d%d%d",
- _tatFlags[0][0], _tatFlags[1][0], _tatFlags[2][0], _tatFlags[ 3][0], _tatFlags[ 4][0], _tatFlags[ 5][0], _tatFlags[ 6][0],
- _tatFlags[7][0], _tatFlags[8][0], _tatFlags[9][0], _tatFlags[10][0], _tatFlags[11][0], _tatFlags[12][0], _tatFlags[13][0],
- _tatFlags[0][1], _tatFlags[1][1], _tatFlags[2][1], _tatFlags[ 3][1], _tatFlags[ 4][1], _tatFlags[ 5][1], _tatFlags[ 6][1],
- _tatFlags[7][1], _tatFlags[8][1], _tatFlags[9][1], _tatFlags[10][1], _tatFlags[11][1], _tatFlags[12][1], _tatFlags[13][1]);
- debugC(5, kDebugTlcGame, "Tlc:TatFlags: %d%d%d%d%d%d%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d%d%d%d%d%d%d",
- _tatFlags[0][2], _tatFlags[1][2], _tatFlags[2][2], _tatFlags[ 3][2], _tatFlags[ 4][2], _tatFlags[ 5][2], _tatFlags[ 6][2],
- _tatFlags[7][2], _tatFlags[8][2], _tatFlags[9][2], _tatFlags[10][2], _tatFlags[11][2], _tatFlags[12][2], _tatFlags[13][2],
- _tatFlags[0][3], _tatFlags[1][3], _tatFlags[2][3], _tatFlags[ 3][3], _tatFlags[ 4][3], _tatFlags[ 5][3], _tatFlags[ 6][3],
- _tatFlags[7][3], _tatFlags[8][3], _tatFlags[9][3], _tatFlags[10][3], _tatFlags[11][3], _tatFlags[12][3], _tatFlags[13][3]);
- debugC(5, kDebugTlcGame, "Tlc:TatFlags: %d%d%d%d%d%d%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d%d%d%d%d%d%d",
- _tatFlags[0][4], _tatFlags[1][4], _tatFlags[2][4], _tatFlags[ 3][4], _tatFlags[ 4][4], _tatFlags[ 5][4], _tatFlags[ 6][4],
- _tatFlags[7][4], _tatFlags[8][4], _tatFlags[9][4], _tatFlags[10][4], _tatFlags[11][4], _tatFlags[12][4], _tatFlags[13][4],
- _tatFlags[0][5], _tatFlags[1][5], _tatFlags[2][5], _tatFlags[ 3][5], _tatFlags[ 4][5], _tatFlags[ 5][5], _tatFlags[ 6][5],
- _tatFlags[7][5], _tatFlags[8][5], _tatFlags[9][5], _tatFlags[10][5], _tatFlags[11][5], _tatFlags[12][5], _tatFlags[13][5]);
- debugC(5, kDebugTlcGame, "Tlc:TatFlags: %d%d%d%d%d%d%d%d%d%d%d%d%d%d %d%d%d%d%d%d%d%d%d%d%d%d%d%d",
- _tatFlags[0][6], _tatFlags[1][6], _tatFlags[2][6], _tatFlags[ 3][6], _tatFlags[ 4][6], _tatFlags[ 5][6], _tatFlags[ 6][6],
- _tatFlags[7][6], _tatFlags[8][6], _tatFlags[9][6], _tatFlags[10][6], _tatFlags[11][6], _tatFlags[12][6], _tatFlags[13][6],
- _tatFlags[0][7], _tatFlags[1][7], _tatFlags[2][7], _tatFlags[ 3][7], _tatFlags[ 4][7], _tatFlags[ 5][7], _tatFlags[ 6][7],
- _tatFlags[7][7], _tatFlags[8][7], _tatFlags[9][7], _tatFlags[10][7], _tatFlags[11][7], _tatFlags[12][7], _tatFlags[13][7]);
+
+ debugTatFlags(0, 1);
+ debugTatFlags(2, 3);
+ debugTatFlags(4, 5);
+ debugTatFlags(6, 7);
}
else {
setScriptVar(0x01, 1);
@@ -730,6 +709,21 @@ void TlcGame::opFlags() {
}
+void TlcGame::debugTatFlags(int y, int y2) {
+ Common::String s = "Tlc:TatFlags: ";
+ for (int x = 0; x < 14; x++) {
+ s += int(_tatFlags[x][y]);
+ }
+ y = y2;
+ s += " ";
+ for (int x = 0; x < 14; x++) {
+ s += int(_tatFlags[x][y]);
+ }
+
+ debugC(5, kDebugTlcGame, s.c_str());
+}
+
+
void TlcGame::opTat() {
switch (_scriptVariables[0x40]) {
case 1:
@@ -761,9 +755,7 @@ void TlcGame::opTat() {
void TlcGame::tatInitRegs() {
- int i;
-
- for (i = 0; i < 0x10; i++) {
+ for (int i = 0; i < 0x10; i++) {
setScriptVar(0x4D + i, 0);
setScriptVar16(0x5D + i*2, 0);
}
diff --git a/engines/groovie/tlcgame.h b/engines/groovie/tlcgame.h
index e937d12a7f..09c76cae80 100644
--- a/engines/groovie/tlcgame.h
+++ b/engines/groovie/tlcgame.h
@@ -74,7 +74,7 @@ public:
TlcGame();
~TlcGame();
- static Common::String getTlcMusicFilename(int musicId);
+ static const char* getTlcMusicFilename(int musicId);
/**
* Sets a pointer to the script variables. This makes it easier if we want
@@ -182,6 +182,7 @@ private:
void tatResultQuest();
void tatResultEpisode();
void tatGetProfile();
+ void debugTatFlags(int y, int y2);
// Variables for TAT handling
int _tatEpisodes;
Commit: bb7975e719fb41502a8a0b9230b11eb5012d9f34
https://github.com/scummvm/scummvm/commit/bb7975e719fb41502a8a0b9230b11eb5012d9f34
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix crash when skipping many short sounds
Not cleaning up the sounds meant skipping through them too quickly would cause the mixer to run out of channels.
Changed paths:
engines/groovie/vdx.cpp
engines/groovie/vdx.h
diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp
index c224bb47aa..8cc37a657c 100644
--- a/engines/groovie/vdx.cpp
+++ b/engines/groovie/vdx.cpp
@@ -57,6 +57,9 @@ void VDXPlayer::setOrigin(int16 x, int16 y) {
}
void VDXPlayer::stopAudioStream() {
+ if (_audioStream) {
+ g_system->getMixer()->stopHandle(_soundHandle);
+ }
_audioStream = NULL;
}
@@ -534,8 +537,7 @@ void VDXPlayer::chunkSound(Common::ReadStream *in) {
if (!_audioStream && !isFastForwarding()) {
_audioStream = Audio::makeQueuingAudioStream(22050, false);
- Audio::SoundHandle sound_handle;
- g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &sound_handle, _audioStream);
+ g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle, _audioStream);
}
byte *data = (byte *)malloc(60000);
diff --git a/engines/groovie/vdx.h b/engines/groovie/vdx.h
index 27f84745de..c6515cd741 100644
--- a/engines/groovie/vdx.h
+++ b/engines/groovie/vdx.h
@@ -24,6 +24,7 @@
#define GROOVIE_VDX_H
#include "groovie/player.h"
+#include "audio/mixer.h"
namespace Common {
class ReadStream;
@@ -46,6 +47,7 @@ protected:
private:
Graphics::Surface *_fg, *_bg;
uint8 _palBuf[3 * 256];
+ Audio::SoundHandle _soundHandle;
// Origin
int16 _origX, _origY;
Commit: cfd928f296cb03d874870b457ad744988666050a
https://github.com/scummvm/scummvm/commit/cfd928f296cb03d874870b457ad744988666050a
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: cleanup signed/unsigned compiler warnings
Changed paths:
engines/groovie/groovie.cpp
engines/groovie/script.cpp
engines/groovie/script.h
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index db3ec6545b..530ec971b4 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -450,7 +450,7 @@ void SoundEffectQueue::queue(Common::SeekableReadStream *soundfile, uint32 loops
stopAll();
}
_queue.push({soundfile, loops});
- for (int i = 1; i < loops; i++) {
+ for (uint32 i = 1; i < loops; i++) {
_queue.push({soundfile, loops});
}
tick();
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 36b8d14103..5154abc446 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -69,7 +69,7 @@ const byte t7gMidiInitScript[] = {
Script::Script(GroovieEngine *vm, EngineVersion version) :
_code(NULL), _savedCode(NULL), _stacktop(0), _debugger(NULL), _vm(vm),
- _videoFile(NULL), _videoRef(-1), _staufsMove(NULL), _lastCursor(0xff),
+ _videoFile(NULL), _videoRef(UINT32_MAX), _staufsMove(NULL), _lastCursor(0xff),
_version(version), _random("GroovieScripts"), _tlcGame(0), _t11hGame(0) {
// Initialize the opcode set depending on the engine version
@@ -696,7 +696,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
// Close the previous video file
if (_videoFile) {
- _videoRef = -1;
+ _videoRef = UINT32_MAX;
delete _videoFile;
}
@@ -755,7 +755,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
// Close the file
delete _videoFile;
_videoFile = NULL;
- _videoRef = -1;
+ _videoRef = UINT32_MAX;
// Clear the input events while playing the video
_eventMouseClicked = 0;
diff --git a/engines/groovie/script.h b/engines/groovie/script.h
index f7a9079bb9..1e32650c22 100644
--- a/engines/groovie/script.h
+++ b/engines/groovie/script.h
@@ -122,7 +122,7 @@ private:
// Video
Common::SeekableReadStream *_videoFile;
- int32 _videoRef;
+ uint32 _videoRef;
uint16 _bitflags;
uint16 _videoSkipAddress;
Commit: 02ade73150e7762a77714b933ae9010c8c3af2ac
https://github.com/scummvm/scummvm/commit/02ade73150e7762a77714b933ae9010c8c3af2ac
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix compiler errors and warnings
Changed paths:
engines/groovie/script.cpp
engines/groovie/tlcgame.cpp
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 5154abc446..27aa8a1720 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -69,7 +69,7 @@ const byte t7gMidiInitScript[] = {
Script::Script(GroovieEngine *vm, EngineVersion version) :
_code(NULL), _savedCode(NULL), _stacktop(0), _debugger(NULL), _vm(vm),
- _videoFile(NULL), _videoRef(UINT32_MAX), _staufsMove(NULL), _lastCursor(0xff),
+ _videoFile(NULL), _videoRef(UINT_MAX), _staufsMove(NULL), _lastCursor(0xff),
_version(version), _random("GroovieScripts"), _tlcGame(0), _t11hGame(0) {
// Initialize the opcode set depending on the engine version
@@ -696,7 +696,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
// Close the previous video file
if (_videoFile) {
- _videoRef = UINT32_MAX;
+ _videoRef = UINT_MAX;
delete _videoFile;
}
@@ -755,7 +755,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
// Close the file
delete _videoFile;
_videoFile = NULL;
- _videoRef = UINT32_MAX;
+ _videoRef = UINT_MAX;
// Clear the input events while playing the video
_eventMouseClicked = 0;
@@ -780,7 +780,7 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
}
bool Script::playBackgroundSound(uint32 fileref, uint32 loops) {
- if (fileref == -1) {
+ if (fileref == UINT_MAX) {
return false;
}
@@ -861,7 +861,7 @@ void Script::o_hotspot_rect() {
// TLC: The regions for many questions are in an extra database
if (_version == kGroovieTLC && left == 0 && top == 0 && right == 0 && bottom == 0 && _tlcGame != NULL) {
if (_tlcGame->getRegionNext(left, top, right, bottom) < 0) {
- debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-RECT(x,x,x,x) @0x%04X cursor=%d SKIPPED", left, top, right, bottom, address, cursor);
+ debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d SKIPPED", left, top, right, bottom, address, cursor);
return;
}
}
@@ -1695,7 +1695,6 @@ void Script::o_setvideoorigin() {
_bitflags |= 1 << 7;
debugC(1, kDebugScript, "Groovie::Script: SetVideoOrigin(0x%04X,0x%04X) (%d, %d)", origX, origY, origX, origY);
- debugC(1, kDebugVideo, "Groovie::Script: SetVideoOrigin(0x % 04X, 0x % 04X) (%d, %d)", origX, origY, origX, origY);
_vm->_videoPlayer->setOrigin(origX, origY);
}
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
index d2a241595b..214cc92300 100644
--- a/engines/groovie/tlcgame.cpp
+++ b/engines/groovie/tlcgame.cpp
@@ -671,7 +671,7 @@ void TlcGame::opFlags() {
_tatFlags[x][y] = 0;
}
}
- debugC(1, kDebugTlcGame, "Tlc:TatFlags: Initialized fields", x, y);
+ debugC(1, kDebugTlcGame, "Tlc:TatFlags: Initialized fields (%d, %d)", x, y);
break;
// Get and set flags
@@ -709,18 +709,14 @@ void TlcGame::opFlags() {
}
-void TlcGame::debugTatFlags(int y, int y2) {
- Common::String s = "Tlc:TatFlags: ";
+void TlcGame::debugTatFlags(int y1, int y2) {
+ Common::String s1, s2;
for (int x = 0; x < 14; x++) {
- s += int(_tatFlags[x][y]);
- }
- y = y2;
- s += " ";
- for (int x = 0; x < 14; x++) {
- s += int(_tatFlags[x][y]);
+ s1 += int(_tatFlags[x][y1]);
+ s2 += int(_tatFlags[x][y2]);
}
- debugC(5, kDebugTlcGame, s.c_str());
+ debugC(5, kDebugTlcGame, "Tlc:TatFlags: %s %s", s1.c_str(), s2.c_str());
}
Commit: 1687b7f08b1bc26ce9a969016af098eb4d8c1361
https://github.com/scummvm/scummvm/commit/1687b7f08b1bc26ce9a969016af098eb4d8c1361
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix error missing limits.h
Changed paths:
engines/groovie/script.cpp
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 27aa8a1720..7bd9709cf7 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -20,6 +20,8 @@
*
*/
+#include <limits.h>
+
#include "audio/mididrv.h"
#include "groovie/script.h"
Commit: 6822711c916745b214ff7df727a230ef9152b73b
https://github.com/scummvm/scummvm/commit/6822711c916745b214ff7df727a230ef9152b73b
Author: Die4Ever (30947252+Die4Ever at users.noreply.github.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: T11H mouse trap WIP
more properly initializes the board which also avoids graphical bugs
started to document different arguments
Changed paths:
engines/groovie/t11hgame.cpp
diff --git a/engines/groovie/t11hgame.cpp b/engines/groovie/t11hgame.cpp
index f2b4c0cc54..cebc38ad79 100644
--- a/engines/groovie/t11hgame.cpp
+++ b/engines/groovie/t11hgame.cpp
@@ -63,12 +63,44 @@ void T11hGame::opMouseTrap() {
// variable 24 is the mouse?
//_scriptVariables[24] = 2;
- // value of 0 is V, 1 is <, 2 is ^, 3 is >
- // variable 23 is the outside piece
- _scriptVariables[23] = 1;
- // variable slot is the space number + 25, the left corner (Stauf's goal) is space 1, above that is space 2, the center is 13, and the right corner (goal) is space 25
- for (int i = 27; i <= 49; i++) {
- _scriptVariables[i] = 3;
+ switch (_scriptVariables[2]) {
+ case 0:
+ warning("mouse trap _scriptVariables[2] is 0 not implemented yet");
+ break;
+ case 1: // init board
+ // value of 0 is V, 1 is <, 2 is ^, 3 is >
+ // variable 23 is the outside piece
+ _scriptVariables[23] = _random.getRandomNumber(3);
+ // variable slot is the space number + 25, the left corner (Stauf's goal) is space 1, above that is space 2, the center is 13, and the right corner (goal) is space 25
+ for (int i = 27; i <= 49; i++) {
+ _scriptVariables[i] = _random.getRandomNumber(3);
+ }
+ break;
+ case 2: // before player choose move floor, set the banned move
+ {
+ int clicked = int(_scriptVariables[0]) * 5 + int(_scriptVariables[1]) + 1;
+ _scriptVariables[clicked + 50] = 0;
+ break;
+ }
+ case 3: // after player moving floor
+ // a bunch of hardcoded conditionals to copy variables and set the banned move
+ // this probably also sets a variable to allow the player to move the mouse, and checks for win/lose
+ break;
+ case 4: // 4 is not in the switch/case according to Ghidra
+ warning("mouse trap _scriptVariables[2] is 4? this shouldn't happen");
+ break;
+ case 5: // maybe player moving mouse
+ break;
+ case 6: // Stauf moving floor?
+ break;
+ case 7: // maybe Stauf moving mouse
+ break;
+ case 8: // samantha making a move
+ break;
+
+ default:
+ warning((Common::String("mouse trap _scriptVariables[2] is ") + int(_scriptVariables[2]) + "? this shouldn't happen").c_str());
+ break;
}
}
Commit: f3337a4cd2ae4c73db357814570abcad6d37433e
https://github.com/scummvm/scummvm/commit/f3337a4cd2ae4c73db357814570abcad6d37433e
Author: Die4Ever (30947252+Die4Ever at users.noreply.github.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: cleanup detection.cpp
cleaning up detection.cpp by removing all references to the disk.1 file and using AD_ENTRY2s
for Groovie v2 games, make sure to search for a file in the GROOVIE folder and also a file in the MEDIA folder, in order to ensure the user is adding the root game directory and not a subfolder, this also ensures that Mass Add Games works correctly without broken duplicates
also improved the error message in resource.cpp for when a file from a different disk is not found
Changed paths:
engines/groovie/detection.cpp
engines/groovie/detection.h
engines/groovie/groovie.cpp
engines/groovie/resource.cpp
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 943d6b4d4f..ce3bb43b1f 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -67,7 +67,7 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS,
GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
- kGroovieT7G, 0
+ kGroovieT7G
},
// The 7th Guest Mac English
@@ -78,266 +78,124 @@ static const GroovieGameDescription gameDescriptions[] = {
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK,
GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
- kGroovieT7G, 0
+ kGroovieT7G
},
-#if 0
- // These entries should now be identical to the first T7G Mac entry after
- // changing the app to only use the data part of the resource fork. They
- // are left disabled here as a reference.
-
- // The 7th Guest Mac English (Aztec single disc)
- {
- {
- "t7g", "",
- AD_ENTRY1s("T7GMac", "6bdee8d0f9eef6d58d02fcd7deec3fb2", 1830783),
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK,
- GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
- },
- kGroovieT7G, 0
- },
-
- // The 7th Guest Mac English (Aztec bundle, provided by Thefinaleofseem)
- {
- {
- "t7g", "",
- AD_ENTRY1s("T7GMac", "0d595d4b44ae1814082938d051e5174e", 1830783),
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK,
- GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
- },
- kGroovieT7G, 0
- },
-#endif
-
// The 7th Guest DOS Russian (Akella)
{
{
"t7g", "",
- {
- { "script.grv", 0, "d1b8033b40aa67c076039881eccce90d", 16659},
- { "intro.gjd", 0, NULL, 31711554},
- AD_LISTEND
- },
+ AD_ENTRY2s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659,
+ "intro.gjd", NULL, 31711554),
Common::RU_RUS, Common::kPlatformDOS, ADGF_NO_FLAGS,
GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
- kGroovieT7G, 0
+ kGroovieT7G
},
+ // The 7th Guest iOS English
{
{
"t7g", "",
- {
- { "script.grv", 0, "d1b8033b40aa67c076039881eccce90d", 16659},
- { "SeventhGuest", 0, NULL, -1},
- AD_LISTEND
- },
+ AD_ENTRY2s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659,
+ "SeventhGuest", NULL, -1),
Common::EN_ANY, Common::kPlatformIOS, ADGF_NO_FLAGS,
GUIO4(GUIO_NOMIDI, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
- kGroovieT7G, 0
+ kGroovieT7G
},
- // The 11th Hour DOS English
- {
- {
- "11h", "CD-ROM",
- AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
- },
- kGroovieT11H, 1
- },
-
- {
- {
- "11h", "deu",
- AD_ENTRY1s("disk.1", "3d5133fc457e80b80591086dce283792", 76),
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
- },
- kGroovieT11H, 1
- },
-
- // The 11th Hour Macintosh English
- {
- {
- "11h", "",
- AD_ENTRY1s("disk.1", "4c1d0549f544f052fba2b7a9aebd1077", 220),
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
- },
- kGroovieT11H, 1
- },
-
- // The 11th Hour Macintosh English
+ // The 11th Hour DOS/Windows English (Available on Steam)
{
{
"11h", "",
- AD_ENTRY2s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227,
- "The 11th Hour Installer", "bcdb4040b27f15b18f39fb9e496d384a", 1002987),
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
- },
- kGroovieT11H, 1
- },
-
- // The 11th Hour Macintosh English (Installed)
- {
- {
- "11h", "Installed",
- AD_ENTRY2s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227,
- "el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
- },
- kGroovieT11H, 1
- },
-
- // The 11th Hour Windows English (Available on Steam)
- {
- {
- "11h", "Digital",
- {
- { "disk.1", 0, "4c1d0549f544f052fba2b7a9aebd1077", 220},
- { 0, 0, 0, 0 }
- },
+ AD_ENTRY2s("script.grv", "bdb9a783d4debe477ac3856adc454c17", 62447,
+ "introd1.gjd", NULL, -1),
Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
- kGroovieT11H, 1
+ kGroovieT11H
},
- // The 11th Hour DOS Demo English
- {
- {
- "11h", "Demo",
- AD_ENTRY1s("disk.1", "aacb32ce07e0df2894bd83a3dee40c12", 70),
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE,
- GUIO5(GUIO_NOLAUNCHLOAD, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
- },
- kGroovieT11H, 1
- },
-
- // The Making of The 11th Hour DOS English
+ // The Making of The 11th Hour English
{
{
"11h", "Making Of",
- AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
+ AD_ENTRY2s("makingof.grv", "12e1e5eef2c7a9536cd12ac800b31408", 994,
+ "atpuz.gjd", NULL, -1),
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
},
- kGroovieT11H, 2
+ kGroovieT11H
},
- // The Making of The 11th Hour Macintosh English
- {
- {
- "11h", "Making Of",
- AD_ENTRY2s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227,
- "The 11th Hour Installer", "bcdb4040b27f15b18f39fb9e496d384a", 1002987),
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
- },
- kGroovieT11H, 2
- },
-
- // The Making of The 11th Hour Macintosh English (Installed)
- {
- {
- "11h", "Making Of (Installed)",
- AD_ENTRY2s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227,
- "el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
- },
- kGroovieT11H, 2
- },
-
- // Clandestiny Trailer DOS English
+ // Clandestiny Trailer English
{
{
"clandestiny", "Trailer",
- AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227),
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
+ AD_ENTRY2s("trailer.grv", "a7c8bdc4e8bff621f4f50928a95eaaba", 6,
+ "atpuz.gjd", NULL, -1),
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
},
- kGroovieCDY, 3
+ kGroovieCDY
},
- // Clandestiny Trailer Macintosh English
+ // Clandestiny PC English
{
{
- "clandestiny", "Trailer",
- AD_ENTRY2s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227,
- "The 11th Hour Installer", "bcdb4040b27f15b18f39fb9e496d384a", 1002987),
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
- },
- kGroovieCDY, 3
- },
-
- // Clandestiny Trailer Macintosh English (Installed)
- {
- {
- "clandestiny", "Trailer (Installed)",
- AD_ENTRY2s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227,
- "el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
- Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
- GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ "clandestiny", "",
+ AD_ENTRY2s("clanmain.grv", "dd424120fa1daa9d6b576d0ba22a4936", 54253,
+ "ACT01MUS.MPG", NULL, -1),
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
+ GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
},
- kGroovieCDY, 3
+ kGroovieCDY
},
- // Clandestiny DOS English
+ // Clandestiny iOS English
{
{
"clandestiny", "",
- AD_ENTRY1s("disk.1", "f79fc1515174540fef6a34132efc4c53", 76),
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
- GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
+ AD_ENTRY2s("clanmain.grv", "dd424120fa1daa9d6b576d0ba22a4936", 54253,
+ "ACT01MUS.m4a", NULL, -1),
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
+ GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
},
- kGroovieCDY, 1
+ kGroovieCDY
},
// Uncle Henry's Playhouse PC English
{
{
"unclehenry", "",
- AD_ENTRY1s("disk.1", "0e1b1d3cecc4fc7efa62a968844d1f7a", 72),
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
+ AD_ENTRY2s("tpot.grv", "849dc7e5309e1b9acf72d8abc9e145df", 11693,
+ "trt7g.gjd", NULL, -1),
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
},
- kGroovieUHP, 1
+ kGroovieUHP
},
// Tender Loving Care PC English
{
{
"tlc", "",
- AD_ENTRY1s("disk.1", "32a1afa68478f1f9d2b25eeea427f2e3", 84),
- Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE,
- GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
- },
- kGroovieTLC, 1
- },
-
- // Tender Loving Care PC Deutsch
- {
- {
- "tlc", "deu",
- AD_ENTRY1s("disk.1", "07fd3381128b0035a72d41548241c82b", 77),
- Common::DE_DEU, Common::kPlatformDOS, ADGF_UNSTABLE,
+ AD_ENTRY2s("tlcmain.grv", "47c235155de5103e72675fe7294720b8", 17479,
+ "tlcnav.gjd", NULL, -1),
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
},
- kGroovieTLC, 1
+ kGroovieTLC
},
- {AD_TABLE_END_MARKER, kGroovieT7G, 0}
+ {AD_TABLE_END_MARKER, kGroovieT7G}
};
static const char *directoryGlobs[] = {
"MIDI",
+ "GROOVIE",
+ "MEDIA",
0
};
diff --git a/engines/groovie/detection.h b/engines/groovie/detection.h
index 16efa4af30..a321d0e26e 100644
--- a/engines/groovie/detection.h
+++ b/engines/groovie/detection.h
@@ -39,7 +39,6 @@ struct GroovieGameDescription {
ADGameDescription desc;
EngineVersion version; // Version of the engine
- int indexEntry; // The index of the entry in disk.1 for V2 games
};
} // End of namespace Groovie
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 530ec971b4..f362836b53 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -210,42 +210,14 @@ Common::Error GroovieEngine::run() {
syncSoundSettings();
// Get the name of the main script
- Common::String filename = _gameDescription->desc.filesDescriptions[0].fileName;
+ Common::String filename;
if (_gameDescription->version == kGroovieT7G) {
+ filename = "script.grv";
// Run The 7th Guest's demo if requested
if (ConfMan.hasKey("demo_mode") && ConfMan.getBool("demo_mode"))
filename = "demo.grv";
- else if (getPlatform() == Common::kPlatformMacintosh)
- filename = "script.grv"; // Stored inside the executable's resource fork
} else {
- // Open the disk index
- Common::File disk;
- if (!disk.open(filename)) {
- error("Couldn't open %s", filename.c_str());
- return Common::kNoGameDataFoundError;
- }
-
- // Search the entry
- bool found = false;
- int index = 0;
- while (!found && !disk.eos()) {
- Common::String line = disk.readLine();
- if (line.hasPrefix("title: ")) {
- // A new entry
- index++;
- } else if (line.hasPrefix("boot: ") && index == _gameDescription->indexEntry) {
- // It's the boot of the entry we're looking for,
- // get the script filename
- filename = line.c_str() + 6;
- found = true;
- }
- }
-
- // Couldn't find the entry
- if (!found) {
- error("Couldn't find entry %d in %s", _gameDescription->indexEntry, filename.c_str());
- return Common::kUnknownError;
- }
+ filename = _gameDescription->desc.filesDescriptions[0].fileName;
}
// Check the script file extension
diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp
index b92a0b5f57..3023df1c67 100644
--- a/engines/groovie/resource.cpp
+++ b/engines/groovie/resource.cpp
@@ -47,11 +47,11 @@ Common::SeekableReadStream *ResMan::open(uint32 fileRef) {
return NULL;
}
- debugC(1, kDebugResource, "Groovie::Resource: Opening resource 0x%04X (%s, %d, %d)", fileRef, _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size);
+ debugC(1, kDebugResource, "Groovie::Resource: Opening resource 0x%04X (%s, %d, %d, %d)", fileRef, _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size, resInfo.disks);
// Does it exist?
if (!Common::File::exists(_gjds[resInfo.gjd])) {
- error("Groovie::Resource: %s not found", _gjds[resInfo.gjd].c_str());
+ error("Groovie::Resource: %s not found (resInfo.disks: %d)", _gjds[resInfo.gjd].c_str(), resInfo.disks);
return NULL;
}
Commit: 70386000b62fabf478a09517f9baa9718dccc879
https://github.com/scummvm/scummvm/commit/70386000b62fabf478a09517f9baa9718dccc879
Author: Die4Ever (30947252+Die4Ever at users.noreply.github.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: detection updates and cleanup
added The 11th Hour demos and mac versions
Changed paths:
engines/groovie/clangame.cpp
engines/groovie/clangame.h
engines/groovie/detection.cpp
engines/groovie/groovie.cpp
engines/groovie/tlcgame.cpp
engines/groovie/tlcgame.h
diff --git a/engines/groovie/clangame.cpp b/engines/groovie/clangame.cpp
index 451d345cdb..fc9c5b6a5b 100644
--- a/engines/groovie/clangame.cpp
+++ b/engines/groovie/clangame.cpp
@@ -25,7 +25,7 @@
namespace Groovie {
// This a list of files for background music. These list is hard-coded in the TLC player.
-const char * kClanMusicFiles[] = {"mbf_arb1.mpg", "mbf_arm1.mpg", "mbf_bal1.mpg", "mbf_c2p2.mpg", "act18mus.mpg", "act15mus.mpg", "act21mus.mpg",
+const char *kClanMusicFiles[] = {"mbf_arb1.mpg", "mbf_arm1.mpg", "mbf_bal1.mpg", "mbf_c2p2.mpg", "act18mus.mpg", "act15mus.mpg", "act21mus.mpg",
"act05mus.mpg", "act04mus.mpg", "act23mus.mpg", "act17mus.mpg", "act03mus.mpg", "act06mus.mpg", "act19mus.mpg",
"act07mus.mpg", "mbf_mne1.mpg", "act24mus.mpg", "act24mus.mpg", "act14mus.mpg", "act20mus.mpg", "act15mus.mpg",
"act13mus.mpg", "act08mus.mpg", "mbf_uph1.mpg", "mbf_uph1.mpg", "act19mus.mpg", "mbf_bol1.mpg", "mbf_cbk1.mpg",
@@ -36,7 +36,7 @@ const char * kClanMusicFiles[] = {"mbf_arb1.mpg", "mbf_arm1.mpg", "mbf_bal1.mpg"
"mbf_c3p2.mpg", "mbf_c3p1.mpg", "act25mus.mpg", "mbf_c4p2.mpg", "mbf_c4p1.mpg"};
// Gets the filename of the background music file.
-const char* ClanGame::getClanMusicFilename(int musicId) {
+const char *ClanGame::getClanMusicFilename(int musicId) {
return kClanMusicFiles[musicId];
}
diff --git a/engines/groovie/clangame.h b/engines/groovie/clangame.h
index 64b131cb65..1732dcefd8 100644
--- a/engines/groovie/clangame.h
+++ b/engines/groovie/clangame.h
@@ -27,7 +27,7 @@ namespace Groovie {
class ClanGame {
public:
- static const char* getClanMusicFilename(int musicId);
+ static const char *getClanMusicFilename(int musicId);
};
} // namespace Groovie
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index ce3bb43b1f..ae381ccc17 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -105,6 +105,7 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieT7G
},
+#ifdef ENABLE_GROOVIE2
// The 11th Hour DOS/Windows English (Available on Steam)
{
{
@@ -117,30 +118,138 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieT11H
},
- // The Making of The 11th Hour English
+ // The 11th Hour Mac English
+ {
+ {
+ "11h", "",
+ AD_ENTRY2s("script.grv", "bdb9a783d4debe477ac3856adc454c17", 62447,
+ "The 11th Hour Installer", "bcdb4040b27f15b18f39fb9e496d384a", 1002987),
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
+ GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
+ },
+ kGroovieT11H
+ },
+
+ // The 11th Hour Mac English (Digital)
+ {
+ {
+ "11h", "Digital",
+ AD_ENTRY2s("script.grv", "bdb9a783d4debe477ac3856adc454c17", 62447,
+ "el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
+ GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
+ },
+ kGroovieT11H
+ },
+
+ // The 11th Hour DOS Interactive Demo English https://archive.org/details/11th_Hour_demo
+ {
+ {
+ "11h", "Interactive Demo",
+ AD_ENTRY2s("demo.grv", "5faec559b9abf18cf143751b420208dc", 15991,
+ "dvmod1a.gjd", "e304fe68f95c54fc82d785768e372892", 8068568),
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE,
+ GUIO5(GUIO_NOLAUNCHLOAD, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ },
+ kGroovieT11H
+ },
+
+ // The 11th Hour DOS Interactive Demo English (packaged with the Non-Interactive Demo) https://archive.org/details/11HDEMO
+ {
+ {
+ "11h", "Interactive Demo",
+ AD_ENTRY2s("demo.grv", "824b1a051f841a50ab7a6b4c10180bbc", 15898,
+ "dvmod1a.gjd", "e304fe68f95c54fc82d785768e372892", 8068568),
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE,
+ GUIO5(GUIO_NOLAUNCHLOAD, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ },
+ kGroovieT11H
+ },
+
+ // The 11th Hour DOS Non-Interactive Demo English https://archive.org/details/11HDEMO
+ {
+ {
+ "11h", "Non-Interactive Demo",
+ AD_ENTRY2s("niloop.grv", "b4c35a2a6ebaf72fbd830b590d48f8ea", 456,
+ "dvmod1b.gjd", "43eb268ef6d64a75b9846df5be453d30", 11264100),
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE,
+ GUIO5(GUIO_NOLAUNCHLOAD, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ },
+ kGroovieT11H
+ },
+
+ // The Making of The 11th Hour DOS/Windows English
{
{
"11h", "Making Of",
AD_ENTRY2s("makingof.grv", "12e1e5eef2c7a9536cd12ac800b31408", 994,
- "atpuz.gjd", NULL, -1),
+ "zmakd2a.gjd", NULL, -1),
Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
},
kGroovieT11H
},
- // Clandestiny Trailer English
+ // The Making of The 11th Hour Macintosh English
+ {
+ {
+ "11h", "Making Of",
+ AD_ENTRY2s("makingof.grv", "12e1e5eef2c7a9536cd12ac800b31408", 994,
+ "The 11th Hour Installer", "bcdb4040b27f15b18f39fb9e496d384a", 1002987),
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
+ GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ },
+ kGroovieT11H
+ },
+
+ // The Making of The 11th Hour Macintosh English (Digital)
+ {
+ {
+ "11h", "Making Of (Digital)",
+ AD_ENTRY2s("makingof.grv", "12e1e5eef2c7a9536cd12ac800b31408", 994,
+ "el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
+ GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ },
+ kGroovieT11H
+ },
+
+ // Clandestiny Trailer DOS/Windows English
{
{
"clandestiny", "Trailer",
AD_ENTRY2s("trailer.grv", "a7c8bdc4e8bff621f4f50928a95eaaba", 6,
"atpuz.gjd", NULL, -1),
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE,
GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
},
kGroovieCDY
},
+ // Clandestiny Trailer Macintosh English
+ {
+ {
+ "clandestiny", "Trailer",
+ AD_ENTRY2s("trailer.grv", "a7c8bdc4e8bff621f4f50928a95eaaba", 6,
+ "The 11th Hour Installer", "bcdb4040b27f15b18f39fb9e496d384a", 1002987),
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_DEMO | ADGF_UNSTABLE,
+ GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ },
+ kGroovieCDY
+ },
+
+ // Clandestiny Trailer Macintosh English (Digital)
+ {
+ {
+ "clandestiny", "Trailer (Digital)",
+ AD_ENTRY2s("trailer.grv", "a7c8bdc4e8bff621f4f50928a95eaaba", 6,
+ "el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
+ Common::EN_ANY, Common::kPlatformMacintosh, ADGF_DEMO | ADGF_UNSTABLE,
+ GUIO4(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT)
+ },
+ kGroovieCDY
+ },
+
// Clandestiny PC English
{
{
@@ -159,7 +268,7 @@ static const GroovieGameDescription gameDescriptions[] = {
"clandestiny", "",
AD_ENTRY2s("clanmain.grv", "dd424120fa1daa9d6b576d0ba22a4936", 54253,
"ACT01MUS.m4a", NULL, -1),
- Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
+ Common::EN_ANY, Common::kPlatformIOS, ADGF_UNSTABLE,
GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
},
kGroovieCDY
@@ -188,6 +297,7 @@ static const GroovieGameDescription gameDescriptions[] = {
},
kGroovieTLC
},
+#endif
{AD_TABLE_END_MARKER, kGroovieT7G}
};
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index f362836b53..e3f259ef75 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -221,7 +221,7 @@ Common::Error GroovieEngine::run() {
}
// Check the script file extension
- if (!filename.hasSuffix(".grv")) {
+ if (!filename.hasSuffixIgnoreCase(".grv")) {
error("%s isn't a valid script filename", filename.c_str());
return Common::kUnknownError;
}
diff --git a/engines/groovie/tlcgame.cpp b/engines/groovie/tlcgame.cpp
index 214cc92300..efcd14b200 100644
--- a/engines/groovie/tlcgame.cpp
+++ b/engines/groovie/tlcgame.cpp
@@ -34,7 +34,7 @@
namespace Groovie {
// This a list of files for background music. These list is hard-coded in the TLC player.
-const char * kTlcMusicFiles[] = {"ep01epm.mpg", "ep01tatm.mpg", "amb_hs.mpg", "amb_mr.mpg", "amb_kr.mpg", "amb_mo.mpg", "music_rc.mpg", "amb_ds.mpg", "amb_ds3.mpg",
+const char *kTlcMusicFiles[] = {"ep01epm.mpg", "ep01tatm.mpg", "amb_hs.mpg", "amb_mr.mpg", "amb_kr.mpg", "amb_mo.mpg", "music_rc.mpg", "amb_ds.mpg", "amb_ds3.mpg",
"amb_jr.mpg", "amb_mr4.mpg", "amb_jr4.mpg", "amb_jr2.mpg", "amb_kr2.mpg", "amb_mr2.mpg", "amb_br.mpg", "amb_ds2.mpg", "amb_jr3.mpg",
"amb_ds4.mpg", "amb_kr3.mpg", "amb_to1.mpg", "amb_to2.mpg", "ep02epm.mpg", "ep02tatm.mpg", "ep03epm.mpg", "ep03tatm.mpg", "ep04epm.mpg",
"ep04tatm.mpg", "ep05epm.mpg", "ep05tatm.mpg", "ep06epm.mpg", "ep06tatm.mpg", "ep07epm.mpg", "ep07tatm.mpg", "ep08epm.mpg", "ep08tatm.mpg",
@@ -84,7 +84,7 @@ uint16 inline TlcGame::getScriptVar16(uint16 var) {
}
// Gets the filename of the background music file.
-const char* TlcGame::getTlcMusicFilename(int musicId) {
+const char *TlcGame::getTlcMusicFilename(int musicId) {
return kTlcMusicFiles[musicId];
}
diff --git a/engines/groovie/tlcgame.h b/engines/groovie/tlcgame.h
index 09c76cae80..e652ea5de6 100644
--- a/engines/groovie/tlcgame.h
+++ b/engines/groovie/tlcgame.h
@@ -74,7 +74,7 @@ public:
TlcGame();
~TlcGame();
- static const char* getTlcMusicFilename(int musicId);
+ static const char *getTlcMusicFilename(int musicId);
/**
* Sets a pointer to the script variables. This makes it easier if we want
Commit: 1af1d35540cfdba47064602f64fa2a1527d3435e
https://github.com/scummvm/scummvm/commit/1af1d35540cfdba47064602f64fa2a1527d3435e
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix detection for T7G Mac
groovie.cpp requires the main grv file to be the first file in the game description
Changed paths:
engines/groovie/detection.cpp
engines/groovie/script.cpp
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index ae381ccc17..868c29150a 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -58,7 +58,8 @@ static const PlainGameDescriptor groovieGames[] = {
};
static const GroovieGameDescription gameDescriptions[] = {
-
+ // groovie.cpp requires the first file to be the main .grv file
+
// The 7th Guest DOS English
{
{
@@ -74,7 +75,8 @@ static const GroovieGameDescription gameDescriptions[] = {
{
{
"t7g", "",
- AD_ENTRY1s("T7GMac", "acdc4a58dd3f007f65e99b99d78e0bce", 1814029),
+ AD_ENTRY2s("script.grv", NULL, -1,
+ "T7GMac", "acdc4a58dd3f007f65e99b99d78e0bce", 1814029),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK,
GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED)
},
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 7bd9709cf7..f28208b67b 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -1971,7 +1971,7 @@ void Script::o2_vdxtransition() {
void Script::o2_savescreen() {
uint16 val = readScript16bits();
- // TODO: Parameter
+ // TODO: Parameter and cleanup
if (val)
warning("Groovie::Script: o2_copyscreentobg: Param is %d", val);
@@ -1987,7 +1987,7 @@ void Script::o2_savescreen() {
void Script::o2_restorescreen() {
uint16 val = readScript16bits();
- // TODO: Parameter
+ // TODO: Parameter and cleanup
if (val)
warning("Groovie::Script: o2_copybgtoscreen: Param is %d", val);
Commit: 328a47dffa3bff12caf2bc51681d8f926da3032a
https://github.com/scummvm/scummvm/commit/328a47dffa3bff12caf2bc51681d8f926da3032a
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: improve cursor/fades fps
Improves the fps of mouse cursor movements without messing up the animation speed of the cursors. Also improves the fps of fade ins and fade outs.
Changed paths:
engines/groovie/cursor.cpp
engines/groovie/graphics.cpp
engines/groovie/groovie.cpp
engines/groovie/roq.cpp
diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp
index 114d8c570b..b09fbb382b 100644
--- a/engines/groovie/cursor.cpp
+++ b/engines/groovie/cursor.cpp
@@ -72,7 +72,7 @@ void GrvCursorMan::setStyle(uint8 newStyle) {
void GrvCursorMan::animate() {
if (_lastTime) {
int newTime = _syst->getMillis();
- if (_lastTime - newTime >= 75) {
+ if (newTime - _lastTime >= 66) {
_lastFrame++;
_lastFrame %= _cursor->getFrames();
_cursor->showFrame(_lastFrame);
diff --git a/engines/groovie/graphics.cpp b/engines/groovie/graphics.cpp
index 8a377371ef..a570dde85b 100644
--- a/engines/groovie/graphics.cpp
+++ b/engines/groovie/graphics.cpp
@@ -51,7 +51,7 @@ void GraphicsMan::update() {
uint32 time = _vm->_system->getMillis() - _fadeStartTime;
// Scale the time
- int step = (time * 15 << 3) / 1000;
+ int step = (time * 20 << 3) / 1000;
if (step > 256) {
step = 256;
}
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index e3f259ef75..a3f3ceec8c 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -240,7 +240,7 @@ Common::Error GroovieEngine::run() {
}
// Game timer counter
- uint16 tmr = 0;
+ int tmr = 0;
// Check that the game files and the audio tracks aren't together run from
// the same cd
@@ -306,19 +306,20 @@ Common::Error GroovieEngine::run() {
// Still waiting for input, just update the mouse, game timer and then wait a bit more
_grvCursorMan->animate();
_system->updateScreen();
- tmr++;
+
+ int newTime = _system->getMillis();
// Wait a little bit between increments. While mouse is moving, this triggers
// only negligably slower.
- if (tmr > 4) {
+ if ( newTime - tmr >= 200) {
_script->timerTick();
- tmr = 0;
+ tmr = newTime;
}
- _system->delayMillis(50);
+ _system->delayMillis(5);
} else if (_graphicsMan->isFading()) {
// We're waiting for a fading to end, let the CPU rest
// for a while and continue
- _system->delayMillis(30);
+ _system->delayMillis(5);
} else {
// Everything's fine, execute another script step
_script->step();
diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp
index 1e34aad9ee..e610149b26 100644
--- a/engines/groovie/roq.cpp
+++ b/engines/groovie/roq.cpp
@@ -76,13 +76,11 @@ static inline void copyPixelIfAlpha(byte *dst, const byte *src) {
static inline void copyPixelWithA(byte *dst, const byte *src) {
if (src[kAIndex] == 255) {
copyPixel(dst, src);
- } else {
- if (src[kAIndex] > 0) {
- dst[kAIndex] = MAX(src[kAIndex], dst[kAIndex]);
- dst[kRIndex] = ((src[kRIndex] * src[kAIndex]) + dst[kRIndex] * (255 - src[kAIndex])) >> 8;
- dst[kGIndex] = ((src[kGIndex] * src[kAIndex]) + dst[kGIndex] * (255 - src[kAIndex])) >> 8;
- dst[kBIndex] = ((src[kBIndex] * src[kAIndex]) + dst[kBIndex] * (255 - src[kAIndex])) >> 8;
- }
+ } else if (src[kAIndex] > 0) {
+ dst[kAIndex] = MAX(src[kAIndex], dst[kAIndex]);
+ dst[kRIndex] = ((src[kRIndex] * src[kAIndex]) + dst[kRIndex] * (255 - src[kAIndex])) >> 8;
+ dst[kGIndex] = ((src[kGIndex] * src[kAIndex]) + dst[kGIndex] * (255 - src[kAIndex])) >> 8;
+ dst[kBIndex] = ((src[kBIndex] * src[kAIndex]) + dst[kBIndex] * (255 - src[kAIndex])) >> 8;
}
// In case of alpha == 0 just do not copy
}
@@ -225,7 +223,6 @@ void ROQPlayer::buildShowBuf() {
byte *prv = (byte *)_prevBuf->getBasePtr((_restoreArea->left - _origX) / _scaleX, (line - _origY) / _scaleY);
byte *ovr = (byte *)_overBuf->getBasePtr(_restoreArea->left, line);
- //memcpy(dst, src, width * _bg->format.bytesPerPixel);
for (int i = 0; i < width; i++) {
if (prv[kAIndex] != 0) {
copyPixel(dst, src);
@@ -267,13 +264,14 @@ void ROQPlayer::buildShowBuf() {
int startX, startY, stopX, stopY;
calcStartStop(startX, stopX, _origX, _screen->w);
calcStartStop(startY, stopY, _origY, _screen->h);
+ assert(destBuf->format == _currBuf->format);
+ assert(destBuf->format == _overBuf->format);
+ assert(destBuf->format.bytesPerPixel == 4);
for (int line = startY; line < stopY; line++) {
byte *in = (byte *)_currBuf->getBasePtr(MAX(0, -_origX) / _scaleX, (line - _origY) / _scaleY);
byte *inOvr = (byte *)_overBuf->getBasePtr(startX, line);
byte *out = (byte *)destBuf->getBasePtr(startX, line + destOffset);
- assert(destBuf->format == _currBuf->format);
- assert(destBuf->format.bytesPerPixel == 4);
for (int x = startX; x < stopX; x++) {
if (destBuf == _overBuf) {
Commit: 5d4303566b64a18edda1d3865316ed6f768ca23e
https://github.com/scummvm/scummvm/commit/5d4303566b64a18edda1d3865316ed6f768ca23e
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: tweak script timer
Changed paths:
engines/groovie/groovie.cpp
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index a3f3ceec8c..d11aad00fc 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -307,19 +307,19 @@ Common::Error GroovieEngine::run() {
_grvCursorMan->animate();
_system->updateScreen();
- int newTime = _system->getMillis();
// Wait a little bit between increments. While mouse is moving, this triggers
// only negligably slower.
- if ( newTime - tmr >= 200) {
+ if (tmr >= 250) {
_script->timerTick();
- tmr = newTime;
+ tmr = 0;
}
- _system->delayMillis(5);
+ _system->delayMillis(10);
+ tmr += 10;
} else if (_graphicsMan->isFading()) {
// We're waiting for a fading to end, let the CPU rest
// for a while and continue
- _system->delayMillis(5);
+ _system->delayMillis(10);
} else {
// Everything's fine, execute another script step
_script->step();
Commit: 1a9cd3e900800dd3375341863148e1089518ed1a
https://github.com/scummvm/scummvm/commit/1a9cd3e900800dd3375341863148e1089518ed1a
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: fix uses of ENABLE_GROOVIE2
Fixing compiler errors when groovie2 was disabled
Changed paths:
engines/groovie/detection.cpp
engines/groovie/metaengine.cpp
engines/groovie/music.cpp
engines/groovie/script.cpp
engines/groovie/t11hgame.h
engines/groovie/tlcgame.h
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index 868c29150a..abb15bfcfc 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -107,7 +107,6 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieT7G
},
-#ifdef ENABLE_GROOVIE2
// The 11th Hour DOS/Windows English (Available on Steam)
{
{
@@ -299,7 +298,6 @@ static const GroovieGameDescription gameDescriptions[] = {
},
kGroovieTLC
},
-#endif
{AD_TABLE_END_MARKER, kGroovieT7G}
};
diff --git a/engines/groovie/metaengine.cpp b/engines/groovie/metaengine.cpp
index 7f7837b30f..06726807a5 100644
--- a/engines/groovie/metaengine.cpp
+++ b/engines/groovie/metaengine.cpp
@@ -48,7 +48,7 @@ public:
Common::Error GroovieMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
#ifndef ENABLE_GROOVIE2
- if (((const GroovieGameDescription *)gd)->version == kGroovieV2)
+ if (((const GroovieGameDescription *)gd)->version != kGroovieT7G)
return Common::Error(Common::kUnsupportedGameidError, _s("GroovieV2 support is not compiled in"));
#endif
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index bb10ec760f..35d6bcadd5 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -775,7 +775,11 @@ void MusicPlayerTlc::unload() {
}
Common::String MusicPlayerTlc::getFilename(uint32 fileref) {
+#ifdef ENABLE_GROOVIE2
return TlcGame::getTlcMusicFilename(fileref);
+#else
+ return "";
+#endif
}
bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
@@ -816,7 +820,11 @@ bool MusicPlayerTlc::load(uint32 fileref, bool loop) {
}
Common::String MusicPlayerClan::getFilename(uint32 fileref) {
+#ifdef ENABLE_GROOVIE2
return ClanGame::getClanMusicFilename(fileref);
+#else
+ return "";
+#endif
}
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index f28208b67b..2134f932c3 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -809,7 +809,9 @@ void Script::o_inputloopstart() { //0x0B
// For TLC the regions for many questions are in an extra database. Reset internal region counters
if (_version == kGroovieTLC && _tlcGame != NULL) {
+#ifdef ENABLE_GROOVIE2
_tlcGame->getRegionRewind();
+#endif
}
// Reset the input action and the mouse cursor
@@ -862,10 +864,12 @@ void Script::o_hotspot_rect() {
// TLC: The regions for many questions are in an extra database
if (_version == kGroovieTLC && left == 0 && top == 0 && right == 0 && bottom == 0 && _tlcGame != NULL) {
+#ifdef ENABLE_GROOVIE2
if (_tlcGame->getRegionNext(left, top, right, bottom) < 0) {
debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d SKIPPED", left, top, right, bottom, address, cursor);
return;
}
+#endif
}
debugC(5, kDebugScript, "Groovie::Script: HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d", left, top, right, bottom, address, cursor);
@@ -2011,6 +2015,7 @@ void Script::o2_gamespecial() {
uint8 arg = readScript8bits();
switch (_version) {
+#ifdef ENABLE_GROOVIE2
case kGroovieTLC:
if (_tlcGame == NULL) {
_tlcGame = new TlcGame();
@@ -2081,7 +2086,7 @@ void Script::o2_gamespecial() {
debugC(1, kDebugScript, "Groovie::Script: Op42 (0x%02X): T11H Invalid -> NOP", arg);
}
break;
-
+#endif
default:
debugC(1, kDebugScript, "Groovie::Script: GameSpecial (0x%02X)", arg);
warning("Groovie::Script: OpCode 0x42 for (GameSpecial) current game not implemented yet.");
diff --git a/engines/groovie/t11hgame.h b/engines/groovie/t11hgame.h
index 897cda2486..9b2053a8c2 100644
--- a/engines/groovie/t11hgame.h
+++ b/engines/groovie/t11hgame.h
@@ -32,6 +32,7 @@ class GroovieEngine;
class T11hGame {
public:
+#ifdef ENABLE_GROOVIE2
T11hGame();
~T11hGame();
/**
@@ -55,6 +56,7 @@ private:
uint16 inline getScriptVar16(uint16 var);
byte *_scriptVariables;
static const byte kGalleryLinks[21][10];
+#endif
};
} // End of Groovie namespace
diff --git a/engines/groovie/tlcgame.h b/engines/groovie/tlcgame.h
index e652ea5de6..da3506644e 100644
--- a/engines/groovie/tlcgame.h
+++ b/engines/groovie/tlcgame.h
@@ -71,6 +71,7 @@ struct TlcTatQuestions {
class TlcGame
{
public:
+#ifdef ENABLE_GROOVIE2
TlcGame();
~TlcGame();
@@ -190,6 +191,7 @@ private:
TlcTatHeader *_tatHeaders;
TlcTatQuestions *_tatQuestions;
// uint8 _tatCoeffs[15][16];
+#endif
};
} // End of Groovie namespace
Commit: f6c50c7238012bd77e9818c13fa2dcff40c0184c
https://github.com/scummvm/scummvm/commit/f6c50c7238012bd77e9818c13fa2dcff40c0184c
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: updates to detection and adding demos
Changed paths:
engines/groovie/detection.cpp
engines/groovie/groovie.cpp
diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp
index abb15bfcfc..ffd3f8bf86 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -58,7 +58,7 @@ static const PlainGameDescriptor groovieGames[] = {
};
static const GroovieGameDescription gameDescriptions[] = {
- // groovie.cpp requires the first file to be the main .grv file
+ // groovie.cpp requires the first file to be the main .grv file for v2 games, might as well stick to that convention for v1 games from now on too
// The 7th Guest DOS English
{
@@ -131,10 +131,10 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieT11H
},
- // The 11th Hour Mac English (Digital)
+ // The 11th Hour Mac English (Installed)
{
{
- "11h", "Digital",
+ "11h", "Installed",
AD_ENTRY2s("script.grv", "bdb9a783d4debe477ac3856adc454c17", 62447,
"el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
@@ -203,10 +203,10 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieT11H
},
- // The Making of The 11th Hour Macintosh English (Digital)
+ // The Making of The 11th Hour Macintosh English (Installed)
{
{
- "11h", "Making Of (Digital)",
+ "11h", "Making Of (Installed)",
AD_ENTRY2s("makingof.grv", "12e1e5eef2c7a9536cd12ac800b31408", 994,
"el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
@@ -239,10 +239,10 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieCDY
},
- // Clandestiny Trailer Macintosh English (Digital)
+ // Clandestiny Trailer Macintosh English (Installed)
{
{
- "clandestiny", "Trailer (Digital)",
+ "clandestiny", "Trailer (Installed)",
AD_ENTRY2s("trailer.grv", "a7c8bdc4e8bff621f4f50928a95eaaba", 6,
"el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_DEMO | ADGF_UNSTABLE,
@@ -251,6 +251,18 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieCDY
},
+ // Clandestiny PC Demo English https://archive.org/details/Clandestiny_demo
+ {
+ {
+ "clandestiny", "Demo",
+ AD_ENTRY2s("clandemo.grv", "faa863738da1c93673ed58a4b9597a63", 6744,
+ "cddemo.gjd", NULL, -1),
+ Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE,
+ GUIO3(GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_NOASPECT)
+ },
+ kGroovieCDY
+ },
+
// Clandestiny PC English
{
{
@@ -299,6 +311,30 @@ static const GroovieGameDescription gameDescriptions[] = {
kGroovieTLC
},
+ // Tender Loving Care PC Demo German https://archive.org/details/Tender_Loving_Care_demo
+ {
+ {
+ "tlc", "Demo",
+ AD_ENTRY2s("tlcmain.grv", "6ec818f595eedca6570280af0c681642", 17361,
+ "tlcnav.gjd", NULL, -1),
+ Common::DE_DEU, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE,
+ GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
+ },
+ kGroovieTLC
+ },
+
+ // Tender Loving Care PC Trailer https://archive.org/details/Tender_Loving_Care_demo
+ {
+ {
+ "tlc", "Trailer",
+ AD_ENTRY2s("preview.grv", "d95401509a0ef251e8c340737edf728c", 19,
+ "drama1.gjd", NULL, -1),
+ Common::UNK_LANG, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE,
+ GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
+ },
+ kGroovieTLC
+ },
+
{AD_TABLE_END_MARKER, kGroovieT7G}
};
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index d11aad00fc..75356b69a1 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -244,7 +244,7 @@ Common::Error GroovieEngine::run() {
// Check that the game files and the audio tracks aren't together run from
// the same cd
- if (getPlatform() != Common::kPlatformIOS && _gameDescription->version != kGroovieTLC) {
+ if (getPlatform() != Common::kPlatformIOS && _gameDescription->version == kGroovieT7G) {
if (!existExtractedCDAudioFiles()
&& !isDataAndCDAudioReadFromSameCD()) {
warnMissingExtractedCDAudio();
Commit: b09a33092111f61f475ea079807921a5fcced7ce
https://github.com/scummvm/scummvm/commit/b09a33092111f61f475ea079807921a5fcced7ce
Author: Die4Ever (30947252+Die4Ever at users.noreply.github.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: tweak _waitingForInput loop
fixes the end of The 11th Hour where there's supposed to be a timeout but it didn't actually trigger until you moved the mouse
also the script timer has been further slowed down to 1000ms because that appears to be what T7G uses, both from looking at the exe and also from observing the game
Changed paths:
engines/groovie/groovie.cpp
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 75356b69a1..5d54e8b9dd 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -302,25 +302,27 @@ Common::Error GroovieEngine::run() {
continue;
}
- if (_waitingForInput) {
- // Still waiting for input, just update the mouse, game timer and then wait a bit more
- _grvCursorMan->animate();
- _system->updateScreen();
-
- // Wait a little bit between increments. While mouse is moving, this triggers
- // only negligably slower.
- if (tmr >= 250) {
- _script->timerTick();
- tmr = 0;
- }
-
- _system->delayMillis(10);
- tmr += 10;
- } else if (_graphicsMan->isFading()) {
+ if (_graphicsMan->isFading()) {
// We're waiting for a fading to end, let the CPU rest
// for a while and continue
_system->delayMillis(10);
} else {
+ if (_waitingForInput) {
+ // Still waiting for input, just update the mouse, game timer and then wait a bit more
+ _grvCursorMan->animate();
+ _system->updateScreen();
+
+ // Wait a little bit between increments. While mouse is moving, this triggers
+ // only negligably slower.
+ if (tmr >= 1000) {
+ _script->timerTick();
+ tmr = 0;
+ }
+
+ _system->delayMillis(10);
+ tmr += 10;
+ }
+
// Everything's fine, execute another script step
_script->step();
}
Commit: 9b490a0864d1bf25510ddc1fb598974f8bc97adf
https://github.com/scummvm/scummvm/commit/9b490a0864d1bf25510ddc1fb598974f8bc97adf
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-09-15T19:13:57+03:00
Commit Message:
GROOVIE: unset _waitingForInput and cleanup
Unset _waitingForInput to make the game more responsive. Also some cleanup of old commented out code.
Changed paths:
engines/groovie/groovie.cpp
engines/groovie/music.cpp
engines/groovie/script.cpp
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 5d54e8b9dd..d66ff7696c 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -321,6 +321,11 @@ Common::Error GroovieEngine::run() {
_system->delayMillis(10);
tmr += 10;
+
+ // the script doesn't unset _waitingForInput
+ // so we unset it here in order to let the script run as many steps as it needs to
+ // this makes the game more responsive
+ _waitingForInput = false;
}
// Everything's fine, execute another script step
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index 35d6bcadd5..5112e38dd2 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -190,6 +190,7 @@ bool MusicPlayer::play(uint32 fileref, bool loop) {
void MusicPlayer::stop() {
_backgroundFileRef = 0;
+ setBackgroundDelay(0);
unload();
}
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index 2134f932c3..d81863f074 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -1462,27 +1462,21 @@ void Script::o_copyrecttobg() { // 0x37
right = 640 - 1;
}
- uint16 i, width = right - left, height = bottom - top;
+ uint16 width = right - left, height = bottom - top;
uint32 offset = 0;
- byte *fg, *bg;
uint32 pitch = _vm->_graphicsMan->_foreground.pitch;
debugC(1, kDebugScript, "Groovie::Script: COPYRECT((%d,%d)->(%d,%d))", left, top, right, bottom);
debugC(2, kDebugVideo, "Groovie::Script: @0x%04X: COPYRECT((%d,%d)->(%d,%d))",_currentInstruction-9, left, top, right, bottom);
- fg = (byte *)_vm->_graphicsMan->_foreground.getBasePtr(left, top - baseTop);
- bg = (byte *)_vm->_graphicsMan->_background.getBasePtr(left, top - baseTop);
- for (i = 0; i < height; i++) {
+ byte *fg = (byte *)_vm->_graphicsMan->_foreground.getBasePtr(left, top - baseTop);
+ byte *bg = (byte *)_vm->_graphicsMan->_background.getBasePtr(left, top - baseTop);
+ for (uint16 i = 0; i < height; i++) {
memcpy(bg + offset, fg + offset, width * _vm->_graphicsMan->_foreground.format.bytesPerPixel);
offset += pitch;
}
- // _vm->_graphicsMan->_background.copyFrom(_vm->_graphicsMan->_foreground);
- //{
- // Graphics::Surface *_bg = &_vm->_graphicsMan->_background;
- // _vm->_system->copyRectToScreen(_bg->getPixels(), _bg->pitch, 0, (_vm->_system->getHeight() - _bg->h) / 2, _bg->w, _bg->h);
- //}
- _vm->_system->copyRectToScreen(_vm->_graphicsMan->_background.getBasePtr(left, top - baseTop), pitch, left, top, width, height);
+ _vm->_system->copyRectToScreen(bg, pitch, left, top, width, height);
_vm->_graphicsMan->change();
}
@@ -1895,14 +1889,12 @@ void Script::o2_midicontrol() {
uint16 arg1 = readScript16bits();
uint16 arg2 = readScript16bits();
- // TODO: see if we need to revisit the commented code here, maybe @Alphard-o can help
switch (arg1) {
case 0:
// Stop Playback
debugC(1, kDebugScript, "Groovie::Script: MIDI %d:Stop: %d", arg1, arg2);
_vm->_musicPlayer->stop();
_vm->_soundQueue.stopAll();
- //_vm->_musicPlayer->setBackgroundDelay(0);
break;
case 1:
@@ -1910,8 +1902,6 @@ void Script::o2_midicontrol() {
debugC(1, kDebugScript, "Groovie::Script: MIDI %d: Play song %d", arg1, arg2);
_vm->_musicPlayer->playSong(arg2);
_vm->_musicPlayer->setUserVolume(100);
- //_vm->_musicPlayer->setBackgroundSong(arg2);
- //_vm->_musicPlayer->startBackground();
break;
case 3:
@@ -1975,13 +1965,10 @@ void Script::o2_vdxtransition() {
void Script::o2_savescreen() {
uint16 val = readScript16bits();
- // TODO: Parameter and cleanup
+ // TODO: Parameter
if (val)
warning("Groovie::Script: o2_copyscreentobg: Param is %d", val);
- // Graphics::Surface *screen = _vm->_system->lockScreen();
- // _vm->_graphicsMan->_background.copyFrom(screen->getSubArea(Common::Rect(0, 80, 640, 320)));
- // _vm->_system->unlockScreen();
_vm->_graphicsMan->saveScreen();
debugC(1, kDebugScript, "Groovie::Script: CopyScreenToBG3: 0x%04X", val);
@@ -1991,13 +1978,10 @@ void Script::o2_savescreen() {
void Script::o2_restorescreen() {
uint16 val = readScript16bits();
- // TODO: Parameter and cleanup
+ // TODO: Parameter
if (val)
warning("Groovie::Script: o2_copybgtoscreen: Param is %d", val);
- // Graphics::Surface *screen = _vm->_system->lockScreen();
- // _vm->_graphicsMan->_background.copyRectToSurface(*screen, 0, 80, Common::Rect(0, 0, 640, 320 - 80));
- // _vm->_system->unlockScreen();
_vm->_graphicsMan->restoreScreen();
debugC(1, kDebugScript, "Groovie::Script: CopyBG3ToScreen: 0x%04X", val);
More information about the Scummvm-git-logs
mailing list